A mixed-category e-commerce site — browse products, add them to a cart, and check out. Built to practice the parts of an online store that go beyond a simple product list: cart state, order persistence, and tying orders back to a logged-in user. Written by Joel Odum.
After building an auth-based note app, I wanted to try something with more moving parts — specifically, state that has to survive across pages (a cart) and a checkout flow that actually writes a permanent record to the database instead of just updating the UI. I skipped real payment processing on purpose so I could focus on getting the cart logic, order structure, and guest-vs-logged-in flow right first. Letting people browse and add to cart without an account, but requiring login only at checkout, felt like the more realistic version of how a real store works.
- Browse a catalog of products across multiple categories, with filtering
- Add to cart and adjust quantities without needing an account
- Cart persists across page reloads (stored locally in the browser)
- Checkout requires login, and creates a real order record tied to that user
- View past orders, each with the items and quantities purchased
- Custom "corner store" catalog design — price tag stickers, ledger-style typography
- Next.js (App Router)
- Supabase — Postgres database + authentication
- React Context + localStorage for cart state
- Tailwind CSS for styling
- Deployed on Vercel
-
Clone the repo:
git clone https://github.com/joelgreyhat1/corner-store.git cd corner-store -
Install dependencies:
npm install
-
Create a
.env.localfile with your Supabase credentials:NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key -
Run the development server:
npm run dev
-
Open http://localhost:3000 in your browser.
- Managing state that needs to persist across pages and reloads, using Context + localStorage rather than reaching for a database on every click
- Structuring related database tables (orders and order_items) and writing to both together as one logical transaction
- Designing an auth flow where most of the app is public, but a specific action (checkout) triggers a login requirement mid-flow
- No payment processing yet — that's a natural next step if I revisit this project
MIT