Capstone: A Complete, Working Food Tracker

Food Tracker (React + Firebase)

Chapter 13 · Capstone: A Complete, Working Food Tracker

Maya has just installed the finished app on her phone, at its real deployed URL. Every step below is a real feature, built in a specific earlier chapter, used exactly the way it was designed to be used.

Step 1 — Signing Up

Maya creates an account with her email and a password. From this moment on, her pantry is genuinely hers — not merely hidden behind a login screen, but enforced by the Security Rules built across Chapters 6, 9, and 11: every read, write, and update on her items now checks request.auth.uid == resource.data.userId, on Firebase's own servers, regardless of what the app's UI does or doesn't show.

Step 2 — Scanning Her First Item

She points her phone's camera at a yogurt carton's barcode. The getUserMedia-based scanning component (Chapter 4) decodes it and hands it to lookupBarcode (Chapter 3), which checks barcodeCache first, finds nothing (a genuinely new product), queries Open Food Facts, and caches the result for the next person who scans the same barcode. She confirms the name, picks an expiry date, and saves — Chapter 5's addItem, now including her own userId per Chapter 11.

Step 3 — What Actually Got Stored

Behind the scenes, the real document reflects every data-modeling decision from Chapter 2: name and nameLower, barcode, category, status: "active", a genuine Firestore Timestamp for expiryDate, addedAt set by serverTimestamp() (and enforced by Chapter 6's own rule requiring it), and userId. Nothing here was left to chance — every field exists because an earlier chapter deliberately decided it should.

Step 4 — An Alert, a Few Days Later

Opening the app later that week, the dashboard flags the yogurt as expiring soon — Chapter 7's own query, running cleanly now that the composite index it needs was codified in firestore.indexes.json and deployed for real in Chapter 12, rather than existing only as a console click-through on one developer's machine.

Step 5 — Searching Her History

Wanting to buy more of something she'd tracked before, Maya types "yogurt" into search. This finds "Greek Yogurt" — a genuine mid-word match, something the raw Firestore prefix trick Chapter 8 first demonstrated could never do. It works because Chapter 8's actual chosen implementation filters the loaded history client-side with .includes(), not the more limited prefix-only Firestore query — the more capable of the chapter's own two approaches, deliberately chosen over the more constrained one.

Step 6 — Marking the Yogurt Used

She finishes it. One tap calls Chapter 9's markItemUsed: status flips to "used", usedAt is stamped, and expiryDate is genuinely removed via deleteField() — not nulled. The item drops off the active dashboard immediately, but per Chapter 2's original design, it never disappears from her history at all.

Step 7 — A Recipe Suggestion

With chicken and eggs both nearing expiry, Maya opens the recipe tab. Chapter 10's suggestRecipes fans out one TheMealDB query per ingredient, merges the results, and sorts by how many of her own expiring items each recipe actually uses — a recipe using both chicken and eggs together surfaces above one using only either alone.

Step 8 — All of This, at a Real Address

Every step above happened at the app's actual Firebase Hosting URL, over HTTPS by default — the exact requirement Chapter 4 flagged early and left as an assumption, now genuinely satisfied since Chapter 12's deployment.

Chapter Attribution

StepChapter(s) applied
1 — Signing upChapter 11 (Firebase Authentication), Chapters 6 & 9 (rules extended by ownership)
2 — First scanChapter 4 (camera scanning), Chapter 3 (barcode lookup + cache), Chapter 5 (add-item flow), Chapter 11 (userId)
3 — What got storedChapter 2 (data model), Chapter 6 (serverTimestamp enforcement)
4 — Expiry alertChapter 7 (expiry query), Chapter 12 (deployed composite index)
5 — SearchChapter 8 (item history & search)
6 — Marking usedChapter 9 (deleteField, the used-item invariant)
7 — Recipe suggestionChapter 10 (TheMealDB fan-out and merge)
8 — Real deployed URLChapter 12 (Hosting, HTTPS), Chapter 1 (the architecture this all rests on), Chapter 4 (the requirement finally met)
What this whole course was really about
Chapter 1 opened with a claim: this app would have no server the developer writes, runs, and deploys themselves. Every single step above — authentication, a barcode lookup, a database write, an alert, a search, a status change, a multi-API recipe search, and the deployment serving all of it — happened without that claim ever being broken. Not because the app does less than its siblings, but because Firestore, Security Rules, and Cloud Functions turned out to be enough, chapter after chapter, for a real, complete, multi-feature application.
Honest scope note
This capstone deliberately stops short of several things: the weekly meal planner named as future work all the way back in Chapter 1 was never built here; there's no offline/PWA support, so the app requires a live connection; each account's pantry is fully private and single-user, with no shared-household or multi-user pantry support; Chapter 7's proactive scheduled notification was built as an optional stretch feature and was never wired up to an actual push-notification delivery mechanism (like Firebase Cloud Messaging tokens); and no automated test suite or CI pipeline was covered anywhere in this course. Each is a genuine, reasonable next step — none of them were quietly assumed to already be done.

Hands-On Exercises

Exercise 1

In Step 5, Maya's search for "yogurt" finds "Greek Yogurt" — a mid-word match. Explain specifically why this works, referencing which of Chapter 8's two approaches actually powers the real search feature.

📄 View solution
Exercise 2

Pick any two steps from Maya's session and explain how each one depends on at least two earlier chapters working together, not just one chapter in isolation.

📄 View solution
Exercise 3

Explain why the honest scope note excludes push notifications specifically, even though Chapter 7 already built a scheduled Cloud Function that checks for expiring items.

📄 View solution

Chapter 13 Quick Reference — Course Complete

  • 8 steps, 12 prior chapters — one continuous, realistic session with the finished, deployed app
  • This course's own throughline, closed out: no server the developer writes, runs, or deploys themselves — genuinely true across every single feature built
  • Honest scope note: no meal planner, no offline/PWA support, no shared-household pantries, no push-notification delivery, no automated tests/CI
  • Food Tracker (React + Firebase) is now complete — 13/13 chapters