In Quantum Metropolis 2150, no system goes directly to production servers. Every change goes through a rigorous verification process — from preview deployments for individual Pull Requests, through the staging environment, to a controlled promotion to production. Such a pipeline ensures that residents of Quantum City never experience faulty code.
Preview Deployments are automatic application deployments generated for each Pull Request. Every PR receives its own, unique URL at which changes can be tested before being merged into the main branch.
Vercel — the platform created by the Next.js authors — offers the best support for Preview Deployments. But other platforms, like Netlify or AWS Amplify, also support this concept.
project-git-feature-xyz-team.vercel.app)1# Example Preview Deployments URLs:
2# PR #42: my-app-git-feature-login-myteam.vercel.app
3# PR #43: my-app-git-fix-header-myteam.vercel.app
4# PR #44: my-app-git-update-api-myteam.vercel.app
5
6# Each URL is unique and works as long as the PR exists1// vercel.json
2{
3 "git": {
4 "deploymentEnabled": {
5 "main": true,
6 "staging": true
7 }
8 },
9 "github": {
10 "autoAlias": true,
11 "autoJobCancelation": true,
12 "silent": false
13 },
14 "headers": [
15 {
16 "source": "/(.*)",
17 "headers": [
18 {
19 "key": "X-Robots-Tag",
20 "value": "noindex"
21 }
22 ]
23 }
24 ]
25}Important note: Preview Deployments should have the header
X-Robots-Tag: noindex so that search engines do not index test versions!Professional projects use a multi-level deployment pipeline:
1Development (dev) → Developer's local machine
2 ↓
3Preview → Automatic per-PR (Vercel Preview)
4 ↓
5Staging → Production mirror (final tests)
6 ↓
7Production (prod) → Production servers (end users)Each Git branch can be mapped to a different environment:
1# Branch → environment configuration in Vercel:
2# main → Production (app.quantum-city.com)
3# staging → Staging (staging.quantum-city.com)
4# develop → Development (dev.quantum-city.com)
5# feature/* → Preview (auto-generated URL)
6
7# Developer workflow:
8git checkout -b feature/new-dashboard
9# ... coding ...
10git push origin feature/new-dashboard
11# → Automatically: Preview Deployment!
12
13# After review and merge into staging:
14git checkout staging
15git merge feature/new-dashboard
16git push origin staging
17# → Automatically: Staging Deployment!
18
19# After tests on staging, merge into main:
20git checkout main
21git merge staging
22git push origin main
23# → Automatically: Production Deployment!Each environment has its own variables:
1// Vercel CLI - adding variables per environment
2// vercel env add DATABASE_URL development
3// vercel env add DATABASE_URL preview
4// vercel env add DATABASE_URL production
5
6// In the code, we check the environment:
7// app/api/config/route.ts
8import { NextResponse } from 'next/server';
9
10export async function GET() {
11 const environment = process.env.VERCEL_ENV; // 'production' | 'preview' | 'development'
12 const gitBranch = process.env.VERCEL_GIT_COMMIT_REF; // e.g. 'feature/login'
13 const commitSha = process.env.VERCEL_GIT_COMMIT_SHA; // commit hash
14
15 return NextResponse.json({
16 environment,
17 branch: gitBranch,
18 commit: commitSha?.slice(0, 7),
19 // Different databases per environment
20 database: environment === 'production'
21 ? 'prod-cluster'
22 : environment === 'preview'
23 ? 'preview-cluster'
24 : 'dev-cluster',
25 });
26}In the staging and preview environments, it's worth protecting access so that unauthorized people do not see unpublished changes:
1// middleware.ts - protecting preview and staging
2import { NextRequest, NextResponse } from 'next/server';
3
4export function middleware(request: NextRequest) {
5 const environment = process.env.VERCEL_ENV;
6
7 // Do not protect production
8 if (environment === 'production') {
9 return NextResponse.next();
10 }
11
12 // Check authorization for preview/staging
13 const authHeader = request.headers.get('authorization');
14 const previewToken = process.env.PREVIEW_ACCESS_TOKEN;
15
16 // Allow access with a token or cookie
17 const hasToken = authHeader === 'Bearer ' + previewToken;
18 const hasCookie = request.cookies.get('preview-access')?.value === previewToken;
19
20 if (!hasToken && !hasCookie) {
21 // Redirect to the preview login page
22 return NextResponse.redirect(new URL('/preview-login', request.url));
23 }
24
25 return NextResponse.next();
26}
27
28export const config = {
29 matcher: ['/((?!preview-login|api|_next/static|favicon.ico).*)'],
30};Deploy Hooks are webhook URLs that trigger a new deployment when called:
1# Creating a Deploy Hook in Vercel:
2# Settings → Git → Deploy Hooks
3# Name: "CMS Content Update"
4# Branch: main
5# → Generates URL: https://api.vercel.com/v1/integrations/deploy/prj_xxx/yyy
6
7# Usage with CMS (e.g., after publishing an article):
8curl -X POST https://api.vercel.com/v1/integrations/deploy/prj_xxx/yyy
9
10# Usage in GitHub Actions:
11# - name: Trigger Vercel Deploy
12# run: curl -X POST ${{ secrets.VERCEL_DEPLOY_HOOK }}
13
14# Usage with Strapi/Sanity webhook:
15# After publishing content → POST to Deploy Hook URL
16# → Vercel rebuilds the page with new data (ISR/SSG)1// app/api/webhook/cms/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3
4export async function POST(request: NextRequest) {
5 // Verifying the webhook from the CMS
6 const signature = request.headers.get('x-webhook-signature');
7 const secret = process.env.CMS_WEBHOOK_SECRET;
8
9 if (!verifySignature(signature, secret)) {
10 return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
11 }
12
13 // Trigger revalidation or new deploy
14 const deployHookUrl = process.env.VERCEL_DEPLOY_HOOK;
15
16 if (deployHookUrl) {
17 await fetch(deployHookUrl, { method: 'POST' });
18 return NextResponse.json({ status: 'Deploy triggered' });
19 }
20
21 return NextResponse.json({ status: 'No deploy hook configured' });
22}
23
24function verifySignature(signature: string | null, secret: string | undefined): boolean {
25 if (!signature || !secret) return false;
26 // HMAC verification implementation
27 return true;
28}Environment promotion is the controlled process of moving code between environments:
1# Strategy 1: Git-flow with automatic deploy
2# develop → auto-deploy to dev
3# staging → auto-deploy to staging
4# main → auto-deploy to production
5
6# Merge workflow:
7git checkout staging
8git merge develop # Promote dev → staging
9git push origin staging # Auto-deploy to staging
10
11# After tests on staging:
12git checkout main
13git merge staging # Promote staging → prod
14git push origin main # Auto-deploy to production
15
16# Strategy 2: Vercel Promote (without merge)
17# Vercel allows promoting an existing deployment:
18vercel promote [deployment-url] --scope=team
19
20# This moves EXACTLY the same build to production
21# Without rebuilding — guarantee of identity!Preview Deployments and staging environments are the foundations of a professional deployment process:
In Quantum Metropolis 2150, no system goes to production without the full preview → staging → production cycle. This guarantees the stability and quality of services for all residents of the cyberpunk city.