Skip to content

Repository files navigation

NizKhata

Every rupee, accounted for.

Multi-workspace, single-entry accounting with multi-line transactions, contacts, debts, dues, transfers, and per-line tax tagging.

Stack: React + Vite + TypeScript · Firebase (Firestore + Google Auth) · Firestore Security Rules · Tailwind CSS + shadcn/ui. Pure client + Firestore + Rules (no Cloud Functions).

UX: installable PWA (offline app-shell via vite-plugin-pwa / Workbox), light / dark / system theme (persisted, no flash-of-wrong-theme), fully responsive (desktop sidebar rail ↔ mobile drawer), with entrance animations and reduced-motion support.

Status: Foundation phase (build-order steps 1–4) is implemented — data model, seed logic, Security Rules + tests, auth, onboarding, workspace + permission context, and a permission-gated app shell. Feature screens (Accounts → Reports, Members/Roles editors, CSV) are scaffolded as gated placeholders. See SPEC_NOTES.md for design decisions, deviations from the spec, and open questions.

Getting started

npm install
cp .env.example .env # fill in your Firebase web config

Run against the local emulator (recommended for dev)

Requires the Firebase CLI and Java (for the Firestore emulator).

# .env: VITE_USE_EMULATORS=true
npm run emulators # starts Auth + Firestore + Emulator UI (port 4000)
npm run dev # in another terminal

Run against a real Firebase project

  1. Create a Firebase project; enable Google sign-in and Cloud Firestore.
  2. Put the web app config into .env and set VITE_USE_EMULATORS=false.
  3. Deploy rules + indexes: npm run deploy:rules.

Deploy (Firebase Hosting)

The app is hosted on Firebase Hosting — same platform as Auth + Firestore, so the app, Security Rules and indexes deploy together with one command.

firebase login # once
npm run deploy # build + deploy hosting, rules and indexes# or target one thing:
npm run deploy:hosting # build + deploy only the static site
npm run deploy:rules # deploy only firestore rules + indexes

.firebaserc already points at the nizkhata project. The dist build reads VITE_FIREBASE_* from your local .env at build time.

Scripts

ScriptWhat
npm run devVite dev server
npm run buildtypecheck + production build
npm run typechecktsc only
npm test / npx vitest runpure-logic unit tests (FY + transaction engine)
npm run test:rulesSecurity Rules matrix (needs emulator + Java)
npm run emulatorsFirebase Emulator Suite
npm run deploybuild + deploy hosting, rules and indexes
npm run deploy:hostingbuild + deploy only the static site
npm run deploy:rulesdeploy only Firestore rules + indexes

Run the rules tests with the emulator wrapper:

firebase emulators:exec --only firestore "npm run test:rules"

Architecture

src/
types/ models.ts (Firestore schema) · permissions.ts (catalog + system roles)
lib/ txn.ts (balance math + validation engine) · financialYear.ts
firebase/ config.ts (app init + emulator wiring)
auth/ AuthProvider (Google sign-in + first-login onboarding)
workspace/ WorkspaceProvider (memberships, active workspace, can()) ·
onboarding.ts (invite claim / personal-workspace seed) · seed.ts
components/ AppShell · Sidebar · ProtectedRoute · states (loading/empty/error/no-perm)
pages/ Login · Dashboard · gated placeholders
firestore.rules Security Rules (the real isolation boundary)
firestore.indexes.json composite indexes (§9)
test/rules/ Security Rules test matrix

Derived-not-stored: account balances, debt outstanding, contact positions, due remaining, and tax totals are all computed from transaction lines via src/lib/txn.ts — never persisted (avoids drift).