Deployment
Every app in the Frequency monorepo deploys as its own Vercel project with its own domain, environment variables, and preview environments. This gives each site independent deployment lifecycles while sharing the same codebase.
Deployment Model
Brand Site
apps/public/brand
Brand guidelines and component showcase. Own Vercel project, own domain.
Public Template
apps/public/template-public
Public documentation template. Own Vercel project, own domain.
Standards
apps/private/standards
This site. Requires Supabase auth. Own Vercel project, own domain.
Private Template
apps/private/template-private
Authenticated documentation template. Own Vercel project, own domain.
Each app is a separate Vercel project with:
- Its own production domain
- Its own preview environments (per PR)
- Its own environment variables (though Supabase creds are shared)
- Independent deployment triggers and rollbacks
Quick Setup
The fastest path to deploying a new app:
/setup-project yourdomain.comThis automates all the steps below. For manual setup or understanding what happens under the hood, read on.
Step 1: Link to Vercel
Each app in the monorepo needs its own Vercel project:
# Navigate to the app directory
cd apps/private/standards
# Link to a new Vercel project
vercel link --yesThis creates .vercel/project.json with your org and project IDs.
Important: Repeat this for each app you want to deploy. Each app = one Vercel project.
Step 2: Add Custom Domain
vercel domains add standards.yourdomain.comStep 3: Configure DNS (Route 53)
Apex Domain (yourdomain.com)
| Record Type | Name | Value |
|---|---|---|
| A | @ | 76.76.21.21 |
Subdomains (app.yourdomain.com)
| Record Type | Name | Value |
|---|---|---|
| CNAME | standards | cname.vercel-dns.com |
| CNAME | brand | cname.vercel-dns.com |
PR Preview Wildcard
For automatic PR preview environments:
| Record Type | Name | Value |
|---|---|---|
| CNAME | *.branch | cname.vercel-dns.com |
Step 4: GitHub Secrets
Add these secrets to your GitHub repository for CI/CD:
| Secret | Source |
|---|---|
VERCEL_ORG_ID | .vercel/project.json → orgId |
VERCEL_PROJECT_ID | .vercel/project.json → projectId |
VERCEL_TOKEN | Vercel Settings → Tokens |
Note: If deploying multiple apps, you’ll need separate
VERCEL_PROJECT_IDvalues per app (store asVERCEL_PROJECT_ID_STANDARDS,VERCEL_PROJECT_ID_BRAND, etc.).
Step 5: Environment Variables
Add required environment variables for each Vercel project:
# Per-app: navigate to app dir first
cd apps/private/standards
vercel env add NEXT_PUBLIC_SUPABASE_URL
vercel env add NEXT_PUBLIC_SUPABASE_ANON_KEYEnvironment Scopes
Vercel supports three scopes per variable:
| Scope | When Used |
|---|---|
| Development | vercel dev locally |
| Preview | PR preview deployments |
| Production | Production deployments |
All apps share the same Supabase project, so the Supabase credentials are identical across apps and scopes.
Step 6: Deploy
# Production deployment
vercel --prod
# Preview deployment (automatic on PR)
vercelPR Preview Environments
Every pull request automatically gets a preview deployment:
- URL: Unique Vercel URL per deployment
- Deployed on: Every push to the PR branch
- Torn down: When the PR is merged or closed
- Environment: Uses “Preview” scope environment variables
How It Works
- Developer opens a PR
- GitHub Actions triggers
vercel deployfor each affected app - Vercel builds and deploys to a preview URL
- The PR gets a comment with the preview link
- Reviewers can test the changes in a live environment
Build Configuration
Next.js + Nextra Config
// next.config.mjs
const withNextra = nextra({});
export default withNextra({
reactStrictMode: true,
transpilePackages: ['@frequencyads/components'],
experimental: {
optimizePackageImports: ['@mantine/core', '@mantine/hooks', '@tabler/icons-react'],
},
});Build Commands
| Command | Purpose |
|---|---|
pnpm build | Full production build (via Turborepo) |
pnpm postbuild | Generate Pagefind search index |
pnpm start | Start production server locally |
Build Optimizations
- Turborepo caching — unchanged packages skip rebuilds
- Output file tracing — only deploy files that are actually used
- Automatic code splitting — per-route bundles
- Static generation — pages without dynamic data are pre-rendered
- Package import optimization — tree-shakes Mantine and Tabler icons
Monitoring
Health Check
// src/app/api/public/health/route.ts
export function GET() {
return Response.json({
status: 'healthy',
timestamp: new Date().toISOString(),
version: process.env.NEXT_PUBLIC_APP_VERSION,
});
}Rollback
If a production deployment has issues:
- Instant rollback via Vercel dashboard → Deployments → Previous → Promote
- CLI rollback:
vercel rollback - Git revert: Revert the commit, push, and let CI/CD redeploy
Each app can be rolled back independently since they’re separate Vercel projects.
Deployment Checklist
Before deploying to production:
- Type checking passes (
pnpm type-check) - Build succeeds locally (
pnpm build) - Environment variables set for production scope (per Vercel project)
- DNS records configured and propagated
- GitHub secrets configured for CI/CD
- PR preview tested by at least one reviewer
- Quality gates (VALIDITUS, GATED) passed