Live site: https://recipes.akofink.com
A React + TypeScript single-page app built with Webpack and deployed to GitHub Pages. Recipe content is sourced from the public repository https://github.com/akofink/recipes-md.
- Node.js LTS (22.x recommended). This repo includes an
.nvmrc; if you usenvm, runnvm use. - Yarn (v1) or npm. CI uses Yarn, examples below use Yarn, but npm works too.
- Git
- Clone and enter the repo
git clone https://github.com/akofink/recipes-ui.git cd recipes-ui - Use the recommended Node version (optional, if you use nvm)
nvm use # or install if needed nvm install - Install dependencies
yarn install # or npm install - Generate data and start the development server
- First, generate the recipe data:
yarn generate
- Then start the development server (with HMR):
By default the app serves on http://localhost:3000. You can override the host/port via environment variables when starting:
yarn start # or npm run start
PORT=4000 HOST=127.0.0.1 yarn start
- First, generate the recipe data:
yarn start– Run webpack-dev-server with hot reloadyarn watch– Rebuild on file changes (without dev server)yarn generate– Generate static data from recipes-md repository (createssrc/generated/recipes.jsonandsrc/generated/meta.json)yarn build– Create a production build indist/(automatically runsyarn generatefirst)yarn clean– Remove generated files and build output (src/generated/anddist/)yarn check– Run typecheck, lint, and format check (used in CI)yarn deploy– Publishdist/to thegh-pagesbranch usinggh-pages
yarn build
# or
npm run buildThe yarn build command automatically generates static data from the recipes-md repository and then creates an optimized production build. The static assets will be emitted to dist/. Serve that folder with any static file server. Pre-rendered static pages are under dist/static/.
Note: You don't need to run yarn generate manually before building - the build process handles this automatically.
This repo uses GitHub Actions to build and deploy automatically:
- Build workflow:
.github/workflows/build.yml- Runs on pull requests to validate builds - Deploy workflow:
.github/workflows/deploy.yml- Runs on pushes tomainand deploys to GitHub Pages - The deploy action runs
yarn buildand then uploads thedist/folder to GitHub Pages using the officialactions/deploy-pages@v4action
The deployment process includes:
- Build validation (typecheck, lint, format check)
- Production build with static data generation
- Upload to GitHub Pages artifact storage
- Deploy to the live site
You can also deploy locally (requires push access):
yarn build
yarn deploy- Routing uses
react-router-dom(v6). The dev server is configured withhistoryApiFallbackso deep links work locally. webpack.config.tsreadsHOSTandPORTfrom the environment if set.- Static data generation and prerender: At build time, a script fetches recipe metadata and markdown from the recipes-md repo and writes
src/generated/recipes.jsonplussrc/generated/meta.json(tracked upstream SHAs used for incremental builds). Whenmeta.jsonis missing or invalid, generation uses the initial recipes-md commit as the base for the compare API so the diff covers the full repo history. Then, the script uses React SSR (react-dom/server + StaticRouter) to prerender the real app UI to static HTML undersrc/generated/static/(copied todist/static/). The/staticsite is explicitly for no-JavaScript browsers to degrade gracefully, while the SPA continues to work normally.- Optional token: To avoid rate limits during generation, set
GITHUB_TOKEN(orGH_TOKEN/RECIPES_GITHUB_TOKEN) in your environment. - Incremental: The generator checks latest upstream commit SHAs for
recipes/andimages/paths and skips regeneration when unchanged (but still refreshes prerendered HTML from local data).
- Optional token: To avoid rate limits during generation, set
src/
components/ # Reusable UI building blocks
layouts/ # Route-level screens (recipes list, recipe detail, error)
services/ # Data fetching and business logic
util/ # Helper utilities
index.tsx # App entry; sets up router
App.tsx # Root component
routes.tsx # Route definitions
- ESLint and Prettier are configured. Example commands:
npx eslint src --ext .ts,.tsx npx prettier --check . npx prettier --write .
- Browserslist: caniuse-lite is outdated – this is informational. Update the local DB:
npx update-browserslist-db@latest
- Sass deprecations from Bootstrap – warnings about abs(), percentage units, or unitless values come from Bootstrap’s SCSS. They don’t break the build. They’ll be resolved in future Bootstrap releases. You can ignore them during development.
- Port already in use: set a different
PORTwhen starting, e.g.PORT=4001 yarn start. - Blank page on refresh in production: ensure GitHub Pages is serving the
gh-pagesbranch; client-side routing relies onindex.htmlbeing returned for unknown paths.
Questions or issues? Please open an issue or a pull request.