Official ordering site for Xoli's Bakery — Fresh Everyday, Mmabatho, South Africa.
Built with React + Vite. Browse the menu, build an order with pack-size pricing, review it on a dedicated cart page, and send it straight to WhatsApp for pickup.
- React 18 + Vite
- React Router for client-side routing
- react-helmet-async for per-page SEO tags + JSON-LD structured data
- Plain CSS (no framework) — design tokens in
src/index.css, matching the bakery's own flyer/logo palette
public/
images/ real product + hero photos, logo
robots.txt crawler rules (explicitly allows major AI crawlers, disallows /cart)
sitemap.xml indexable routes
llms.txt plain-text business/menu summary for AI assistants (llms.txt convention)
src/
components/ Navbar, Footer, Seo, MenuItemCard, MenuSection, FindSection
context/ CartContext (cart state + localStorage persistence)
data/ menu.js — single source of truth for items, pricing, business info
pages/ Home, Cart, About, NotFound
App.jsx route definitions
main.jsx app entry (Router, Helmet, Cart providers)
This site exists to sell, so the full menu (MenuSection) and contact/location
details (FindSection) render directly on the homepage — a visitor sees
pricing and can start ordering without navigating anywhere. /menu and
/find-us are kept as redirects to /#menu and /#find so any existing
links or bookmarks still land in the right place.
/cart is its own route, not a sidebar widget. The navbar always shows a
live item count linking to it. Adding items on the homepage menu never
forces the cart into view — people review and check out on their own terms,
then send the order to WhatsApp with their name and pickup day attached.
- Per-page
<title>, meta description, canonical URL, Open Graph + Twitter tags viaSeo.jsx - JSON-LD structured data:
Bakeryschema on the home page with a fullOfferCatalogof every menu item and its pack pricing, plus per-itemitemPropmicrodata on the menu cards themselves /cartis markednoindex(standard practice — transactional pages shouldn't rank)robots.txtexplicitly allows major AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot) so assistants can read and cite accurate menu/pricing/contact infollms.txtat the site root gives AI assistants a clean, structured summary of the business — an emerging convention alongside robots.txt/sitemap.xml- Real
<img alt>text, semantic HTML (<address>,<main>,<nav>, heading hierarchy)
Note on rendering: this is a client-rendered SPA. index.html ships with
solid baseline meta tags and fallback content so basic crawlers see real
content immediately, and react-helmet-async updates tags per route for
JS-executing crawlers (which is most of them today, including Google and the
major AI crawlers). If you want maximum crawlability later, the next step up
is pre-rendering/SSG (e.g. moving to Next.js or Astro, or adding a
prerender build step) — happy to help with that migration when it's needed.
- Confirm postal code in
src/data/menu.js(BUSINESS.address.postalCodeis a placeholder) - Confirm all menu prices are current
- Confirm the map pin in
FindSectionlands on the right building (it geocodes the address text — no hardcoded coordinates yet) - If a custom domain is added later, update
SITE_URLinsrc/components/Seo.jsx,baseinvite.config.js, and the URLs inpublic/sitemap.xml,public/robots.txt,public/llms.txt, andindex.htmlto match - Swap placeholder
og:image/ social preview if a better hero photo becomes available
npm install
npm run dev # start local dev server
npm run build # production build to dist/
npm run preview # preview the production build locally
npm run lint # lint the sourceThis repo is configured to deploy automatically to GitHub Pages at
https://codevenientlab.github.io/Xoli-s-Bakery/ every time main is
pushed, via .github/workflows/deploy.yml.
One-time setup after the first push (GitHub won't build anything until this is set):
- Push this repo to
https://github.com/CodevenientLab/Xoli-s-Bakery(see below) - On GitHub: Settings → Pages → Build and deployment → Source → select GitHub Actions
- Push (or re-run the workflow from the Actions tab) — the site builds and deploys automatically. First deploy takes a couple of minutes; watch progress under the Actions tab.
- The live site will be at https://codevenientlab.github.io/Xoli-s-Bakery/
Because GitHub Pages has no server-side rewrite rules, a client-side router
like this one needs a workaround for direct links / refreshes on routes
like /cart — that's what public/404.html + the decoder script in
index.html handle (the standard
spa-github-pages technique).
No action needed, it's already wired up — just don't remove either file.
If this ever moves to a different host (Netlify, Vercel, Cloudflare Pages,
a custom domain, etc.), those hosts handle SPA fallback natively via their
own config (e.g. Netlify's _redirects with /* /index.html 200), so the
404.html trick and the base path in vite.config.js can be simplified
back down at that point — happy to help with that migration when needed.
git remote add origin https://github.com/CodevenientLab/Xoli-s-Bakery.git
git push -u origin main(This repo already has an initial commit — git init/git commit aren't
needed again unless starting fresh.)