Creates beautiful, protein-focused weekly dinner menus for families with research capabilities...
Plans a week of protein-focused family dinners and emits a multi-page PDF: a stylized menu page followed by a categorized shopping list, recipe links, and kickoff notes.
These three steps are mandatory every time. Skipping any of them produces a worse menu.
ALWAYS ask the user which day the menu should start before doing anything else. A "week" is ambiguous — Monday-start vs. Sunday-start vs. "starting Thursday" all change the meal flow (e.g., where leftover days, pizza night, and restaurant night land).
Ask exactly this (or equivalent):
"Which day should this week's menu start on?"
Then ask the standing follow-ups (every time — these change the meal flow, not just flavor):
If the user has not answered the start-day question, do NOT proceed to research or planning. For the other follow-ups, pick a sensible default only if they explicitly decline ("you choose"): assume no late nights and no oversized leftover meals unless told otherwise.
Use web search every time, even if you "know" what's in season. Seasonality, trends, and recipe links must come from current sources, not memory.
Required searches before drafting the menu:
Capture the actual recipe URLs as you go — you will need them for the recipes page in step 4.
notes and the context page.The output PDF MUST contain, in order:
Because the menu page is single-page printable, keep meal name, protein, and notes short — long strings are truncated to fit. If you have a lot of leftover/repurposing detail, put it on the context page, not the meal note.
Pass all four pieces of data to scripts/generate_menu.py:
from scripts.generate_menu import create_menu_pdf
menu_data = {
'title': 'Family Dinner Menu',
'subtitle': 'Week of Nov 10, 2026',
'meals': [
{'day': 'Monday', 'name': '...', 'protein': '...', 'prep_time': '...', 'notes': '...'},
# ... 7 entries, in the order the user's week runs
],
'shopping_list': {
'Produce': ['Brussels sprouts (1 lb)', 'Lemon', ...],
'Proteins': ['Chicken breast (2 lb)', ...],
'Dairy & Eggs': [...],
'Pantry': [...],
'Frozen': [...],
'Bakery': [...],
'Beverages': [...],
'Other': [...],
},
'recipes': [
{'day': 'Monday', 'name': 'Grilled Chicken...', 'url': 'https://...', 'notes': 'optional'},
# one entry per recipe-driven meal (skip leftover/restaurant days)
],
'context': "Free-form notes: what's seasonal this week, prep-ahead tips,\n"
"leftover repurposing plan, restaurant reservation reminders, etc.",
}
design = create_menu_pdf(menu_data, '/path/to/output.pdf')
Use only these shopping list categories (the script orders them and ignores empty ones): Produce, Proteins, Dairy & Eggs, Pantry, Frozen, Bakery, Beverages, Other.
recipes[].url becomes a clickable link in the PDF — verify the URLs from your web search before passing them in.
| Mistake | Fix |
|---|---|
Generating the PDF with meals only, no shopping list / recipes / context |
All three companion fields are required. The companion pages are not optional. |
| Skipping the "which day" question because the user said "this week" | "This week" is ambiguous. Ask for the start day. |
| Skipping the late-nights / leftover-meal questions | Both are required follow-ups. They shape which nights get leftovers and which get a slow roast. |
| Scheduling a 45-minute weeknight cook on a night the user said they'd be working late | Move that cook to an earlier/lighter night and put leftovers, restaurant night, or a sheet-pan meal on the late night. |
| Building in oversized "cook-once-eat-twice" meals when the user didn't ask for them | Only do this when the user opted in. Otherwise size meals normally and let one batch meal naturally feed one leftover night. |
| Skipping web search because you remember what's in season | Seasonality drifts and recipe links rot — always search. |
| Inventing recipe URLs or reusing prior ones | Use only URLs you obtained from the current web search. |
| Putting ingredients in custom categories ("For pizza", "For Tuesday") | Use the standard grocery categories listed above. |
| Putting leftover/restaurant nights in the recipes list | Recipes page is for cookable recipes only. |
| Long meal names / notes that overflow the menu page | Keep menu-page text short. Move detail to the context page. The menu page is one printable sheet. |
create_menu_pdf without shopping_list, recipes, or contextAny of these means: stop, return to the Required First Steps, and do them in order.
scripts/generate_menu.py — PDF generator. Renders one stylized menu page (random theme from 9 designs) plus the three companion pages described above. The menu page is asserted to fit on a single 8.5" × 11" sheet.google/fonts) and cached under ~/.cache/family-menu-fonts/ — set FAMILY_MENU_FONT_CACHE to override. Subsequent runs are offline. There is no bundled fonts directory; if a download ever fails, that font silently falls back to Helvetica.