I don't write code. Let me get that out of the way first. I'm a designer and content person who somehow ended up building a full auto-deploy pipeline for my portfolio site. The entire thing was built through conversation with Claude Code — no IDE, no Stack Overflow, no tutorial YouTube videos at 2x speed.

Here's how it works: I write something in Sanity Studio, hit publish, and two minutes later it's live on my site. No manual deploys. No SSH-ing into servers. No prayer.

The best deploy pipeline is one you forget exists. You publish, you move on. The machines handle the rest.

The Architecture

The pipeline has four moving parts, each one simple on its own. The magic is in how they connect:

  • Sanity Studio — where I write and publish content
  • Sanity Webhook — fires an event when content changes
  • GitHub Actions — catches the event and runs the build
  • Cloudflare Workers — serves the built site at the edge
Don't Panic

If "webhook" and "GitHub Actions" sound intimidating, I was right there with you three weeks ago. Think of a webhook as a phone call — "hey, something changed" — and GitHub Actions as the assistant who picks up and does the work.

Step 1: The Webhook

Sanity has built-in webhook support. You tell it: "When any document is published, send a POST request to this URL." That's it. One URL, one checkbox.

The URL points to GitHub's repository_dispatch API. This is how you tell GitHub Actions to wake up and do something. Here's what Claude Code generated for me:

// Sanity webhook → GitHub repository_dispatch
// This fires every time you publish in Sanity Studio

POST https://api.github.com/repos/{owner}/{repo}/dispatches
Headers:
  Authorization: Bearer {GITHUB_TOKEN}
  Accept: application/vnd.github.v3+json
Body:
  { "event_type": "sanity-publish" }

Step 2: GitHub Actions Workflow

The workflow listens for that sanity-publish event and runs the build. But here's a gotcha that took me an embarrassingly long time to figure out:

The 60-Second Problem

Sanity's CDN doesn't update instantly. When you publish a document, the CDN can take up to 60 seconds to serve the fresh data. If your build starts immediately, it might fetch stale content.

The fix is almost comically simple:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Wait for Sanity CDN
        run: sleep 60    # Yes, really.

      - name: Checkout
        uses: actions/checkout@v4

      - name: Build
        run: npm ci && npm run build

      - name: Deploy
        uses: cloudflare/wrangler-action@v3

A sleep 60. That's the fix. Sometimes the unglamorous solution is the right one.

Step 3: The Debounce

What happens if you publish three times in quick succession? Without protection, you'd get three overlapping builds. Wasteful at best, broken at worst.

GitHub Actions has a beautiful one-liner for this:

concurrency:
  group: "deploy"
  cancel-in-progress: true

If a new publish comes in while a build is running, it cancels the old one and starts fresh. Free debouncing.

The Result

The whole pipeline — from Sanity publish to live site — takes about 2 minutes. Most of that is the intentional 60-second CDN wait. The actual build and deploy is under a minute.

I've published over 30 content updates since setting this up. Not once have I thought about deploys. That's exactly how it should be.

The goal isn't to understand every line. The goal is to ship something that works, learn what you can, and know where to look when something breaks.