Multi-Client Astro

One Codebase.
Many Client Sites.

The hostname decides which tenant's content, theme, and navigation a visitor gets. Everything else is shared.

What it does

Hostname routing

Middleware maps the subdomain to a tenant slug, so acme.example.com and beta.example.com serve different content from one deployment.

Per-tenant theming

Colors, logo, and navigation come from one registry entry per tenant, applied as CSS custom properties rather than forked components.

MDX content

Pages are MDX files with Zod-checked frontmatter. Navigation is built from those files, so adding a page adds a nav entry.

Identity gating

Put a tenant behind Cloudflare Access and the app reads the signed-in email from the request headers. It never handles sign-in itself.

Edge rendering

Astro 4 in SSR mode on Cloudflare Pages Functions, so pages render at the edge close to the visitor.

Tenants

Tenants on this deployment are served from their own subdomains and resolved from the request hostname. The ?as=<slug> override is not available here — it works on localhost, and on a *.pages.dev host only when ALLOW_TENANT_OVERRIDE=true is set.

Run it yourself

Clone it, install, and run. No environment variables required.

git clone https://github.com/keyanfayaz/client-sites.git
cd client-sites
pnpm install
pnpm dev

Check out the README for full documentation.

Preview deployment detected. Robots are blocked via X-Robots-Tag: noindex.