IGN Recipes is a Mushroom Kingdom–themed recipe catalog built with Payload CMS and Next.js App Router.
It demonstrates how editors manage Recipes and Foods in Payload while the frontend stays fast, simple, and on brand.
After completing the original assessment requirements, several production‑level enhancements were implemented to strengthen performance, UX, and maintainability. These updates reflect feedback from senior engineers and demonstrate continued learning beyond the initial scope.
- Implemented Payload’s
wherequery capability to perform server‑side filtering. - Replaced client‑side
.filter()logic with a real database query. - Added
qs-esmto serialize nested Payload query parameters. - Added database indexes on
titleanddescriptionfields for faster lookups. - Result: More accurate, scalable search aligned with real‑world API usage.
- Replaced all
<img>tags with Next.js<Image>across Recipes and Foods pages. - Added
remotePatternstonext.config.mjsfor Payload media. - Result: Faster page loads, reduced layout shift, and production‑ready image handling.
- Updated the Recipes list page to use the Payload GraphQL endpoint instead of the REST API, keeping the same server-side search semantics.
- Designed the GraphQL query shape to mirror Payload's
wherefilters so blank searches return all recipes and non-blank searches filter by title or description. - Added global metadata defaults in the Next.js App Router layout (title, description, Open Graph) plus per-recipe
generateMetadatafor dynamic titles, descriptions, and OG/Twitter tags. - Added canonical URLs and JSON-LD
Recipeschema on recipe detail pages so search engines can better index and potentially surface rich recipe results.
- Build a Payload CMS backend with two collections: Recipes and Foods
- Recipes must include:
- title
- description
- instructions
- ingredients (has-many Foods)
- quantity per ingredient
- Foods must include at least a name
- Build 3 public pages using Next.js:
- Recipe List
- Recipe Detail
- Food Detail (showing recipes that use that food)
- Optional: image support for Foods + Recipes
- Payload collections for Recipes and Foods
- Typed
hasManyrelationship for ingredients + quantities - Payload Media upload enabled
- Admin panel CRUD verified
/recipeslist view with images/recipes/[id]detail view with ingredient links/foodslist of ingredients/foods/[id]detail page showing all recipes using that food- Sorting, layout, and styling
- Mario-themed UI styling
- A–Z sorting
- Search bar for recipes
- Pre-populated Toadstool Café dataset
- Consistent theming across all pages
- Defining Payload collections and relationships in TypeScript
- Creating a typed
hasManyfield for ingredients with quantities - Writing a reusable seed script that creates linked collections
- Handling static images alongside Payload’s media uploads
- Building a Next.js App Router frontend that consumes Payload’s REST API
- Improving UX with search, sorting, navigation, and consistent theme work
Backend
- Payload CMS
- Payload Media Uploads
- SQLite (local dev)
Frontend
- Next.js App Router
- TypeScript
- Pico.css (global styling)
Tooling
- pnpm
- tsx (for seed runner)
- Node script to auto-ensure
.envexists for local dev
You'll need:
- Node.js v18+
- pnpm
git clone <repo-url>
cd ign-recipes-payload
pnpm installpnpm devVisit:
- Frontend: http://localhost:3000
- Admin: http://localhost:3000/admin
Note:
With a brand‑new database, the Recipes and Foods collections will be empty.
Nav links and search will not return results until you add data via the admin panel or run the seed script.
Open a new terminal window (leave pnpm dev running) and run:
pnpm seed:toadstoolThe following section is part of the original Payload template used to create this project.
It is kept here for completeness and setup reference.
This template comes configured with the bare minimum to get started.
- Clone repo
cd project && cp .env.example .env- Add
MONGODB_URIif using Mongo/S3 pnpm install && pnpm dev- Visit
http://localhost:3000
- Update
MONGODB_URIin.env - Run
docker-compose up - Login and create admin user
- Users – Auth-enabled admin users
- Media – Upload-enabled collection
For more, see:
https://payloadcms.com/docs/configuration/collections
If you have issues, reach out via Discord or GitHub Discussions.