mirror of
https://github.com/runyanjake/cooking.git
synced 2026-03-26 01:43:17 -07:00
cooking
A content-first personal recipe site. No popups, no life stories — just recipes.
Live site: recipes.whitney.rip
Stack
- Next.js 15 (App Router, SSG, standalone output)
- TypeScript + Tailwind CSS
- MDX with YAML frontmatter for recipe content
- next-mdx-remote/rsc + remark-gfm for server-side MDX compilation
- No database — recipes are MDX files on disk
Project Structure
app/ # Next.js App Router pages
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 SVGs
authors.json # Author metadata
recipes/ # All recipe content (MDX + images colocated)
[category]/
[slug]/
[slug].mdx
assets/
hero.jpg
Adding a Recipe
- 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
Frontmatter
---
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.
Content Structure
Wrap recipe content in <RecipeCard> — ## headings inside it become tabs:
Intro prose (rendered above the card).
<RecipeCard>
## Photos

*Caption text*
## Ingredients
- 1 cup lentils
## Instructions
1. Rinse and cook.
## Notes
Optional tips.
## References
Optional credits.
</RecipeCard>
Development
npm install
npm run dev # http://localhost:3000
npm run build
npm run lint
Docker
Build and run with Docker Compose (deploys behind a Traefik reverse proxy):
docker compose up -d --build
To rebuild from scratch:
docker compose down && docker system prune -f && docker compose up -d --build && docker logs -f recipes
The container runs on port 3000. Traefik handles TLS termination via Let's Encrypt.
Description
Languages
MDX
67.2%
TypeScript
32%
Dockerfile
0.4%
CSS
0.3%
JavaScript
0.1%