feat(web): recipe list and detail (PLAN §4.4 & §4.6)#18
Merged
Conversation
- Fetch GET /recipes via listRecipes + createResource; loading, error, and empty states. - Recipe cards with thumbnail, title, summary; navigate to /recipes/:id with router Link. - Vitest mock for ./api listRecipes so tests run without a live API. - Tick PLAN §4.4. Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Implements PLAN §4.4 by wiring the SolidJS home page to the typed GET /recipes client and rendering a navigable recipe list with loading/error/empty states.
Changes:
- Fetch recipes on the home page via
listRecipes+createResourceand render linked recipe cards. - Add page styles for recipe list states and card layout.
- Update web tests to mock
./apiso tests don’t require a running backend.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| PLAN.md | Marks PLAN §4.4 as completed. |
| apps/web/src/pages/Page.css | Adds styles for home lede, list states, and recipe card layout. |
| apps/web/src/pages/Home.tsx | Implements recipe fetching, UI states, and navigation to /recipes/:id. |
| apps/web/src/App.test.tsx | Mocks listRecipes to keep tests backend-independent. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add recipe detail page data loading and styles (PLAN §4.6); shared loaders - Enable API CORS for local Vite origins - Use @/ alias; Biome rules (arrows, explicit types, no default export) - Add Home.test.tsx with MemoryRouter; fix img dimensions for 4:3 cards - Update PLAN (§4.5 component library note); Cursor rule for path aliases Made-with: Cursor
Redoc requires the yaml package at runtime; pnpm does not hoist it. Aligns with REQUIREMENTS (no ^ or ~). Made-with: Cursor
Prefer relative same-folder imports for api barrel, entrypoint, layout, and pages; keep @/ for imports that would require ../ (Biome rule). Made-with: Cursor
- Replace async function exports and resolveBaseUrl with const arrows - Run assert-no-function-declarations.mjs after Biome (useArrowFunction does not cover top-level function declarations) - Add Cursor rule documenting the convention Made-with: Cursor
- Home: createResource uses listRecipes({ throwOnError: true })
- RecipePage: getRecipeById inline; guard with !id
- Remove loadRecipes/loadRecipeDetail; adjust Home error test for throws
Made-with: Cursor
Made-with: Cursor
- RecipeCard for home list items; RecipeDetailBody composes header, hero, ingredients, and steps - RecipePage renders RecipeDetailBody from loaded RecipeDetail Made-with: Cursor
Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Delivers PLAN §4.4 (home recipe list) and §4.6 (recipe detail), with supporting tooling and refactors on the SolidJS app and monorepo.
Features
listRecipeswiththrowOnError) andcreateResource; shows loading, error, and empty states; grid of linked cards (RecipeCard) to/recipes/:id.GET /recipes/{id}viagetRecipeByIdwiththrowOnError; full content composed fromRecipeDetailBody(header, hero image, ingredients, steps).CORSMiddlewarefor local Vite origins so the browser can call the API in dev.Developer experience
@/path alias (Vite + TS); BiomenoRestrictedImportsfor../**(same-folder./imports encouraged where possible).yaml@2.8.3in@solid-pact/openapiso Redocly/redocly lintresolves theyamlmodule under pnpm.useArrowFunction,useExplicitType,noDefaultExport, …);scripts/assert-no-function-declarations.mjsafter Biome (Biome does not flag top-levelfunctiondeclarations). Cursor rules for path alias and const-arrow style.Home.test.tsxmocks@/apilistRecipes;MemoryRouterfor<A>; error case uses thrownErrorto matchthrowOnErrorbehaviour.Refactors (high level)
listRecipes/getRecipeByIdfrom pages (no separatelibloaders); sharedapiClientwiring stays insrc/api/index.ts.RecipeCardandcomponents/recipe-detail/*extracted from page files; props destructured where useful.Checklist
pnpm --filter web lintpnpm --filter web testpnpm --filter web buildPLAN
PLAN.md.Made with Cursor