I've edited this post, but AI helped. These are meant to be quick posts related to the Advent of AI. I don't have time if I'm doing one of these each day to spend a couple hours on a post.
For Advent of AI Day 10, I built a festival poster generator using Goose recipes. But this post isn't really about making posters. It's about understanding how recipe arguments and conditional logic turn static prompts into reusable AI workflows.
Up until now in the Advent of AI challenges, I'd been using recipes pretty simply. Pass in some parameters, get output.
But Day 10 made me dig deeper into what's actually happening under the hood with arguments and Jinja templating.
The advent of AI series leverages Goose, an open source AI agent. If you've never heard of it, check it out!
block
/
goose
an open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM
goose is your on-machine AI agent, capable of automating complex development tasks from start to finish. More than just code suggestions, goose can build entire projects from scratch, write and execute code, debug failures, orchestrate workflows, and interact with external APIs - autonomously.
Whether you're prototyping an idea, refining existing code, or managing intricate engineering pipelines, goose adapts to your workflow and executes tasks with precision.
Designed for maximum flexibility, goose works with any LLM and supports multi-model configuration to optimize performance and cost, seamlessly integrates with MCP servers, and is available as both a desktop app as well as CLI - making it the ultimate AI assistant for developers who want to move faster and focus on innovation.
Quick Links
Need Help?
The Problem I Was Solving
The Day 10 challenge asks you to generate festival posters. Not just one poster, but posters for different event types. Food events need warm, cozy vibes. Kids events need bright, playful energy. Performance events need elegant styling.
Without parameters, you're writing separate prompts for each type. That's tedious and doesn't scale. With parameters and conditional logic, you write one recipe that handles all of them.
How Recipe Parameters Work
Goose recipes let you define inputs just like function parameters. You specify what can change, and users provide those values when they run the recipe.
Here's the basic setup:
version: 1.0.0
title: Festival Poster Generator
description: Generate themed HTML posters with conditional styling
parameters:
- key: event_name
input_type: string
requirement: required
description: Name of the festival event
- key: event_type
input_type: select
requirement: required
description: Type of event - determines theme and styling
options:
- food
- kids
- performance
- competition
- workshop
- key: tagline
input_type: string
requirement: optional
description: Optional tagline or subtitle
default: ""
Required vs Optional
Required parameters are non-negotiable. You can't generate a poster without knowing the event name, date, location, and type. The recipe won't run if these are missing.
Optional parameters add flexibility. A tagline is nice to have, but if you don't provide one, the recipe still works. Setting default: "" means optional parameters become empty strings when not provided, which is perfect for conditional logic later.
Conditional Logic with Jinja
This is where it gets really good. The instructions section of a recipe supports Jinja2 templating. That means you can write logic that changes what the AI actually sees based on the parameters you pass in.
For the poster generator, the entire styling instructions change based on event_type:
instructions: |
You are a festival poster generator.
**Event Details:**
- Event Name: {{ event_name }}
- Date & Time: {{ event_datetime }}
- Location: {{ location }}
- Event Type: {{ event_type }}
{% if tagline %}- Tagline: {{ tagline }}{% endif %}
{% if description %}- Description: {{ description }}{% endif %}
{% if event_type == "food" %}
## Food Event Theme
- Use warm, inviting colors (burgundy, warm orange, cream)
- Typography: Friendly, rounded fonts
- Mood: Cozy, appetizing, welcoming
{% endif %}
{% if event_type == "kids" %}
## Kids Event Theme
- Use bright, playful colors (rainbow palette, pastels)
- Typography: Playful, bold, easy-to-read fonts
- Mood: Fun, energetic, joyful
{% endif %}
Same recipe, completely different instructions sent to the AI depending on what event_type you provide. That's the power of this approach.
What This Actually Does
When you run the recipe with event_type: food, the AI gets instructions about warm colors and cozy vibes. Run it with event_type: kids, and it gets instructions about bright colors and playful energy.
The AI doesn't see both sets of instructions. It only sees the one that matches your event type. That's way better than trying to cram all the logic into a single prompt and hoping the AI picks the right path.
Useful Jinja Patterns
Variable Interpolation
The basic {{ variable_name }} syntax injects parameter values:
instructions: |
Create a poster for {{ event_name }} on {{ event_datetime }}.
Conditional Blocks
{% if condition %} lets you include or skip entire sections:
{% if tagline %}
Make the tagline prominent: {{ tagline }}
{% endif %}
{% if not description %}
Since no description was provided, create a brief one.
{% endif %}
I used this a lot for optional parameters. If someone provides a tagline, include it. If not, skip that section entirely.
String Manipulation
Jinja filters let you transform values on the fly:
Save to: poster_{{ event_type }}_{{ event_name | lower | replace(" ", "_") }}.html
This converts "Hot Cocoa Tasting" to "hot_cocoa_tasting" automatically. Super useful for file names.
Combining Conditions
You can get fancy with multiple conditions:
{% if event_type == "performance" and ticket_info %}
Display ticket info with elegant styling: {{ ticket_info }}
{% elif event_type == "kids" and not ticket_info %}
Add "Free admission - all families welcome!"
{% endif %}
Why This Matters
With parameters and conditional logic, you write once and reuse forever.
For the Day 10 challenge, I can generate posters for all the different festival events just by changing the parameters:
# CLI
goose run festival-poster-generator \
--event_name "Hot Cocoa Tasting" \
--event_datetime "December 15, 2pm–4pm" \
--location "Main Plaza" \
--event_type food
Want a kids event? Same recipe, different parameters:
goose run festival-poster-generator \
--event_name "Storytelling Hour" \
--event_datetime "December 17, 3pm–4pm" \
--location "Story Tent" \
--event_type kids
In Goose Desktop, you get a form UI with dropdowns for the event type and text inputs for everything else. Way nicer than typing command-line args.
The real win is consistency. All the posters follow the same structure and quality standards because they're coming from the same recipe. The only thing that changes is the data and the conditional styling.
Beyond Posters
The Day 10 challenge is about posters, but these patterns work for any repetitive AI task.
I've been using Goose recipes for all sorts of stuff during Advent of AI:
- Data transformation (Day 8: messy vendor data to structured JSON)
- GitHub automation (Day 6: issue triage and labeling)
- UI generation (Day 4: festival website with theme switching)
Each one follows the same pattern. Define what varies (parameters), write conditional logic for different paths (Jinja), run it as many times as you need.
For work at Pomerium, I could see this being useful for generating security policies or MCP server configurations with different auth providers and policy levels. Same recipe, different security postures based on parameters.
Things I Learned
Start Simple
Don't try to make everything configurable on day one. Figure out the 3-5 things that actually need to vary, make those parameters, and ship it. You can always add more later.
Use Select Types When You Can
For the event type, I used input_type: select instead of a freeform string. This prevents typos and makes the conditional logic reliable. If someone can only pick from "food", "kids", "performance", etc., you don't have to worry about handling "Food" vs "food" vs "FOOD".
Provide Defaults for Optional Stuff
For optional parameters, think about what makes sense when nothing is provided:
- key: output_format
input_type: select
requirement: optional
default: html
options:
- html
- markdown
Most people probably want HTML, so default to that.
Test All the Paths
With conditional logic, you're creating multiple execution paths. I made sure to test:
- All five event types to confirm each conditional branch works
- Optional parameters both provided and omitted
- Edge cases like really long event names
Check the Docs
The Recipe Parameters docs list all the input types and validation options. Reference these when you're setting up parameters instead of guessing.
Reference Docs
Everything here is documented officially:
- Recipe Guide - Overview of how recipes work
- Recipe Reference - Complete spec
- Recipe Parameters - All parameter types
- Jinja2 Docs - Full templating syntax
I referenced these docs a lot while building the poster recipe.
Wrapping Up
Parameters and conditional logic turn recipes from one-off tools into reusable workflows.
Instead of "make me a poster", it becomes "here's a poster recipe that adapts based on what you need". Run it once, run it a hundred times, same quality every time.
The Day 10 challenge is a good intro to these concepts. You get to see how the same recipe generates five completely different poster themes just by changing one parameter. But the real learning is recognizing when you could apply this pattern to your own work.
What repetitive tasks are you doing with AI right now? What parts change each time? Those changing parts are your parameters. The logic that decides what to do with those parameters? That's your Jinja conditionals.
Check out the Day 10 challenge if you want to try building one yourself.
If you want to stay in touch, all my socials are on nickyt.online.
Until the next one!
Resources:
- Advent of AI - Day 10 Challenge
- Goose Recipe Guide
- Recipe Parameters Documentation
- Jinja2 Templating
Photo by Sven Mieke on Unsplash



Top comments (0)