Contributing - grumnuts/dosh GitHub Wiki

Contributing

Prerequisites

  • Node.js 20+
  • npm

Running Locally

# Backend (port 3000)
cd backend && npm install && npm run dev

# Frontend (port 5173, proxies /api to :3000)
cd frontend && npm install && npm run dev

Open http://localhost:5173 in your browser.

Project Structure

backend/src/
  db/           # Schema, migrations, DB client
  routes/       # One file per resource (auth, budget, transactions, ...)
  services/     # Business logic (budget calculations, CSV import, rules)
  middleware/   # Session authentication
  utils/        # audit, dates, money

frontend/src/
  api/          # Typed fetch wrappers per resource
  components/
    ui/         # Shared primitives (Button, Input, Modal, ...)
    layout/     # Sidebar, BottomNav, Layout
    budget/     # BudgetTable, CategoryModal, GroupModal, CoverModal
    transactions/ # TransactionForm, ImportWizard, BulkEditModal
    reports/    # Report components
  hooks/        # useAuth, useWeek, useLocalStorageBool, useResizableCols
  pages/        # One file per route

TypeScript

Both packages must compile with zero errors before committing:

cd backend && npx tsc --noEmit
cd frontend && npx tsc --noEmit

No any types. Use unknown and narrow instead.

Code Standards

Money: All monetary values are integer cents. Use parseCents() / formatCents() from backend/src/utils/money.ts. Never store or calculate with floats.

SQL: All queries must use parameterised statements. No string interpolation into SQL.

Backend patterns:

  • Routes go in src/routes/, business logic in src/services/, helpers in src/utils/
  • Log all mutations with logAudit() from src/utils/audit.ts
  • Always call recordBudgetChange() when a category's budgeted amount changes

Frontend patterns:

  • TanStack Query for all server state — no useState + useEffect for fetching
  • Invalidate query keys after mutations: ['budget'], ['transactions'], ['accounts']
  • react-hook-form + zod for forms
  • Use the shared <Modal> component — don't create custom backdrop/overlay logic

Styling:

  • Tailwind utility classes only — no custom CSS unless Tailwind can't do it
  • Dark mode only: background #111111, surfaces #1c1c1c / #252525 / #2e2e2e
  • Accent (income, positive): text-accent / #4ade80
  • Danger (overspent, negative): text-danger / #f87171
  • Transfers/covers: text-transfer / #6b7280

Git Workflow

  • Always create a new branch: feature/short-description, fix/short-description, refactor/short-description
  • Never commit directly to main
  • Commit often — after each meaningful, working change
  • Don't batch unrelated changes into a single commit
  • Ensure TypeScript compiles before every commit

Pull Requests

  • Open a PR from your feature branch into main
  • PR title should match the branch objective
  • PR body should summarise what changed and why
  • Squash-merge into main
  • Delete the branch after merging

Database Migrations

Add new migration files in backend/src/db/migrations/ with sequential numbering (e.g. 013_add_foo.sql). Migrations run automatically on startup in order. They are applied once and tracked — do not modify existing migration files.

No Over-Engineering

  • Don't add abstractions for one-off cases
  • Don't add error handling for scenarios that can't happen
  • Don't add comments unless the logic is genuinely non-obvious
  • Don't design for hypothetical future requirements
⚠️ **GitHub.com Fallback** ⚠️