Step 2 of 4
Deploy Your Store
Put your store online so customers can visit it. Vercel hosts your site for free with automatic HTTPS.
You'll need a free Vercel account, your keys from Step 1, and optionally a domain name · Estimated time: 15–25 min
1. Start the Deployment
There are two ways to get your code onto Vercel. Both end up in the same place — pick whichever suits you.
Option A — the one-click button (fastest)
The product README has a Deploy with Vercel button at the top. It clones the repository into your own GitHub account and shows you a form for the environment variables before the first build. The form pre-fills prompts for nine variables:
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
SUPABASE_DB_URL
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
STRIPE_SECRET_KEY
NEXT_PUBLIC_SITE_NAME
NEXT_PUBLIC_SITE_URL
CRON_SECRETEverything else (email, file uploads, analytics) is added afterwards under Settings → Environment Variables. Section 2 below explains each value.
Option B — import an existing repository
Use this if you already pushed your own copy of the code to GitHub, GitLab, or Bitbucket.
- Go to vercel.com/new
- Click Import Git Repository (or Add New → Project)
- Find your ShipCommerce repository in the list and click Import
- Vercel will automatically detect that it's a Next.js project
- Expand Environment Variables and add the values from section 2 before you deploy
2. Add Your Environment Variables
Environment variables are configuration values your store reads when it starts — the database address, your site URL, payment keys. The block below is grouped so you can see what you have to fill in and what you can skip.
# ─── Required ───────────────────────────────────
# From Step 1 (Supabase)
NEXT_PUBLIC_SUPABASE_URL=https://abcdefghijk.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIs...
SUPABASE_DB_URL=postgresql://postgres:PASSWORD@...:6543/postgres
# Your store's name and public address
NEXT_PUBLIC_SITE_NAME=Your Store
NEXT_PUBLIC_SITE_URL=https://your-project.vercel.app
# Protects /api/cron/* — see section 4
CRON_SECRET=paste-a-64-character-hex-string-here
# ─── Payments (optional) ────────────────────────
# Added in Step 3. Cash on delivery and bank transfer
# work without these, so you can deploy first.
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123...
STRIPE_SECRET_KEY=sk_live_abc123...
STRIPE_WEBHOOK_SECRET=whsec_abc123...
# ─── Optional ───────────────────────────────────
RESEND_API_KEY=re_abc123... # order + account emails
RESEND_FROM_EMAIL=hello@yourstore.com # defaults to onboarding@resend.dev
BLOB_READ_WRITE_TOKEN=vercel_blob_... # image uploads; falls back to Supabase StorageThese are example values — use your own keys, not these.
How to add each variable: Type the name (e.g. NEXT_PUBLIC_SUPABASE_URL) in the "Name" field, paste your value in the "Value" field, then click Add. Repeat for each variable. Comments and blank lines are not part of a value — copy only the text after the = sign.
Generating CRON_SECRET
CRON_SECRET is a password you invent. It is the only thing standing between the public internet and your /api/cron/* routes, so use a random value rather than a word. On macOS or Linux:
openssl rand -hex 32Copy the 64-character output into the CRON_SECRET value field. If you ran npm run setup locally, one was already generated for you — copy it out of your .env.local instead.
CRON_SECRET is required in production. Without it, the cleanup route refuses to run at all. Set it now even if you schedule the cron later.
What you can skip
- Stripe keys — cash on delivery and bank transfer work out of the box. You can launch on Supabase alone and add Stripe later.
BLOB_READ_WRITE_TOKEN— optional. When it is unset, product image uploads fall back to Supabase Storage. That works fine; Vercel Blob is simply faster to serve.- Resend — without it, order and account emails are not sent. Everything else still works.
SUPABASE_DB_URLis only read by thedb:setupandmigratescripts, never by the running site — but set it anyway so future migrations are one command away.
The full list of every supported variable is in Configuration.
3. Click Deploy
- Click Deploy
- Wait 2–5 minutes for the build to finish
- When done, you'll see a link like
your-project.vercel.app - Click it — your store is live!
4. Schedule the Cleanup Cron
Your store ships with a maintenance route at /api/cron/cleanup-abandoned-orders. It cancels unpaid cash-on-delivery and bank-transfer orders that were never completed and puts their stock back on the shelf. Nothing calls it on its own — the product does not ship a vercel.json, so you add one.
- Create a file called
vercel.jsonin the root of your repository - Paste this in:
{
"crons": [{ "path": "/api/cron/cleanup-abandoned-orders", "schedule": "0 * * * *" }]
}0 * * * * runs it once an hour, on the hour. Commit and push the file — Vercel picks up the schedule on the next deployment.
You do not have to wire up the authentication yourself. The route requires an Authorization: Bearer $CRON_SECRET header, and Vercel Cron sends exactly that header automatically as long as CRON_SECRET is set as an environment variable on the project.
Hosting somewhere other than Vercel? Any scheduler works — point it at the same URL and have it send the same Authorization: Bearer header with your secret.
5. Add Your Domain (Optional)
If you have a custom domain (e.g. yourstore.com):
- In Vercel, go to your project → Settings → Domains
- Click Add Existing, type your domain in the search field, select Connect to an environment → Production, then click Save
- Vercel will show you DNS records to add at your domain provider:
Type Name Value A @ 76.76.21.21 CNAME www cname.vercel-dns.com - Wait 5–30 minutes for the domain to connect
6. Update Your URLs
Your store's address changed, so three places need to hear about it:
- Vercel: Settings → Environment Variables → change
NEXT_PUBLIC_SITE_URLto your domain, including thehttps://and with no trailing slash - Supabase: Authentication → URL Configuration → set Site URL to your domain, so password-reset and confirmation links point at the right place
- Stripe: if you already configured payments, update your webhook endpoint URL to your domain. Setting it up for the first time? That's Step 3, and you'll use this domain there.
- Redeploy: in Vercel, go to Deployments → click the three dots on the latest → Redeploy. Environment variable changes only take effect on a new deployment.
7. Verify the Deployment
The product includes a health check that tells you whether production is actually wired up correctly. Run it from a local clone whose .env.local holds the same values you just entered in Vercel:
npm run post-deployIt checks that the critical environment variables are set, that Supabase is reachable and has its schema, that the storage bucket exists, and — the one people miss — whether your Stripe keys are still test-mode keys on a live site.
Running your store without Stripe? post-deploy will report the Stripe variables as missing. That is expected — cash on delivery and bank transfer are unaffected.
No local clone? Skip it, and rely on the test purchase in Step 4 instead. Setting up a local clone is covered in Local Development.
Checklist
- ☐Store deployed and accessible
- ☐
CRON_SECRETset and the cleanup cron scheduled invercel.json - ☐Custom domain connected (if applicable)
- ☐
NEXT_PUBLIC_SITE_URLand the Supabase Auth Site URL updated, then redeployed
Was this step clear?