import { ArrowRight, BookHeart, Flame, ReceiptText, SlidersHorizontal } from "lucide-react"; import Link from "next/link"; import { OverlapExplorer, type OverlapComboSnapshot, type OverlapDish } from "./components/OverlapExplorer"; import { RotatingPreview, type PreviewSet } from "./components/RotatingPreview"; import { Logo, SiteHeader } from "./components/SiteHeader"; import { CATALOG, PANTRY_STAPLE_IDS } from "./lib/catalog"; import { buildGroceryList } from "./lib/grocery"; import { APPLIANCES, CUISINES } from "./lib/plan"; import { RECIPES } from "./lib/recipes"; import { formatUsd } from "./lib/units"; // --------------------------------------------------------------------------- // Landing page (server component, fully static). // // Every statistic, menu preview, and interactive overlap combination is // derived from the real recipe & store catalog at build time so zero catalog // payload needs to ship to the landing-page client bundle. // --------------------------------------------------------------------------- const DEMO_RECIPE_IDS = ["chicken-curry", "red-lentil-dal", "chana-masala", "garlic-butter-shrimp-and-rice"] as const; const OVERLAP_DATA = (() => { const options = { householdSize: 2, onHandItems: PANTRY_STAPLE_IDS }; const dishes: OverlapDish[] = DEMO_RECIPE_IDS.map((id) => { const r = RECIPES.find((x) => x.id === id)!; const cuisineLabel = CUISINES.find((c) => c.id === r.cuisine)?.label ?? r.cuisine; return { id, title: r.title, cuisine: `${cuisineLabel} · ${r.prepTime} min`, standaloneCheckout: buildGroceryList([id], options).checkoutTotal, }; }); const combos: Record = {}; const totalMasks = 1 << DEMO_RECIPE_IDS.length; for (let mask = 1; mask < totalMasks; mask++) { const picked = DEMO_RECIPE_IDS.filter((_, idx) => (mask & (1 << idx)) !== 0); const key = [...picked].sort().join(","); const summary = buildGroceryList(picked, options); combos[key] = { checkoutTotal: summary.checkoutTotal, usedTotal: summary.usedTotal, carryoverValue: summary.carryoverValue, sharedNames: summary.lines.filter((l) => l.usedBy.length > 1 && !l.onHand).map((l) => l.item.name), packageCount: summary.lines.length, }; } return { dishes, combos }; })(); const PREVIEW_THEMES: { theme: string; blurb: string; meals: [slot: string, recipeId: string][] }[] = [ { theme: "Comfort classics", blurb: "Cozy & thrifty", meals: [["Mon · Dinner", "chicken-pot-pie"], ["Tue · Lunch", "chicken-noodle-soup"], ["Tue · Dinner", "beef-stroganoff"]] }, { theme: "Shared spice rack", blurb: "High overlap", meals: [["Mon · Dinner", "chicken-curry"], ["Tue · Lunch", "red-lentil-dal"], ["Tue · Dinner", "pad-thai"]] }, { theme: "Weeknight seafood", blurb: "Budget catch", meals: [["Mon · Dinner", "garlic-butter-shrimp-and-rice"], ["Tue · Lunch", "tuna-chickpea-pitas"], ["Tue · Dinner", "baja-fish-tacos"]] }, { theme: "Dorm & studio kitchen", blurb: "Microwave + rice cooker", meals: [["Mon · Breakfast", "berry-banana-smoothie"], ["Mon · Lunch", "microwave-buffalo-chicken-rice-bowls"], ["Mon · Dinner", "rice-cooker-arroz-con-pollo"]] }, { theme: "Plant-forward week", blurb: "Meatless & filling", meals: [["Mon · Breakfast", "shakshuka"], ["Mon · Lunch", "chana-masala"], ["Mon · Dinner", "black-bean-enchiladas"]] }, { theme: "Sunday batch prep", blurb: "Cook once, eat well", meals: [["Breakfasts", "baked-oatmeal-squares"], ["Lunches", "slow-cooker-salsa-chicken"], ["Dinners", "chicken-burrito-bowls"]] }, { theme: "Korean pantry week", blurb: "One tub of gochujang", meals: [["Mon · Dinner", "bulgogi-beef-bowls"], ["Tue · Lunch", "kimchi-fried-rice"], ["Tue · Dinner", "dakgalbi-spicy-chicken-stir-fry"]] }, ]; const PREVIEW_SETS: PreviewSet[] = PREVIEW_THEMES.map(({ theme, blurb, meals }) => { const options = { householdSize: 2, onHandItems: PANTRY_STAPLE_IDS }; const recipe = (id: string) => { const found = RECIPES.find((r) => r.id === id); if (!found) throw new Error(`Landing preview: unknown recipe id "${id}"`); return found; }; const cart = buildGroceryList(meals.map(([, id]) => id), options); return { theme, blurb, meals: meals.map(([slot, id]) => ({ slot, title: recipe(id).title, cost: formatUsd(buildGroceryList([id], options).usedTotal) })), total: formatUsd(cart.checkoutTotal), sharedItems: cart.sharedItemCount, itemCount: cart.lines.length, }; }); const STEPS = [ { num: "01", title: "Set your register target", body: "Choose a weekly grocery ceiling, 1–7 days, meals per day, and household size. Ingredient quantities scale automatically.", }, { num: "02", title: "Match your real kitchen", body: "Toggle only the appliances you own—stovetop, air fryer, rice cooker, microwave. Exclude allergens or mark items already on your shelf.", }, { num: "03", title: "Pack the week with overlap", body: "Auto-fill prioritizes dishes that share open packages of produce, dairy, and aromatics—or pick slot-by-slot sorted by marginal cart cost.", }, { num: "04", title: "Walk the aisles once", body: "Export one consolidated list grouped by store aisle, priced in whole packages the way checkout actually charges.", }, ]; const FAMILY_COUNT = RECIPES.filter((r) => r.styles.includes("caydens_corner")).length; export default function LandingPage() { return (
{/* --- Editorial Hero ------------------------------------------------ */}

