Documentation is work in progress and not completeEditor
FlashCC/Making a deck/Section 14 of 29

AI drafting

The key lives on the server and never reaches the bundle — the request flow, the system prompt constraints, and the two-pass slot alignment.

The key lives on the server and never reaches the bundle. That is the entire reason the server process exists.

  1. 1.AiChat takes a brief. Cmd/Ctrl+Enter submits; a new request aborts any in flight.
  2. 2.draftSlides POSTs { brief, structure: { name, shape, slots } } to /api/draft.
  3. 3.The server calls claude-opus-5 through messages.parse() with a zod output format. The system prompt enforces: finished copy not placeholders, one idea per slide, hook under 90 characters, body under 220, stay in the brief’s voice, add no claims the brief does not contain, no hashtags or emoji.
  4. 4.A policy decline returns 200 with no usable content, so stop_reason === "refusal" is checked before reading and mapped to 422.
  5. 5.alignToSlots runs two passes: first match drafts to slots by role, then fill what is left positionally. One pass swallowed the CTA whenever the model answered out of order — the three point slots sharing an id is exactly what breaks a naive match.