mirror of
https://github.com/runyanjake/cooking.git
synced 2026-09-25 12:48:40 -07:00
2.2 KiB
2.2 KiB
Component Architecture
State and Data Flow
- RecipeLayout owns sidebar open/close state; passes
handleFilterChange(memoised withuseCallback) down to RecipesSidebar - RecipesSidebar owns local UI state (debounced search input, tag filter text, show-more toggles) and reports filter changes via
onFilterChange - RecipesClient owns filter state (synced to the URL), the filtered recipe list, and facet counts (all memoised with
useMemo). Each facet's counts apply every filter except its own; options with zero results are hidden - ActiveFilters renders removable chips for the active filters above the results grid
- Recipe page gets the parsed
RecipeContentfromgetRecipeContent(cached), renders each section with RecipeMarkdown (server), and passes them as tabs to RecipeTabs (client). All panels are in the HTML; inactive ones arehidden - Recipe card:
getRecipeCardImagescomputes the layout once per recipe; the page and thecard/[image]route both use it, so the tab always matches the generated files. Layout measures real block heights with satori'sonNodeDetected, so fitting is exact, not estimated
Known Constraints
- Recipe image URLs are
/recipes/[category]/[slug]/assets/...(from frontmatter, not the folder on disk). UseresolveRecipeAssetUrlfromlib/recipe-urls.ts— never build them fromfolderPath, which can differ from category/slug and uses backslashes on Windows - Recipe detail and asset routes set
dynamicParams = false; everything is prerendered and the runtime image doesn't shiprecipes/ - Paragraphs containing only images are converted to
<figure>elements during parsing (caption from the image title), so there's no<p><figure>nesting - Card fonts are read from
node_modules/@fontsource/*at build time; satori needs woff/ttf (not woff2) and doesn't support variable fonts lib/recipes.tsuses Node.jsfs— server-side only; never import in client components- Build warnings about
<img>vs<Image />in RecipeMarkdown and RecipeCardPanel are intentional - Never add redundant ARIA roles on semantic elements (
<main>,<aside>,<footer>already carry implicit roles)