A collaborative grocery list app — fast, synced, and always in your pocket.
Live demo: https://grab-n-go.udy.me
- Add grocery items with quantities; the list syncs across all open tabs and devices in real time
- Double-click any item to remove it
- Sign in with Google — your list is private to your account
- Multiple named lists with a shared-list collaboration mode
- Built-in analytics (most-added items, shopping frequency)
- Three colour themes: Noir, Light, Dark — persisted across sessions
- Installable as a PWA (works offline for reads)
| Concern | Technology |
|---|---|
| Framework | React 19 + Vite 8 |
| Language | TypeScript 6 |
| Styling | Tailwind CSS v4 (Vite plugin) |
| Database | Firebase Realtime Database v11 |
| Auth | Firebase Authentication (Google OAuth) |
| Hosting | Netlify |
| Linting | ESLint 10 + typescript-eslint |
| Formatting | Prettier 3 |
npm install
npm run dev # Vite dev server → http://localhost:5173
npm run build # tsc + vite build → dist/
npm run preview # Preview the production build
npm run lint # ESLint
npm run format # Prettier writesrc/
├── App.tsx # Root — route layout
├── main.tsx # React entry point
├── index.css # Tailwind v4 + theme tokens + global styles
├── assets/
│ └── noir.png # Mascot (noir detective with receipt)
├── auth/
│ ├── AuthContext.tsx # Firebase auth state provider
│ ├── RequireAuth.tsx # Route guard
│ └── useAuth.ts # Auth hook
├── components/
│ ├── AddItemForm.tsx # Name + quantity form
│ ├── ItemCard.tsx # Single list item (dblclick removes)
│ ├── ItemList.tsx # List renderer + empty state
│ ├── ThemeToggle.tsx # Cycle between themes
│ └── UpdateToast.tsx # PWA update prompt
├── hooks/
│ └── useItems.ts # Firebase onValue subscription + CRUD
├── lib/
│ └── firebase.ts # Firebase app init + db export
├── pages/
│ ├── LoginPage.tsx # Auth landing (animated)
│ ├── ListsOverviewPage.tsx # All lists dashboard
│ ├── ListPage.tsx # Single list view
│ ├── AnalyticsPage.tsx # Usage analytics
│ ├── SettingsPage.tsx # Theme + account settings
│ ├── ThemeChooserPage.tsx # First-time theme picker
│ └── NotFoundPage.tsx # 404
└── theme/
├── ThemeContext.tsx # Theme provider
└── useTheme.ts # Theme hook
useItemssubscribes toitemsList/in Firebase viaonValue— React state updates on every remote change.addItem(name, qty)callspush(itemsRef, [name, qty])— Firebase assigns the key.removeItem(id)callsremove(ref(db, \itemsList/${id}`))`.- Firebase Auth restricts reads/writes to the signed-in user's data.
Database URL is set in src/lib/firebase.ts:
https://grabngo-339fa-default-rtdb.asia-southeast1.firebasedatabase.app/
Built by Udhaya Prakash M — LinkedIn · GitHub