Tech Stack Standards
All client sites use Astro 5/6 (not Next.js — that is for internal Boxi products only). Deployed on Vercel by default or Cloudflare Pages when required.
Stack Reference
Section titled “Stack Reference”| Layer | Vercel (default) | Cloudflare (when needed) |
|---|---|---|
| Framework | Astro 5/6, output: hybrid | Astro 5/6, output: hybrid |
| Adapter | @astrojs/vercel/serverless | @astrojs/cloudflare |
| Database | Neon (Postgres, Drizzle ORM) | Cloudflare D1 (SQLite, Drizzle) |
| Cache | Upstash Redis | Cloudflare KV |
| Storage | Vercel Blob | Cloudflare R2 (no egress fees) |
| Analytics | PostHog | PostHog |
| Email / Forms | Resend | Resend |
| CRM sync | Boxi App webhook | Boxi App webhook |
| Blog (agency writes) | Astro Content Collections | Astro Content Collections |
| Blog (client edits) | Keystatic → CloudCannon → Sanity | Keystatic → CloudCannon → Sanity |
| Package manager | bun | bun |
| Secrets | Doppler (per-client project) | Doppler (per-client project) |
Use Cloudflare only when: zero egress fees on storage are required (R2), site needs Workers/Durable Objects, or very high traffic at minimal cost.
Why Astro for Client Sites
Section titled “Why Astro for Client Sites”Community consensus in 2026 is unambiguous: Astro for content/marketing sites, Next.js for apps.
- 100/100 Lighthouse out of the box (static-first, zero client JS on marketing pages)
- Free hosting on Vercel hobby or Cloudflare Pages
- Agencies actively migrating 40+ WordPress/Webflow sites to Astro + Cloudflare at $0 hosting cost
- Next.js is over-engineered for blogs and landing pages
Output Mode
Section titled “Output Mode”All Boxi client sites use output: 'hybrid':
- Pages are static by default (best performance, cacheable)
/api/contactis always server-rendered (required for contact form)- Keystatic requires hybrid mode for its admin routes
output: 'static' cannot be used — it does not support API routes.
Doppler Secrets (per client)
Section titled “Doppler Secrets (per client)”# Always requiredRESEND_API_KEY=RESEND_FROM_EMAIL= # noreply@clientdomain.comCLIENT_NOTIFY_EMAIL= # owner@clientbusiness.com
# Full-service clients only (Boxi CRM sync)BOXI_APP_URL=https://app.boximarketing.comBOXI_WEBHOOK_SECRET= # openssl rand -hex 32BOXI_CLIENT_ID= # From Boxi App → Client profileRelated
Section titled “Related”- CMS Decision Tree — which CMS per client type
- Contact Forms — canonical 3-step form implementation
- Programmatic SEO — multi-location contractor sites