I’ve been using AI models as a thinking partner for cocktail ideas for a while. Not because I can’t look things up, but because the conversational format is genuinely useful: you describe a constraint or a craving, the model suggests something, you push back on the proportions or swap an ingredient, and something emerges from the iteration that you wouldn’t have arrived at alone.
The problem was that these conversations were disappearing. A drink I’d had the model design in January would come up in conversation months later and I’d have no record of it. The chat history existed somewhere, but it wasn’t organized, searchable, or sharable. I was doing interesting work in a context window and losing it.
So I built a catalog.
Prompted Pours is a Hugo site that archives AI-generated cocktail recipes. It currently holds 135 recipes generated across Claude, GPT-5, and several Gemini versions. But the more interesting thing — the part that required actual design work — was building a system that makes the workflow repeatable and the output consistent.
The Schema
A cocktail recipe on this site isn’t just ingredients and method. Each entry is a TOML-frontmatter Hugo content file with a structured body. The frontmatter carries everything taxonomic and quantitative: title, date, draft status, spirits, styles, glassware, AI model attribution, and the recipe block itself (method, ice, glass, garnish, ingredients with amounts and optional notes). The body has exactly three sections: ## Story, ## Method, ## Notes.
The Story section is what makes this more than a recipe dump. It reconstructs the prompt-to-glass arc in second person: what I asked for, what the model suggested first, what changed and why, what surprised either of us. It’s the record of the co-creation process, not just the result. Without it, a recipe is just a list of ingredients. With it, it’s an account of a specific conversation — why these ratios, why this glass, what the model reached for before landing here.
The Method is a terse numbered list. The Notes section carries ratio tweaks, substitution ideas, what to avoid, what to pair it with.
A few rules I enforced from the start that turned out to matter:
- Decimal ounces, not fractions.
0.75 oz, not3/4 oz. Models drift toward fractions; the rule forces consistency across 135 files. - No leading articles in titles.
Italian Monk, notThe Italian Monk. Articles stay only for literary references (Knife in the Water). Without this rule, half the alphabetical index would be under T. spiritslists every named bottle. Base spirit, vermouth, amaro, liqueur — all of them. Not just the base. This makes the spirits taxonomy actually useful for browsing.
The Prompting System
The schema only works if the models produce output that conforms to it. And models drift. They’ll invent taxonomy values, add leading articles, use fractions, include empty note = "" lines, write ## Notes: with a colon.
The solution was a prompting system: a PROMPTS.md file that lives in the repo with four prompts covering every scenario a recipe might arrive from.
| Scenario | Prompt |
|---|---|
| Start from a brief | Create from scratch |
| Have raw text from an old chat | Convert existing |
| One drink just worked in a live chat | Format what we just discussed |
| Several drinks emerged in one chat | Format every recipe in this chat |
Each prompt is self-contained: it includes the full format template, all the output rules, a canonical taxonomy list, and a pre-output verification checklist the model is asked to run before generating. The checklist reads like a linter: no leading article, spirits lists every named bottle, glass matches glassware, no empty note lines, bullets use - not •, method steps start at column 1.
The canonical taxonomy list is embedded in PROMPTS.md directly — every valid spirit, style, glassware, and AI model value. If a bottle or style isn’t on the list, the model is instructed to pick the closest match and flag the gap in ## Notes so I can decide whether to add it.
The Lint Script
The prompts reduce drift; they don’t eliminate it. Models still occasionally invent values (whiskey instead of bourbon, champagne-flute instead of flute). The drift is subtle and accumulates silently unless you check.
scripts/lint-recipes.sh is the check. It reads every recipe file under content/recipes/, extracts the taxonomy arrays from the frontmatter, and validates each value against the canonical set:
check_array "$f" "spirits" "$SPIRITS"
check_array "$f" "styles" "$STYLES"
check_array "$f" "glassware" "$GLASSWARE"
check_array "$f" "ai-models" "$AI_MODELS"
It exits 0 if everything’s clean and 1 with a list of offenders if not. Running it after an import batch catches model drift before a non-canonical taxonomy value creates a /spirits/whiskey-sour/ 404 page.
The canonical list in the lint script is a duplicate of the one in PROMPTS.md. That redundancy is load-bearing — it means adding a new value requires updating both files, which is slightly annoying but ensures neither can drift relative to the other.
AI Attribution as Taxonomy
The ai-models field was the most deliberate design choice. It would have been easy to omit it — the recipes are the point, not the models that generated them. But I wanted to know which model I’d been working with for a given drink, and browsing by model turned out to be genuinely useful.
GPT-5 tends toward classic frameworks — it reaches for Negroni riffs and Last Word variations, with precise ratios and careful balance. Gemini 2.0 Flash is faster and looser, more willing to combine unusual bottles in ways that either work or don’t. Claude leans into narrative — the Story sections it writes tend to be longer and more specific about the arc of the conversation. None of these are authoritative claims; they’re impressions from 135 data points. But the taxonomy makes those impressions testable in a way they wouldn’t be otherwise.
A recipe can carry multiple model attributions when it evolved across more than one chat. The amaro-nonino batch was a genuine collaboration between Gemini 2.0 Flash and Gemini 3 Flash — the first session established the ratios, a later session with a different model refined the garnish. Both got credited.
What Didn’t Work at First
The doubled method numbering. When converting existing recipes from chat transcripts, models would occasionally produce method steps already numbered in the source text, then wrap them in a numbered list — yielding 1. 1. Combine.... A cleanup pass (Fix: strip doubled method numbering in 17 chat.txt recipes) fixed the existing files, but I should have caught it in the prompt rules earlier.
Draft management is more friction than it needs to be. Imported recipes come in as draft = true so I can review before publishing; flipping them to published requires editing each file. For small batches this is fine, but a batch of 52 GPT-5 recipes (one commit was exactly that) meant manually reviewing and publishing dozens of files. A small script that flips drafts in bulk, with a preview step, would have saved time.
The taxonomy expansion path is slightly awkward. Adding a new value means editing PROMPTS.md, editing lint-recipes.sh, and remembering to tell the current prompt session about the new value so it uses it going forward. It’s three places instead of one.
Where It Is Now
135 recipes, across gin, rum, tequila, mezcal, bourbon, rye, and a long tail of amari and obscure liqueurs. The filter bar on the homepage lets you narrow by spirit, style, or glassware. There’s a zero-proof section. Every recipe has a Story that explains where it came from.
The site is a useful thing — I can find the drink I made in January, share a recipe, browse by what’s in the cabinet. But it’s also a record of what AI-assisted creative work actually looks like when you take it seriously enough to keep notes. The schema, the prompts, and the lint script are the interesting artifact. The cocktails are just what came out.
The schema and prompts are the reusable part — adapt them for any catalog where you want structured, consistent output from an AI across a large number of entries.