Part 3 · AI Content Generation
Now quill earns its name. In Part 3 the blog grows a writing assistant: ask it for a draft, a title,
a summary, or tags, and watch the text stream into the editor as it’s generated. The base playbook’s
askr called the Claude API from a CLI; here you do it from a server — which changes everything,
because now the AI call is on a request path shared by many users, costs real money per token, and can
fail slowly. Production AI is less about the prompt and more about the plumbing around the prompt.
What you’ll build
Section titled “What you’ll build” editor ──POST /api/posts/{id}/draft──► quill ──HTTPS (stream)──► Claude API ▲ │ │ └──────── SSE: tokens as they arrive ────┘◄──── streamed tokens ──────┘ │ long jobs ──► worker (queue + retries)- Server-side generation: a Rust module that calls the Claude API with
reqwest, with prompts for drafting, titling, summarizing, and tagging a post. - Streaming end-to-end: the model’s tokens flow over the SSE pipe you built in Part 2, so the writer sees text appear live instead of staring at a spinner.
- Background jobs: longer generations run as async tasks off the request path, with retries, timeouts, and idempotency — so a slow model never ties up a web worker.
- Guardrails & cost control: input limits, output caps, per-user rate limits, and a cache so the same request never pays twice.
Why this is a systems problem, not a prompt problem
Section titled “Why this is a systems problem, not a prompt problem”| Naive CLI approach | What production forces |
|---|---|
| block until the full response | stream tokens; free the worker |
| one call, hope it works | timeouts, retries, circuit-breaking |
| ignore cost | token accounting, caps, caching |
| trust the input | validate size, strip injection, rate-limit |
The chapters
Section titled “The chapters”| Ch | Title | You add | The idea it teaches |
|---|---|---|---|
| 1 | Calling Claude from the server | reqwest client, prompts, typed responses | server-side API clients, secrets, structured output |
| 2 | Streaming to the editor | model stream → SSE → browser | wiring two streams, partial output, cancellation |
| 3 | Background jobs | a worker binary, a queue, retries | decoupling the request path, idempotency, timeouts |
| 4 | Guardrails & cost | rate limits, caps, response cache | protecting a paid, abusable endpoint |
The thread
Section titled “The thread”Once it compiles, what does it take to run for real users? Part 3’s answer: treat every external call as hostile and expensive. The Claude API is fast and reliable — and you still design as if it will be slow, fail, and cost money, because at scale it eventually does all three. That mindset — timeouts, retries, caching, back-pressure — is the same whether the dependency is an LLM, a payment processor, or another team’s service.