Gstfy is a GST compliance and business operations SaaS for Indian small and micro businesses. The product focus is simple GST billing, filing summaries, business operations, and role-based team access.
This repository is a Turborepo monorepo with the web app and the custom backend service.
apps/web- Next.js web app.apps/backend- Fastify + PostgreSQL backend.
packages/ui- shared UI package.packages/core- shared business constants and feature access helpers.packages/eslint-config- shared ESLint config.packages/typescript-config- shared TypeScript config.
- Node.js 18 or newer.
- pnpm 9.
- PostgreSQL running locally or reachable through
DATABASE_URL.
pnpm installBackend defaults are defined in apps/backend/.env.example.
cp apps/backend/.env.example apps/backend/.envThe default local database URL is:
DATABASE_URL=postgres://postgres:postgres@localhost:5432/gstfyThe web app reads the backend URL from:
NEXT_PUBLIC_API_URL=http://localhost:4000Phone OTP uses Firebase Authentication. The web app needs the public Firebase web app config:
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_DISABLE_APP_VERIFICATION=falseThe backend verifies Firebase phone sign-in ID tokens with Firebase Admin. Use either service account env values:
FIREBASE_PROJECT_ID=
FIREBASE_CLIENT_EMAIL=
FIREBASE_PRIVATE_KEY=Or set GOOGLE_APPLICATION_CREDENTIALS to a local service-account JSON file path. If FIREBASE_PRIVATE_KEY is stored in .env, keep newlines escaped as \n.
Create the local database once:
createdb gstfyMigrations run automatically when apps/backend starts. Migration files live in apps/backend/drizzle and applied migrations are recorded in public.gstfy_migrations.
Disable automatic migrations only when an external deployment pipeline manages them:
AUTO_RUN_MIGRATIONS=falseRun all apps:
pnpm devRun only the backend:
pnpm --filter @gstfy/backend devRun only the web app:
pnpm --filter web devRun all configured checks:
pnpm lint
pnpm check-types
pnpm buildRun backend checks:
pnpm --filter @gstfy/backend lint
pnpm --filter @gstfy/backend check-types
pnpm --filter @gstfy/backend buildRun web checks:
pnpm --filter web lint
pnpm --filter web buildGET /healthGET /health/dbGET /health/migrations
All application API endpoints are versioned under /api/v1.
POST /api/v1/auth/registerPOST /api/v1/auth/lookupPOST /api/v1/auth/ca-referral/verifyPOST /api/v1/auth/loginPOST /api/v1/auth/ca/registerPOST /api/v1/auth/ca/loginPOST /api/v1/auth/phone/verifyGET /api/v1/auth/meGET /api/v1/auth/sessionPOST /api/v1/auth/logoutPOST /api/v1/auth/password/forgotPOST /api/v1/auth/password/resetPOST /api/v1/auth/email/verifyGET /api/v1/accountPATCH /api/v1/accountGET /api/v1/account/settingsPATCH /api/v1/account/settings/userPOST /api/v1/account/settings/user/phone/verifyPOST /api/v1/account/settings/user/passwordPOST /api/v1/account/settings/user/avatarGET /api/v1/settingsPATCH /api/v1/settings/businessPOST /api/v1/settings/business/ca-referralPATCH /api/v1/settings/business/tenantPATCH /api/v1/settings/userPOST /api/v1/settings/user/phone/verifyPOST /api/v1/settings/user/passwordPOST /api/v1/settings/user/avatarPATCH /api/v1/settings/invoicePATCH /api/v1/settings/gst-presetsPATCH /api/v1/settings/printerGET /api/v1/usersPOST /api/v1/usersPATCH /api/v1/users/:memberIdDELETE /api/v1/users/:memberIdGET /api/v1/ca/clientsPOST /api/v1/ca/clientsPOST /api/v1/ca/invites/acceptGET /api/v1/ca/clients/:businessId/summaryPOST /api/v1/ca/clients/:businessId/revokeGET /api/v1/avatars/profile/:seed.svg
- The frontend uses
NEXT_PUBLIC_API_URL; keep it pointed to the runningapps/backendservice. - Backend secrets must stay in backend env files only. Do not expose secrets through
NEXT_PUBLIC_*. - Add shadcn components from the shared UI package, not directly inside
apps/web.