Weekly Meal & Grocery Ledger · Saved Locally

Cook a full week around{" "} what groceries actually cost at checkout.

Most meal planners divide a pinch of cumin into imaginary pennies. Plan my Meals prices whole store packages, pairs recipes that share ingredients, and filters strictly to the appliances on your counter.

Start this week's plan Browse {RECIPES.length} recipes
{/* Architectural Ledger Metrics */}
Tested recipes
{RECIPES.length}
Global cuisines
{CUISINES.length}
Appliances
{APPLIANCES.length}
Priced items
{CATALOG.length}
{/* --- Interactive Package Overlap Proof ---------------------------- */}

Why the math matters

Built for the checkout lane, not fictional per-gram math

{/* Three concise architectural pillars */}

Whole-package register totals

You can't buy 0.3 lb of rice. Every ingredient rounds up to real store packages, showing both what you pay today and what carries over into next week's pantry.

Appliance-honest filtering

Cooking in a dorm or studio without an oven? Uncheck it once and every suggested recipe is guaranteed to work on the gear you actually own.

Three-way pantry control

Mark any store item as Have it ($0 at checkout),{" "} Use, or Avoid{" "} across an entire aisle like Seafood or Dairy.

{/* --- Exposed-Border Workflow Ledger ------------------------------- */}

How it works

Four steps from weekly budget to aisle-sorted list

    {STEPS.map((step) => (
  1. {step.num}

    {step.title}

    {step.body}

  2. ))}
{/* --- Editorial Cuisines & Cayden's Corner Spotlight --------------- */}

On the menu

{CUISINES.length} cuisines, from quick weeknight bowls to slow Sunday braises

    {CUISINES.map((c) => (
  • {c.label}
  • ))}
Explore the full {RECIPES.length}-recipe index
{/* Heirloom Collection Card */}
Heirloom Collection

Cayden's Corner

{FAMILY_COUNT} tried-and-true homemade family recipes—holiday sides, comfort mains, and classic bakes—scaled automatically to your table and integrated right into the weekly planner.

Open family cookbook
); }