Rough order — your teacher might want screenshots of each step.
Make folders: mkdir backend and mkdir frontend
React app: cd frontend then npx create-react-app . (or copy a package.json and run npm install)
Backend deps: cd backend then npm install
Inside backend: mkdir routes
Copy the files from below into the right places
Install deps: npm install in backend/, in frontend/, and once at the repo root (root has a small helper that runs both apps)
Reset empty DB: cd backend then node seed.js (wipes tables — no starter products)
Run both API and React from the repo root: npm run dev or npm start (API on port 5000, React on 3000). Alternatively run node server.js in backend/ and npm start in frontend/ in two terminals.
First time: register on Login, then add stock in Admin. Shop stays empty until you do. No card / payment step — not needed for the brief.
Vagrant setup
Tested with Vagrant 2.4.9. Guest VM should use Node 22.22.2 and npm 10.9.7 (or close — run node -v / npm -v inside the VM).
Put Vagrantfile and provision-vm.sh in the same folder as backend/ and frontend/ (repo root).
vagrant up — first boot installs Node via the provision script.
vagrant ssh then cd /vagrant (project is mounted there).
Ports 5000 and 3000 are forwarded to your Windows machine — open http://localhost:3000 in Edge/Chrome on the host.
Inside the VM: cd backend && npm install && node seed.js && node server.js in one terminal, and cd frontend && npm install && npm start in another (or use screen/tmux).
If the React dev server binds only to localhost inside the VM, that still works with Vagrant port forwarding.
If VirtualBox complains about VT-x, turn on virtualisation in BIOS or use WSL2 instead of Vagrant — same Node commands apply.
Backend: package.json
Use the npm package sqlite (Promise/async API for SQLite). It needs the sqlite3 driver package installed too so Node can talk to the SQLite engine. (That is not the same as using the old sqlite3 API everywhere in your routes — your code uses sqlite's db.all / db.get / db.run.) Skipping cors keeps the file small. On Windows, native modules may need Visual Studio Build Tools.
backend/package.json
Backend: database.js
SQLite database file grocery.db next to server.js. The sqlite package gives you await db.all(), await db.get(), and await db.run(). Pass sqlite3.Database as the driver when opening (that is the driver the sqlite docs use).
backend/database.js
Backend: server.js
Makes an uploads folder, serves files at /uploads/... so product photos work. Still no cors. initDatabase() is async, so routes load after the DB is ready.
backend/server.js
Backend: seed.js
Only clears tables — no fake stock. You add real rows through Admin so the marker can see you doing CRUD. Run again if you want a clean slate (wipes users too).
backend/seed.js
Backend: routes/products.js
REST API routes for products (async handlers). Uses await db.all() / await db.get() from the sqlite package. Supports filtering by category, searching by name, categories list, deals JOIN, and single product by ID.
backend/routes/products.js
Backend: routes/orders.js
Async routes: await db.all / await db.run. Fetches order history with items; new orders use result.lastID from db.run (not lastInsertRowid). Awards 1 point per whole pound spent.
backend/routes/orders.js
Backend: routes/users.js
Sign up / log in (async). Passwords plain text for a short demo. Redeem fixed at 100 points = £10 off. Registration uses result.lastID after await db.run.
backend/routes/users.js
Backend: routes/admin.js
POST /api/admin/upload with form field image returns { url: "/uploads/..." }. CRUD routes use await db.all / get / run and result.lastID on inserts.
backend/routes/admin.js
Frontend: package.json
React app dependencies. Uses react-router-dom for page navigation and react-scripts for the dev server and build tooling.
frontend/package.json
Frontend: public/index.html
The HTML shell. React mounts into the div with id "root".
frontend/public/index.html
Frontend: src/index.js
Entry point. Wraps the App in BrowserRouter (for routing), UserProvider and CartProvider (for global state).
frontend/src/index.js
Frontend: src/index.css
Global CSS reset. Removes default margins, sets the base font, and resets link/button/input styles.
frontend/src/index.css
Frontend: src/App.js
Navbar, routes, footer. Admin route is just another path.
frontend/src/App.js
Frontend: src/App.css
All the styles for the entire application — navbar, slide-out basket, footer, hero, product grid, cards, forms, checkout layout, auth pages, and responsive breakpoints. This is the longest file.
frontend/src/App.css
State Management: CartContext.js
React Context for the checkout basket. Provides addToCart, removeFromCart, updateQuantity, clearCart, plus computed cartTotal and cartCount values to all components.
frontend/src/context/CartContext.js
State Management: UserContext.js
React Context for the logged-in user. Persists user data to localStorage so the session survives page refreshes.
frontend/src/context/UserContext.js
Component: Navbar.js
Navigation bar with logo, page links (including Admin link), basket button with item count badge, and login/logout. Includes a slide-out panel with quantity controls and checkout links for delivery or collection.
frontend/src/components/Navbar.js
Component: ProductCard.js
Reusable product card used on the Home, Products, and Deals pages. Shows the image (emoji), name, description, price (with deal price if applicable), and an add button with a brief confirmation state.
frontend/src/components/ProductCard.js
Page: Home.js
Landing page with a hero banner, category grid linking to filtered listings, a preview of current promotions, and featured items from the first category (Electronics).
frontend/src/pages/Home.js
Page: Products.js
Browse all products with a sidebar category filter and search bar. Uses useSearchParams to read/write the category from the URL query string. Fetches deals to show discount badges on matching products.
frontend/src/pages/Products.js
Page: Deals.js
Shows all active deals with a red banner and product cards displaying discount percentages and original/deal prices.
frontend/src/pages/Deals.js
Page: OrderHistory.js
Displays the logged-in user's past orders. Each order card shows the order number, date, status badge, item list, delivery/collection info, and total. Requires authentication.
frontend/src/pages/OrderHistory.js
Page: Rewards.js
£1 spent = 1 point. 100 points = £10 off (button posts { points: 100 } to the API).
frontend/src/pages/Rewards.js
Page: Collection.js
Pickup checkout page. Uses a single branch (no dropdown — just one store). User picks a date and time slot, reviews the order summary, and submits. Success screen shows confirmation and loyalty points.
frontend/src/pages/Collection.js
Page: Delivery.js
Home delivery checkout page. User enters their address, postcode, selects a date and time slot. Includes a delivery fee (£3.99, free over £40). Order summary with running total. Success screen on completion.
frontend/src/pages/Delivery.js
Page: Login.js
Combined login and registration page. Toggles between login and register forms. Sends credentials to the backend API and stores the returned user data in UserContext on success.
frontend/src/pages/Login.js
Page: Admin.js + image helpers
Admin: file input → FormData + fetch('/api/admin/upload') → paste returned url into image_url. Or type an emoji. Stock: number input + show in the table. Shop:ProductThumb.js + productImage.js turn /uploads/... into <img src="http://localhost:5000/uploads/..."> (React runs on 3000, images on 5000).