Project Overview & Prisma Setup
Food Tracker (React + Express + Prisma)
Chapter 1 · Project Overview & Prisma Setup
This course is a direct companion to Food Tracker (React + Express) — the same app, the same React-plus-Express architecture, built a second time with one deliberate change: Prisma in place of raw SQL via better-sqlite3. That sibling course made "deliberately no ORM" its own honest choice; this one exists specifically to show what an ORM changes, and what it costs, for someone who already knows SQL well and wants real hands-on experience with the other side of that tradeoff.
What the App Actually Does
The spec is identical to the sibling course's own — this course is not re-deciding what the app does, only how its data layer is written:
- Scan a barcode with a phone or webcam camera, looking it up against Open Food Facts (free, open, no API key) to pull in the product's name and details automatically.
- Record a use-by date for the item, and see it flagged once it's expiring soon.
- Keep a full history of every item ever added — some still active with a real expiry date, some already marked used with none — searchable in real time as you type.
- Look up recipes via TheMealDB (also free, no key) using ingredients close to expiring.
A weekly meal planner stays explicitly out of scope, matching every other Food Tracker course on this site.
Why This Course Exists: SQL You Already Know vs. an ORM You Don't
Food Tracker (React + Express) already makes the "same language, both ends" case for a Node/Express backend — that argument doesn't need repeating here, since this course shares it unchanged. What this course adds is a second, narrower comparison sitting entirely inside that same architecture: raw, hand-written SQL against Prisma's schema-first, generated-client approach to the exact same database.
| Aspect | Food Tracker (React + Express) | This course |
|---|---|---|
| Schema definition | Hand-written CREATE TABLE SQL in schema.sql | A schema.prisma model, one field per line, no SQL DDL written by hand |
| Applying schema changes | Manual ALTER TABLE statements — no migrations system | Prisma Migrate — every schema change becomes a real, versioned migration file, applied with npx prisma migrate dev |
| Querying | Raw SQL strings with ? placeholders, run directly through better-sqlite3 | Prisma Client's generated query methods — create(), findMany(), update() — built from the schema itself |
| Sync vs. async | Deliberately synchronous — better-sqlite3 is unusual among Node DB libraries in having no async/await | Fully async/await, matching how most Node database tools actually work |
| Dev tooling | None beyond the SQL itself | npx prisma studio — a real, local GUI for browsing and editing the database |
The Real Cost of an ORM, Named Honestly
Food Tracker (React + Express) names its own honest cost plainly: skipping an ORM means giving up migrations and a query builder, in exchange for total transparency about what SQL is actually running. Prisma's own honest cost runs the other way. Prisma Client's generated methods hide the actual SQL being executed — genuinely convenient day to day, but it's exactly the kind of abstraction that can let an N+1 query problem creep in unnoticed: a loop that looks like ordinary JavaScript can quietly issue one database round-trip per iteration instead of one query total, with nothing in the code itself flagging it. This course will call that out directly wherever it's a real risk, rather than presenting Prisma as free convenience with no downside.
Scaffolding the Project
The client side is identical to the sibling course — a Vite-powered React app, unaffected by what the backend does with its database:
The server side starts the same way too, then adds Prisma on top:
prisma init generates a near-empty starting schema — no Item model yet, since Chapter 2 is where the real data modeling happens:
And the accompanying .env file, pointing Prisma at a local SQLite file the same way better-sqlite3 pointed at foodtracker.db in the sibling course:
A minimal server, confirming everything works end to end before any real feature — or any actual database query — exists yet:
cors(), every request from the React app to the Express API is blocked outright. Prisma doesn't touch this at all — it's purely a client/server-port issue, included here for completeness since this chapter may be read on its own without the sibling course alongside it.
node --watch server/index.js restarts Express automatically on save, the same convenience Vite already gives the React side. And once Chapter 2 adds a real model, npx prisma studio opens a local, in-browser GUI for the actual SQLite database — genuinely useful for checking that a route did what it was supposed to, without writing a single SQL query to look.
Where This Course Is Headed
Data modeling with a real schema.prisma model and Prisma Migrate, barcode lookup with a Prisma-backed cache table, the camera-scanning React component (reused essentially unchanged — it's frontend-only, with no database layer involved), the add-item flow, expiry alerts built on Prisma's typed DateTime queries, item history with live search via Prisma's contains filter, marking items used, recipe lookup, cross-cutting state management, deployment (with Prisma's own build-time generation step added), and a capstone tying every chapter into one complete, working app — closing with an honest comparison back to the sibling course's own raw-SQL version.
Hands-On Exercises
In one sentence, state this course's own core comparison claim against Food Tracker (React + Express). Then, using this chapter's own "Real Cost of an ORM" section, name the one concrete risk Prisma introduces that raw SQL doesn't have.
📄 View solutionExplain the sync-vs-async difference between better-sqlite3 and Prisma Client, and why it means a Prisma-backed route handler has to be written differently from its sibling's own version — even though both routes do the same thing.
Using this chapter's own compare-table, explain what problem Prisma Migrate actually solves that the sibling course's own "manual ALTER TABLE statements" approach doesn't.
Chapter 1 Quick Reference
- The shared app — barcode scan (Open Food Facts) → expiry tracking → alerts → searchable history → recipe lookup (TheMealDB); no meal planner — identical spec to Food Tracker (React + Express)
- This course's own throughline: the same app, the same React + Express architecture, with Prisma replacing raw SQL via
better-sqlite3 - Real payoff: generated, type-shaped queries; Prisma Migrate's real, versioned schema changes; a GUI database browser via
npx prisma studio - Honest cost: the actual SQL is hidden behind Prisma Client, which is exactly what makes an N+1 query problem easy to introduce without noticing
- Setup: the same Vite React client as the sibling course; an Express server with
prismaand@prisma/clientinstalled,prisma/schema.prismascaffolded vianpx prisma init --datasource-provider sqlite - Next chapter: Data Modeling with Prisma: schema.prisma & Prisma Migrate