A React web app to track daily expenses in ₦ (Naira). Built with Vite, Tailwind CSS, and shadcn/ui. No Excel — add expenses, see dashboard totals and charts, and filter the log by date. Data syncs across devices via Supabase (sign in on each device to see the same expenses).
- React 18 + Vite — fast dev and builds
- Tailwind CSS v4 — layout and utilities
- shadcn/ui — Button, Input, Select, Card, Table, etc. (Cursor-style dark theme)
- Recharts — spending by category (pie) and by month (bar)
- Supabase — auth and database so your expenses sync across phones, tablets, and computers
- Sign in / Sign up — one account, same data on every device
- Dashboard: Today’s total, this month’s total, all-time total
- Charts: Spending by category (pie), spending by month (bar)
- Add expense: Date, category, description, amount (₦), payment method, notes. Edit via the table
- Daily log: Table with date filter; Edit and Delete per row
- Node.js v18+
- npm
npm install
npm run devOpen http://localhost:5173.
If Supabase isn’t configured yet, the app will show setup instructions.
To use the app on multiple devices with the same data:
- Create a free project at app.supabase.com.
- In the project: Settings → API — copy Project URL and anon public key.
- In this repo, copy
.env.exampleto.envand set:VITE_SUPABASE_URL= Project URLVITE_SUPABASE_ANON_KEY= anon public key
- In Supabase: SQL Editor — run the script in
supabase/schema.sqlto create theexpensestable and Row Level Security (so each user only sees their own data). - Restart the dev server (
npm run dev) and reload the app. Sign up with email/password; your expenses will sync across any device where you sign in.
If web and mobile point to the same Supabase project, keep one schema source of truth in this repo:
- Canonical file:
supabase/schema.sql(web) - Sync to mobile with:
npm run schema:sync-mobile - Verify sync status with:
npm run schema:check-mobile - Mobile can also pull from here with:
npm run schema:pull-from-web(run insidespendng-mobile)
npm run buildDeploy the dist/ folder to any static host (Netlify, Vercel, GitHub Pages).
Set the same VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY in the host’s environment so auth and data work in production.
Google sign-in in production: To avoid redirecting to localhost after sign-in, set VITE_APP_URL to your live URL (e.g. https://your-app.vercel.app) in the host's environment. In Supabase: Authentication → URL Configuration set Site URL to that same URL and add it to Redirect URLs.
Preview locally: npm run preview
Spend-NG/
index.html
package.json
vite.config.js
components.json # shadcn CLI config
jsconfig.json # path alias @/
supabase/
schema.sql # run in Supabase SQL Editor to create expenses table
scripts/
exportSeedFromExcel.js # one-off: Excel → src/data/seedExpenses.json
src/
main.jsx
App.jsx
contexts/
AuthContext.jsx # Supabase auth state and sign in/up/out
services/
expenseApi.js # Supabase CRUD for expenses
lib/
supabase.js # Supabase client (reads .env)
index.css # Tailwind + Cursor theme (@theme inline)
constants.js
lib/
utils.js # cn() for class names
utils/
helpers.js
data/
seedExpenses.json # prepopulate from Excel
components/
Dashboard.jsx
ExpenseCharts.jsx
ExpenseForm.jsx
ExpenseLog.jsx
ui/ # shadcn (button, input, card, select, table, separator)
README.md
- Categories:
src/constants.js→CATEGORIES - Payment methods:
src/constants.js→PAYMENT_METHODS - Theme: Cursor-style (black/grey/white) in
src/index.css→@theme inline - More shadcn components:
npx shadcn@latest add dialog(etc.)