/ WEB APP

RecipeCorner

One place for every recipe, discovered, saved, and discussed.

ReactViteTypeScriptFirebase v12Zustand v5Tailwind CSS
R

WEB APP

0
Firestore collections
0
Cross-device sync
0
Firebase SDK
0
Zustand version

01 / CONTEXT

Overview

THE CHALLENGE

People save recipes from across the internet into browser bookmarks, notes apps, and screenshots, then can't find them when they actually need to cook. There was no single place to store, discover, and discuss recipes from different sources.

THE SOLUTION

A personal cookbook web app built on Firebase v12 with three Firestore collections: recipes (recipe data and metadata), comments (per-recipe social discussion), and favorites (per-user saved recipe references). Zustand v5 manages client state so the UI stays responsive; React Router v7 handles navigation. Firebase Auth (email/password + Google) gates write operations and scopes favorites to the authenticated user.

THE OUTCOME

Users get a single organised recipe library that syncs across all their devices in real time, with social comments making each recipe page a living discussion.

02 / WHAT IT DOES

Key features

Three Firestore Collections

recipes holds full recipe data and metadata (title, ingredients, steps, tags, authorId). comments is a subcollection per recipe for social discussion. favorites stores per-user recipe references, a lightweight join table pattern in Firestore's document model.

Firebase v12 SDK

Firebase v12's modular tree-shakeable imports keep the client bundle lean. Only the Auth, Firestore, and onSnapshot modules are imported, unused Firebase products add zero bytes.

Zustand v5 Global State

Zustand v5 stores the active recipe, search query, and auth state. Selector-based subscriptions prevent the whole component tree from re-rendering on every Firestore snapshot, only the components that care about a specific slice update.

React Router v7 Navigation

React Router v7 handles client-side routing between the discovery feed, recipe detail pages, and the user's favorites library. Loader functions pre-fetch Firestore data before the route renders.

Social Comments

Each recipe has a real-time comment thread backed by the comments Firestore collection. onSnapshot listeners push new comments to all connected viewers without polling.

03 / STACK

Tech decisions

Tap any item to see why it earned a place.

04 / PROCESS

How it came together

05 / HARD PARTS

Challenges & solutions

Firestore doesn't have SQL joins. Favorites are stored as a separate collection with documents keyed by userId+recipeId, containing only the recipe reference and timestamp. Fetching a user's favorites requires two reads: the favorites collection (to get recipeIds), then a batch get on the recipes collection. Zustand caches the result so subsequent page visits skip the second read.

Firestore onSnapshot fires for every write in a collection, including writes from the current user. Without careful Zustand selector design, every comment posted would re-render the entire recipe list. Separate store slices for recipes, comments, and favorites ensure each snapshot only notifies the components that subscribe to that slice.

LET'S BUILD SOMETHING TOGETHER

I'm always open to discussing new projects, partnerships, or just a good idea.