- MDX 42.2%
- Astro 38.9%
- Vue 6.4%
- JavaScript 5.9%
- CSS 3.1%
- Other 3.5%
| .vscode | ||
| public | ||
| scripts | ||
| slides | ||
| src | ||
| .gitignore | ||
| .nvmrc | ||
| astro.config.mjs | ||
| CLAUDE.md | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| wrangler.toml | ||
Stalwart Website
The marketing site, documentation, and blog for Stalwart. Built with Astro 6 and Starlight; deployed as a static site to Cloudflare Pages.
Stack
- Marketing pages (
/,/pricing,/about,/legal/*, etc.) are Astro pages driven by YAML/Markdown content collections under src/content/pages/ and src/content/legal/. - Documentation (
/docs/...) is rendered by Starlight from src/content/docs/docs/. The previous release line lives at src/content/docs/docs/0.15/ and is served at/docs/0.15/.... - Blog (
/blog,/blog/<post>) is thestarlight-blogplugin reading posts from src/content/docs/blog/. - Search is Pagefind, the offline static-site
search baked into Starlight. The index is rebuilt on every
npm run build. No third-party service or API key needed. - Per-post OG images are generated by
astro-og-canvasat/og/blog/<slug>.pngand referenced from<meta property="og:image">on each blog post. - View Transitions (smooth cross-page nav) are enabled site-wide via
Astro's
<ClientRouter />.
Local development
Requirements: Node.js 20+ (set in package.json engines).
npm install # one-time, installs Astro + Starlight + plugins
npm run dev # http://127.0.0.1:8787 with hot reload
npm run dev watches every Markdown, Astro and YAML file. Edits reload in the
browser within a second; structural changes (new files, frontmatter schema
changes) may require a manual reload.
Other useful scripts:
npm run build # production build to dist/, runs link validation
npm run preview # serve dist/ at http://127.0.0.1:8787 to verify
Authoring docs
Drop new pages into src/content/docs/docs/<section>/<page>.md. Frontmatter
must include at least a title:. Optional helpful fields:
---
title: My new page
description: One-line summary used for SEO and search results.
sidebar:
order: 5 # position within the parent group
badge: New # appears in the sidebar
---
To rename a directory's sidebar label or change ordering, drop a _meta.yml
into that directory (starlight-auto-sidebar docs):
label: Storage settings
order: 5
Admonitions (notes, tips, warnings) use the same triple-colon syntax as before:
:::tip Enterprise feature
This feature ships with the Enterprise edition.
:::
Internal doc links use absolute paths without the .md suffix:
[Storage](/docs/storage/overview).
Authoring blog posts
Add src/content/docs/blog/<post-slug>.mdx (or a folder with index.mdx if
the post has its own assets). Required frontmatter:
---
title: Post title
date: 2026-05-01
authors: [mdecimus] # keys are defined in astro.config.mjs starlightBlog config
tags: [release, jmap]
excerpt: |
One paragraph teaser shown on the index, in tag pages, and in the RSS feed.
---
Reading time is computed automatically.
Deployment (Cloudflare Pages)
The site is a static export. Cloudflare Pages picks up the Astro project automatically; the only config needed in the dashboard is:
- Build command:
npm run build - Build output directory:
dist - Node version:
20(or newer)
wrangler.toml declares the same so wrangler pages deploy
works locally or from CI.
Static asset behaviour and redirects are controlled by:
- public/_headers: cache-control and security headers
- public/_redirects: Docusaurus-era URL redirects
- public/robots.txt: AI/search crawler policy
- public/llms.txt: curated machine-readable doc index
To deploy from your laptop (one-off):
npm run build
npx wrangler pages deploy dist --project-name stalwart-website
Repository layout
.
├── astro.config.mjs # Astro + Starlight integration config
├── src/
│ ├── content.config.ts # Astro content collection schemas
│ ├── content/
│ │ ├── docs/
│ │ │ ├── docs/ # current docs -> /docs/...
│ │ │ ├── docs/0.15/ # archived 0.15 -> /docs/0.15/...
│ │ │ └── blog/ # blog posts -> /blog/...
│ │ ├── pages/ # marketing pages (YAML)
│ │ └── legal/ # long-form legal pages (Markdown)
│ ├── components/ # Astro components shared by marketing + docs
│ │ ├── Header.astro # marketing nav
│ │ ├── Footer.astro # marketing footer
│ │ ├── StarlightHeader.astro # Starlight Header override -> Header
│ │ ├── StarlightFooter.astro # Starlight Footer override -> Footer
│ │ └── VersionPicker.astro # docs version dropdown
│ ├── layouts/ # marketing layouts (Base, LongForm)
│ ├── pages/ # marketing dynamic routes
│ └── styles/ # global tokens and Starlight overrides
├── public/ # static assets copied as-is to dist/
└── scripts/ # one-off migration scripts (kept for reference)
Things to know
- The
links-validatorplugin runs at the end ofnpm run buildand fails the build on broken internal links. Pre-existing broken links in/docs/0.15/**are excluded (seeastro.config.mjs); fix-forward only. - Mermaid diagrams (
```mermaid) are converted to client-rendered SVG via themermaidnpm package; the script is bundled into Starlight pages only. - The
.old/directory is the archived Docusaurus tree, kept out of git via.gitignoreuntil you choose to delete it.