A full-stack recipe + resume web app with a Deno/Oak backend and a SolidJS/Vite frontend.
The app serves recipe data from Markdown front matter, renders recipe detail pages, exposes build metadata, and includes a dedicated resume page.
- Browse all recipes on the home page.
- Open recipe detail pages with ingredients, instructions, tips, timing, and estimated cost.
- View a resume page sourced from Markdown front matter.
- Surface deployment/build metadata from the backend (
commit,tag, compare URL). - Optionally track page views with Google Analytics (build-time opt-in).
- Backend: Deno + Oak HTTP API.
- Frontend: SolidJS SPA (Vite build), served by Nginx in Docker.
- Data source:
recipes/<slug>/recipe.md(+ optionalimage.jpg)resume/resume.md
- Container orchestration: Docker Compose with local, staging, and production overlays.
my-recipes-app/
├── backend/
│ ├── main.ts # API routes and app wiring
│ ├── server.ts # runtime entrypoint
│ ├── types.ts # recipe/resume TypeScript types
│ ├── utils/recipe.ts # recipe normalization logic
│ ├── tests/ # Deno tests (API + parsing behavior)
│ ├── deno.json # backend tasks/imports
│ └── Dockerfile
├── frontend/
│ ├── src/
│ │ ├── App.tsx
│ │ ├── components/ # layout/cards/resume display/spinner
│ │ ├── pages/ # Home, RecipeDetail, ResumePage
│ │ ├── lib/ # API client, analytics, route tracking, types
│ │ └── test/ # frontend test setup + mocks
│ ├── e2e/ # Playwright tests
│ ├── nginx.conf
│ ├── vite.config.ts
│ ├── vitest.config.ts
│ ├── playwright.config.ts
│ ├── package.json
│ └── Dockerfile
├── recipes/ # recipe content (folder per recipe)
├── resume/ # resume markdown data
├── docker-compose.yml # base services
├── docker-compose.local.yml # local ports/volumes
├── docker-compose.staging.yml # staging image + ports
├── docker-compose.prod.yml # production image + ports
├── dev-up.sh # build+run local stack with build metadata args
├── ci-up.sh # run stack from already-built images
├── package.json # root workspace/tooling scripts
└── .github/workflows/ # CI/CD/release automation
- Deno
2.6.x - Oak
v12.6.1 @std/front-matterfor YAML front matter extraction
| Endpoint | Method | Description |
|---|---|---|
/health |
GET |
Health check ({ status: "OK" }). |
/recipes |
GET |
Returns normalized recipe list from recipes/*/recipe.md. |
/recipes/:slug |
GET |
Returns one normalized recipe by slug. |
/recipes/:slug/image.jpg |
GET |
Serves recipe image from filesystem if present. |
/resume |
GET |
Returns parsed resume front matter from resume/resume.md. |
/build-info |
GET |
Returns gitCommit, gitTag, and compare URL for UI build info. |
For recipes, the backend normalizes missing fields with sensible defaults:
title: generated from slug if omitteddescription:""prepTime,cookTime,estimatedCost:0ingredients,instructions,tips:[]image: always exposed as/recipes/<slug>/image.jpg
Invalid recipe folders/files are skipped in the list endpoint instead of crashing the app.
- Routes:
/(recipe listing)/recipe/:slug(recipe details)/resume(resume page)
- Build-info dropdown in header links to release notes or commit compare URL.
- Loading states for async data fetches.
Analytics is disabled by default and enabled only at build-time when:
VITE_ANALYTICS_ENABLED=trueVITE_GA_MEASUREMENT_IDis set
When enabled, page views are tracked via route changes.
- Yarn Berry
4.12.0workspaces - ESLint + Prettier + TypeScript-ESLint
- SolidJS
1.9.x @solidjs/router- Vite
7.x - Tailwind CSS
4.x - Vitest + Testing Library
- Playwright (E2E)
- Deno task runner (
deno task) - Deno test runner (
deno test)
- Node
24.13.0(for workspace/frontend toolchain) - Yarn
4.12.0(via Corepack recommended) - Deno
2.x - Optional: Docker + Docker Compose
yarn installcd backend
deno task start
# http://localhost:3000cd frontend
yarn dev
# http://localhost:5173The frontend expects backend APIs under /api/* (via dev/proxy or containerized Nginx path mapping).
cd backend
deno task test
deno task test:coverage
deno task lint:check
deno task fmt:checkcd frontend
yarn test
yarn test:coverage
yarn lint:check
yarn format:checkyarn lint:check
yarn format:check./dev-up.shThis builds both services and injects build metadata (GIT_COMMIT, GIT_TAG, LATEST_TAG) plus local analytics defaults.
./ci-up.sh- Base:
docker-compose.yml - Local:
docker-compose.local.yml - Staging:
docker-compose.staging.yml - Production:
docker-compose.prod.yml
Create a new folder under recipes/:
recipes/my-new-recipe/
├── recipe.md
└── image.jpg # optional but expected by default image path
Example recipe.md:
---
title: My New Recipe
description: An amazing dish you'll love
prepTime: 15
cookTime: 30
estimatedCost: 12
ingredients:
- 2 cups flour
- 1 tsp salt
instructions:
- Mix everything
- Bake at 350°F
tips:
- Don't overmix!
---Edit resume/resume.md front matter fields used by the /resume endpoint and frontend resume renderer.
Made with ❤️ in Anna, Texas.