A content-first personal recipe site.
Live site: recipes.whitney.rip
- Next.js, TypeScript + Tailwind CSS
- MDX with YAML frontmatter metadata.
- next-mdx-remote/rsc + remark-gfm for server-side compilation/rendering.
- No database — recipes are checked into the repo.
app/
page.tsx # Homepage
recipes/
page.tsx # Recipe listing with search/filter
[category]/[slug]/
page.tsx # Recipe detail page
components/ # UI components
lib/
recipes.ts # Recipe loader (reads from public/recipes/)
public/
assets/ # Site-level data.
authors.json # Author metadata
recipes/ # All recipe content (MDX + images colocated)
[category]/
[slug]/
[slug].mdx
assets/
hero.jpg
- Create a folder:
public/recipes/[category]/[recipe-slug]/ - Add
[recipe-slug].mdxwith frontmatter and content - Create an
assets/subfolder and add images - Reference images with relative paths:
./assets/image.jpg
---
title: "Recipe Title"
slug: "recipe-slug"
date: "YYYY-MM-DD"
lastUpdated: "YYYY-MM-DD"
category: "mains"
tags: ["italian", "chicken"]
cookTime: 45
prepTime: 20
servings: 4
author: "PWS"
description: "Short description for SEO and previews"
featured: false
display: true
displayPhoto: "./assets/hero.jpg"
---display: false hides a recipe without deleting it. Author IDs reference public/authors.json. Categories and tags are free-form strings — no taxonomy file to keep in sync.
Wrap recipe content in <RecipeCard> — ## headings inside it become tabs:
Intro prose (rendered above the card).
<RecipeCard>
## Photos

*Caption text*
## Ingredients
- 1 cup short grain rice
## Instructions
1. Rinse and cook.
## Notes
Optional tips.
## References
Optional credits.
</RecipeCard>npm install
npm run dev # 3000
npm run build
npm run lintdocker compose down && docker system prune -f && docker compose up -d --build && docker logs -f recipes