Build day
Day 3 — Deploy + CMS
Deploy your site live and add a CMS so your client can edit content. You'll learn Git branches, pull requests, and how to wire up Sanity.
Rules for the day
- 01For brand new projects: pushing direct to main is fine — no users yet, no risk.
- 02For live projects: use branches and pull requests — don't break what users see.
- 03Tell Claude your experience level in CLAUDE.md — so responses match what you understand.
- 04Ask "do you see any security issues with this?" before going live — catches things you'd miss.
- 05.env.local lives only on YOUR machine — Vercel needs env vars added separately — biggest gotcha when deploying.
- 06Static pages need a redeploy to show CMS updates — or set up auto-revalidate (~60s).
Concepts you need first
- 1
What's a headless CMS?
A CMS that's separate from the website build. Webflow's CMS is built in. With Sanity (or Strapi) the content lives in a separate service that your site pulls from. Means the same CMS can power a website, mobile app, and other platforms.
- 2
What's a branch?
A copy of your codebase. You can work on a new feature (like an About page) in a branch without affecting your live site. Each branch gets its own preview URL on Vercel — perfect for sharing with clients before going live.
- 3
What's a commit?
Logging your changes — saying 'these are saved'. Like a checkpoint.
- 4
What's a push?
Sending your committed changes from your computer up to GitHub.
- 5
What's a pull request (PR)?
A request to merge a branch (e.g. 'about-page') back into the main branch. Lets you review changes before they go live.
- 6
What's a merge?
Combining two branches together — usually merging your feature branch into main once you're happy with it.
- 7
Why bother with branches?
For a brand new project with no users — just push to main, it's fine. For live projects, branches let multiple people work in parallel without stepping on each other, and let you preview changes before anything goes live.
- 8
What's a CDN?
Content Delivery Network — a place to store images and assets so they load fast. Sanity has its own CDN. Use it for content the client will edit (blog post images). For homepage images that don't change, just put them in /public.
- 9
What's .env.local? Why doesn't Vercel see it?
A file in your project that holds secrets (API keys, project IDs). It's gitignored so it never gets pushed to GitHub. That's the point — but it means Vercel doesn't see it either. You have to add the same env vars manually in Vercel's dashboard (Settings → Environment Variables) for production builds to work.
- 10
Static vs auto-revalidate (why your CMS update isn't showing)
When Vercel builds your site, it pre-renders your homepage HTML based on what's in Sanity AT BUILD TIME. After that, Sanity updates won't appear unless you (a) redeploy in Vercel, or (b) set up auto-revalidate so Next.js re-fetches every X seconds. For real client sites, ask Claude to set up revalidate to ~60 seconds.
Initial deploy to Vercel
- 11
Start your dev server
In a terminal tab inside your project folder.
- 12
Start Claude Code in another tab
- 13
Push everything to main on GitHub
For brand new projects with no users, push direct to main. Tell Claude:
- 14
Vercel auto-deploys
Once GitHub gets the push, Vercel automatically builds and deploys. Wait ~1–2 min and refresh your live URL.
- 15
If Vercel build fails — check env vars
Most common deploy failure. .env.local doesn't sync. Go to Vercel → your project → Settings → Environment Variables and add them manually. See troubleshooting below.
Install Sanity (headless CMS)
- 16
Ask Claude how to add Sanity
Don't memorise the install command — just ask.
- 17
Run the install commands Claude gives you
Make sure your terminal window is wide — line breaks cause issues. Each command pasted in a fresh terminal tab.
- 18
Initialize Sanity Studio
Sanity will prompt through setup: log in with Google → create new project → name it (e.g. 'h-studio-001') → public dataset visibility → add config files (yes).
- 19
Configure Sanity MCP server
When asked: 'Configure Sanity MCP server for Claude Code?' — say YES. This is what makes the rest magical.
- 20
Project settings
TypeScript: yes. Embedded Sanity Studio: yes. Route: /studio. Template: clean project with no predefined types. Add project ID and dataset to .env.local: yes.
- 21
Restart Claude Code if MCP didn't connect
Type /exit, then run claude --dangerously-skip-permissions again.
- 22
Verify Sanity MCP is connected
- 23
Open Sanity Studio locally
You should see Sanity Studio with no document types yet — that's correct.
Create your first content type
- 24
Tell Claude what to build
For demos, let Claude make a sensible schema. For real client work, specify exactly what fields you need.
- 25
Refresh Sanity Studio in browser
You should now see your new document type with sample items inside.
- 26
Test that the homepage updates
Edit one of the sample items in Sanity Studio (change a title), click Publish, refresh your homepage. The change should appear.
- 27
If it doesn't update — it's probably caching
Branches + pull requests (full manual)
- 28
Create a new branch and push to it
When working on something risky (like adding the CMS), use a branch instead of pushing direct to main.
- 29
Vercel auto-creates a preview deployment
Open Vercel — you'll see a new deployment under your branch name with its own preview URL. Share with clients/teammates for review.
- 30
Fix any build errors
If the Vercel build fails, copy the error and paste into Claude.
- 31
Open a pull request
When the branch is approved, ask Claude to open a PR.
- 32
Have Claude review the PR before merging
Catches issues before they go live. Claude takes on a 'reviewer' role and often spots things.
Going live with the CMS
- 33
Add Sanity env vars to Vercel (FIRST TIME ONLY)
Go to vercel.com → your project → Settings → Environment Variables. Add NEXT_PUBLIC_SANITY_PROJECT_ID, NEXT_PUBLIC_SANITY_DATASET, SANITY_API_READ_TOKEN, SANITY_API_WRITE_TOKEN. Get the values from your local .env.local file. Tick all 3 environments (Production, Preview, Development). Mark the two API tokens as Sensitive.
- 34
Register Sanity Studio with your production domain
After deploy, visit yoursite.com/studio. It'll prompt you to register — stops other sites using your CMS. Click 'Add studio host'. Use the FULL URL including /studio (e.g. https://yoursite.vercel.app/studio).
- 35
Add team members or clients to Sanity
Sanity dashboard → Members → Add member. Free plan includes 20 seats.
- 36
Test live updates
Edit something in Sanity Studio on your live site. Click publish.
- 37
If updates don't appear
Most likely your homepage is statically pre-rendered (locked to build time). Two options: (1) Manual: Vercel → Deployments → ⋯ → Redeploy. (2) Better: ask Claude to set up auto-revalidate.
Connect a custom domain
- 38
Buy a domain through Vercel
Vercel → Domains → Buy. Good prices. Tip: .xyz domains are $2 for the first year.
- 39
Or connect a domain you already own
Vercel → Project → Settings → Domains → Add. Type your domain (e.g. yoursite.com) — Vercel gives you DNS records to add at Namecheap/GoDaddy/etc.
- 40
Set up a staging subdomain
Add staging.yoursite.com → set it to 'Preview' instead of 'Production'. Now branches deploy to that subdomain.
- 41
Vercel + Sanity pricing
Both free for portfolios and small client sites. Only need paid plans on big sites with serious traffic — at that point the cost is trivial.
Useful tips
- 42
Use rems/ems instead of pixels (if you prefer)
Julian's tip when asked: easiest way is to tell Claude 'convert it to rems'. If it keeps reverting to pixels, add 'do not use pixels, use rems and ems' to your CLAUDE.md file.
- 43
Use /resume to recover a previous Claude Code conversation
Type /resume inside Claude Code — gives you a list of previous conversations. Works ~90% of the time.
- 44
Use a CLAUDE.md file for persistent context
Anything you want Claude to remember every time — your experience level, brand guidelines, coding preferences (rems vs pixels), tone. Add it to a CLAUDE.md file in your project root and Claude reads it before every action.
- 45
When stuck on a hard prompt — describe it like to a developer
Don't just say 'fix it' or 'match Figma'. List exact issues: 'The H1 has no overlay. The image is too big. The button needs to align with the text on the right.' Be specific.
- 46
Switch to Codex if Claude is being weird
Sometimes Claude has off days. Open a new terminal tab and type 'codex' instead of 'claude'. Same workflow, different model.
- 47
GitHub commits page can be cached
If you push something and don't see it on GitHub's commit list, hard refresh the page (Cmd + Shift + R) before assuming the push failed. Or run: git ls-remote origin main
- 48
Pasted token looks too short? Re-paste it
When adding env vars to Vercel, the value field shows dots. If a token's dots are way shorter than the field width, the paste didn't take. Click the field, clear it, paste again.
Quick version — Ship Studio
Ship Studio gives you a visual UI for branches, pull requests and merges. Click 'new branch' → name it → make changes → click sync → 'submit for review' to open a PR → click merge. Same Git under the hood, just visual. Free. Also has a Backups feature that lets you restore to any previous GitHub push with one click.
- 49
Open the Branches panel
In Ship Studio, click Branches in the sidebar — see all branches visually.
- 50
Click 'New branch'
Type a name (e.g. 'about-page') → click create. Ship Studio switches you to the new branch automatically.
- 51
Make your changes
Use Claude Code as normal — work on the about page, refine, etc.
- 52
Click 'Sync'
Pushes your branch changes to GitHub. You can grab the Vercel preview URL from inside the app.
- 53
Click 'Submit for review'
Opens a pull request for you. Add a description if needed → click Create pull request.
- 54
Click 'Merge'
Merges the branch into main. You can also tell Claude to review the PR first.
- 55
Restoring a backup
If something breaks, go to Backups in Ship Studio. Every push to GitHub is a restore point. Click restore on any of them.
Troubleshooting
Common errors and what they actually mean.
- Missing environment variable: NEXT_PUBLIC_SANITY_PROJECT_ID (Vercel build)
- What:
- .env.local lives only on your machine — Vercel doesn't see it.
- Fix:
- Go to Vercel → your project → Settings → Environment Variables. Add the four Sanity vars manually (project ID, dataset, read token, write token). Get values from your local .env.local. Tick all 3 environments. Then redeploy.
- Cannot find module for page: /_not-found (after moving folder)
- What:
- Stale .next build cache from old folder location.
- Fix:
- Run:
rm -rf .nextthennpm run buildagain. Always do this after moving a folder.
- ReferenceError: window is not defined (on /studio route)
- What:
- Sanity Studio uses browser-only APIs but Next.js is trying to render it on the server.
- Fix:
- Tell Claude: 'The /studio route is failing with window is not defined. Add use client to the page and move metadata to a separate layout.'
- @sanity/image-url default export deprecated
- What:
- Older Sanity tutorials use the default export — newer versions need the named export.
- Fix:
- Change
import imageUrlBuilder from '@sanity/image-url'toimport { createImageUrlBuilder } from '@sanity/image-url'. Or just paste the warning into Claude.
- Sanity MCP not connecting after install
- What:
- Claude Code needs to restart to load the new MCP.
- Fix:
- Type
/exitthen runclaude --dangerously-skip-permissionsagain. Then/mcpto verify.
- CMS update not showing on live site (but works locally)
- What:
- Your homepage is statically pre-rendered — locked to build time.
- Fix:
- Quick fix: Vercel → Deployments → most recent → ⋯ → Redeploy. Better fix: ask Claude to set up Next.js auto-revalidate (e.g. every 60 seconds) so changes appear without redeploying.
- CMS update not showing locally
- What:
- Browser caching.
- Fix:
- Hard refresh (Cmd+Shift+R). If still not updating: 'I updated [field] in Sanity but the homepage still shows the old version. Why?'
- Vercel build failed for my branch
- What:
- Some code change broke the build on Vercel even though it works locally.
- Fix:
- Copy the full Vercel error log and paste into Claude. It'll diagnose and fix.
- Studio host not configured (Sanity)
- What:
- Sanity blocks unauthorized domains from using your CMS.
- Fix:
- Visit yoursite.com/studio → click 'Register this studio' or 'Add studio host'. Paste the FULL URL including /studio (e.g. https://yoursite.vercel.app/studio).
- 'Failed to fetch iframe URL' on Sanity dashboard
- What:
- Harmless. Sanity's dashboard tries to embed your Studio in an iframe; Vercel's frame-protection blocks it.
- Fix:
- Ignore the banner. The Studio still works at yoursite.com/studio directly.
- Local Sanity has different content than live
- What:
- The two Sanity instances are out of sync.
- Fix:
- If Sanity MCP is installed, tell Claude: 'My local Sanity studio shows different content than live — can you check what's out of sync?'
- Don't know what branch I'm on
- What:
- Easy to lose track when juggling branches in the terminal.
- Fix:
- In Claude Code: 'What branch am I on right now?' Or in Ship Studio: just look at the branches panel.
- Pasted into PowerShell terminal and it didn't work (Windows)
- What:
- PowerShell uses different paste shortcuts.
- Fix:
- Use
Ctrl + Shift + Vinstead ofCtrl + V. Or drag screenshots/files in directly.
- Claude is being stupid today
- What:
- Sometimes Claude has off days — model versions update, things change.
- Fix:
- Try Codex as a fallback (type
codexin a terminal instead ofclaude). Or come back tomorrow.