Skip to content

Quickstart

This guide covers the greenfield path: a fresh Next.js project that you want to shadow-and-canary from day one. For an existing project, see Migration (manual).

Time: about 10 minutes.

Prerequisites

  • A Vercel account (Pro or Enterprise for Skew Protection; see Prerequisites)
  • A GitHub account with GitHub Actions available
  • Node.js 20 or later
  • pnpm, npm, or yarn

  1. Clone the template

    Terminal window
    git clone https://github.com/mus-inn/shadow-canary
    cd shadow-canary/examples/greenfield
    npm install

    Or use the GitHub template button on github.com/mus-inn/shadow-canary to create a new repo pre-wired.

  2. Set up Vercel project

    Import the repo in the Vercel dashboard. Then configure these settings in Project Settings:

    SettingValue
    Production Branchproduction
    Auto-assign Custom Production DomainsOFF
    Deployment ProtectionDisabled (POC) or Protection Bypass enabled (prod)
    Skew ProtectionON, 7 days

    [screenshot: Vercel Settings > Git panel with Production Branch field set to “production” and Auto-assign OFF]

    Set the default branch in GitHub to master (not main). The canary cron workflow relies on running on the default branch.

  3. Create an Edge Config store

    In the Vercel dashboard, go to Storage and create a new Edge Config store. Name it something like shadow-config.

    Link the store to your project: in the store’s settings, click Connected Projects and add your project.

    [screenshot: Vercel Storage > Edge Config > Connected Projects panel]

    Copy the store ID — it looks like ecfg_xxxxxxxxxxxx. You will need it for secrets.

  4. Seed the Edge Config

    In the store’s Items tab, add one item:

    • Key: shadow-<your-repo-slug>-canary (e.g. for a repo named my-app, the key is shadow-my-app-canary)
    • Value (JSON):
    {
    "deploymentDomainProd": "",
    "deploymentDomainProdPrevious": "",
    "deploymentDomainShadow": "",
    "trafficShadowPercent": 1,
    "trafficProdCanaryPercent": 100,
    "shadowForceIPs": []
    }

    The workflows will overwrite the URL fields on every deploy. The empty strings here just ensure the key exists before the first push.

  5. Wire GitHub secrets

    In your GitHub repo, go to Settings > Secrets and variables > Actions and add:

    SecretWhere to find it
    VERCEL_TOKENVercel Account Settings > Tokens (scope: team, no expiry)
    VERCEL_ORG_ID.vercel/project.json — the orgId field, or Vercel team settings
    VERCEL_PROJECT_ID.vercel/project.json — the projectId field
    VERCEL_EDGE_CONFIG_IDEdge Config store ID from Step 3 (ecfg_xxxx)
    SLACK_WEBHOOK_URLSlack app > Incoming Webhooks (optional — skip if you don’t use Slack)

    [screenshot: GitHub Settings > Secrets panel with the five secrets listed]

  6. Wire Vercel environment variables

    In Vercel Project Settings > Environment Variables, add these for Production and Preview environments:

    VariableValue
    VERCEL_API_TOKENSame token as VERCEL_TOKEN above
    VERCEL_ORG_IDSame as the GitHub secret
    VERCEL_EDGE_CONFIG_IDSame as the GitHub secret
    ADMIN_USERAdmin username (default: admin)
    ADMIN_PASSAdmin password — choose something strong
    ADMIN_SESSION_SECRETA long random string for signing session cookies

    Generate a session secret:

    Terminal window
    node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
  7. First deploys

    Push to master to deploy the shadow slot:

    Terminal window
    git push origin master

    This triggers deploy-shadow.yml, deploys the app, and writes deploymentDomainShadow into Edge Config. Watch the Actions tab — the first run takes about 90 seconds.

    Then push to production to deploy the production slot. Use [skip-canary] on the first push because there is no previous prod URL to fall back to:

    Terminal window
    git checkout production
    git merge master -m "chore: bootstrap production [skip-canary]"
    git push origin production

    This triggers deploy-prod.yml, promotes the deploy to your custom domain, and sets trafficProdCanaryPercent: 100.

  8. Verify

    Visit these three URLs (replace your-domain.vercel.app with your actual domain):

    URLWhat to check
    https://your-domain.vercel.app/Home page loads normally
    https://your-domain.vercel.app/debugShows branch, commit, deploy ID, and your bucket cookie
    https://your-domain.vercel.app/adminLogin with ADMIN_USER / ADMIN_PASS; status shows “stable”

    On the /debug page, click Force SHADOW — reload and the page should show master as the branch. Click Forcer PROD to return.

You’re done

Your project now has:

  • A permanent 1% shadow slot on master receiving real traffic.
  • A canary ramp on every merge to production, with SLO checks every 15 minutes.
  • Auto-rollback if SLO fails, with Slack notification (if configured).
  • A /admin dashboard to pause, resume, or cancel the canary.

Next steps: