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 (18.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 and generate data
- For development, run the generator once to create
src/generated/recipes.json
:yarn generate
yarn install # or npm install
- For development, run the generator once to create
- Start the development server (with HMR) — ensure
src/generated/recipes.json
exists (useyarn generate
)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
yarn start
– Run webpack-dev-server with hot reloadyarn watch
– Rebuild on file changes (without dev server)yarn build
– Create a production build indist/
(runs static data generation first)yarn deploy
– Publishdist/
to thegh-pages
branch usinggh-pages
yarn build
# or
npm run build
The optimized static assets will be emitted to dist/
. Serve that folder with any static file server. Pre-rendered static pages are under dist/static/
.
This repo uses GitHub Actions to build and deploy on pushes to main
.
- Workflow:
.github/workflows/webpack-deploy.yml
- The action runs
yarn build
and then deploysdist/
to GitHub Pages usinggh-pages
.
You can also deploy locally (requires push access):
yarn build
yarn deploy
- Routing uses
react-router-dom
(v6). The dev server is configured withhistoryApiFallback
so deep links work locally. webpack.config.ts
readsHOST
andPORT
from 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.json
. 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 SPA continues to work normally, and users without JavaScript get the same UI via the pre-rendered HTML.- 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)
util/ # Helper utilities (GitHub fetch wrappers)
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
PORT
when starting, e.g.PORT=4001 yarn start
. - Blank page on refresh in production: ensure GitHub Pages is serving the
gh-pages
branch; client-side routing relies onindex.html
being returned for unknown paths.
Questions or issues? Please open an issue or a pull request.