Skip to content

Repository files navigation

Xoli's Bakery

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.

Tech stack

  • 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

Project structure

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)

The menu sells from the landing page, not behind a click

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 a real page

/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.

SEO & AI-SEO

  • Per-page <title>, meta description, canonical URL, Open Graph + Twitter tags via Seo.jsx
  • JSON-LD structured data: Bakery schema on the home page with a full OfferCatalog of every menu item and its pack pricing, plus per-item itemProp microdata on the menu cards themselves
  • /cart is marked noindex (standard practice — transactional pages shouldn't rank)
  • robots.txt explicitly allows major AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot) so assistants can read and cite accurate menu/pricing/contact info
  • llms.txt at 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.

Before going live

  • Confirm postal code in src/data/menu.js (BUSINESS.address.postalCode is a placeholder)
  • Confirm all menu prices are current
  • Confirm the map pin in FindSection lands on the right building (it geocodes the address text — no hardcoded coordinates yet)
  • If a custom domain is added later, update SITE_URL in src/components/Seo.jsx, base in vite.config.js, and the URLs in public/sitemap.xml, public/robots.txt, public/llms.txt, and index.html to match
  • Swap placeholder og:image / social preview if a better hero photo becomes available

Local development

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 source

Deploying — GitHub Pages (this repo's setup)

This 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):

  1. Push this repo to https://github.com/CodevenientLab/Xoli-s-Bakery (see below)
  2. On GitHub: Settings → Pages → Build and deployment → Source → select GitHub Actions
  3. 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.
  4. 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.

Pushing to GitHub

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.)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages