Skip to content
Back to blog
Build Logs13 May 20262 min read

From Copy Paste To One Command Drafts

I replaced my old copy paste blog routine with a secure endpoint that creates Sanity drafts directly, then I manually review and publish.

From Copy Paste To One Command Drafts
sanityautomationnextjsworkflow

Highlight

Automation should remove friction, not remove control.

For a while, my blog workflow was simple but annoying. I generated content in one place, copied it, pasted it into Sanity, then fixed little formatting issues by hand. It worked, but it always felt like admin work hiding inside creative work.

The real problem was consistency

The pain was not one big failure, it was small repeated friction. Some posts missed metadata quality, some needed clean up, and each run depended on me remembering every field. That is exactly the kind of process that slowly drifts.

  • Keep draft creation fast
  • Enforce SEO and structure rules every time
  • Keep manual publish control in Studio

What I changed

I added a secured endpoint that accepts structured blog payloads, validates them strictly, and writes directly to Sanity as a draft document. That keeps generation and delivery fast, while still forcing a human review before anything goes live.

app/api/blog/draft/route.tsts
import { NextRequest, NextResponse } from "next/server"

export async function POST(request: NextRequest) {
  // 1) Gate the route with a shared secret header
  const authorized = isAuthorizedBlogRequest(request.headers.get("x-blog-secret"))
  if (!authorized) {
    return NextResponse.json({ ok: false, error: "Unauthorized" }, { status: 401 })
  }

  try {
    // 2) Validate incoming draft payload shape/content
    const payload = validateDraftPayload(await request.json())

    // 3) Write to Sanity as draft (not published)
    const { draftId, slug } = await writeDraftToSanity(payload)

    // 4) Return only safe, useful identifiers
    return NextResponse.json({ ok: true, draftId, slug }, { status: 200 })
  } catch {
    // Keep errors generic in public-facing responses
    return NextResponse.json({ ok: false, error: "Invalid draft payload" }, { status: 400 })
  }
}

The interesting part is not the endpoint itself, it is the behaviour it enforces. The payload has to be complete, the structure has to match the schema, and the writing still keeps its voice. The workflow finally feels reliable instead of fragile.

Share

Continue Reading

More field notes