The Problem

Small businesses and freelancers need a local‑only way to import bank PDFs, tag transactions, and view financial health without sending sensitive data to third‑party SaaS platforms. Existing tools either require cloud storage or lack programmable parsing for Portuguese‑language statements.

What This Does

compasso provides a self‑hosted web app that ingests PDF ledgers (Novo Banco, CGD) via the upload endpoints in apps/api/src/routes/upload.ts. Parsed rows are stored in a SQLite file managed by apps/api/src/db/database.ts. The front‑end in apps/web/src/App.tsx renders a dashboard (pages/Dashboard.tsx) with charts from Recharts and lets users create workspaces, categories, and recurring‑transaction patterns. Core business logic lives in services such as apps/api/src/services/transactionService.ts, workspaceService.ts, and recurringDetector.ts, while shared type definitions are in packages/shared/src/types.ts.

How It Is Wired

  1. Server start – apps/api/src/index.ts creates an Express app, registers middleware (middleware/auth.ts, middleware/rateLimiter.ts) and mounts the router from apps/api/src/routes/index.ts.
  2. Routing – The router forwards requests to concrete route files (e.g., routes/transactions.ts, routes/categories.ts). Each route calls a service function; for example, POST /transactions invokes createTransaction in transactionService.ts.
  3. Database hub – All services that persist data call getDatabase (called from 67 places) defined in db/database.ts. This file is the most connected module (Ca = 33) and therefore the blast‑radius for any change.
  4. Error handling – Errors are constructed via helpers in apps/api/src/errors.ts (badRequest, unauthorized, etc.). This hub (Ca = 32) centralises HTTP‑status mapping.
  5. Workspace logic – workspaceService.ts (imports only two other modules, Ca = 19) orchestrates creation, deletion, and role checks; it is the second‑largest stable hub.
  6. Auth flow – authService.ts performs password hashing (hashPassword) and session ID generation (generateSessionId). These functions perform cryptographic work and write to the DB.
  7. Front‑end boot – apps/web/src/main.tsx renders <App />. The protected route component (ProtectedRoute in App.tsx) checks authentication via useAuth (calls fetchApi → API client). API calls funnel through apps/web/src/services/api/client.ts, which wraps fetchApi (called from 44 places).
  8. Utility spread – Helpers like formatCurrency (called from 4 UI components) and cn (class‑name utility) are widely used but low‑complexity.

No circular imports were detected, and the internal call graph shows 500 resolved call edges. The most frequently invoked functions (getDatabase, fetchApi, badRequest) indicate where stability matters most.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/compasso
cd compasso

# Install all npm dependencies (root and workspaces)
npm install

# Build the shared package (required before dev)
npm run build -w @compasso/shared

# Start both services in development mode (see package.json scripts)
npm run dev
  • Configuration – Copy .env.example to .env (or apps/api/.env) and set at least PORT, ALLOWED_ORIGINS, and DATABASE_PATH. For password‑reset emails, add RESEND_API_KEY and EMAIL_FROM as documented.
  • Running – Backend listens on http://localhost:5181; front‑end is served at http://localhost:5180. The Docker compose file (docker-compose.yml) offers an alternative containerised launch (docker compose up -d).

Real‑World Use

A freelancer runs the app on a personal laptop. After registering, they create a “Consulting” workspace, upload a monthly PDF from Novo Banco, and let the parser auto‑categorise expenses. The dashboard shows a “Recurring” chart that flags a monthly software subscription, prompting the user to set a recurring pattern for future alerts.

Code Health & Issues

  • MEDIUM – GITHUB_TOKEN permissions – .github/workflows/ci.yml lacks explicit permissions; add contents: read.
  • MEDIUM – Dependabot – No dependabot config; add .github/dependabot.yml for npm and GitHub‑Actions.
  • MEDIUM – Docker base image – Dockerfile uses mutable node:20-alpine; pin to a digest.
  • MEDIUM – Dependency scan – CI does not run a vulnerability review; integrate dependency-review-action or osv-scanner.
  • MEDIUM – Checkout persist‑credentials – Set persist-credentials: false on the checkout step.
  • MEDIUM – Non‑root user – Add a USER directive to the Dockerfile.
  • LOW – Job timeout – Define timeout-minutes for each CI job to avoid runaway builds.

Additional observations: 35 test files exist, CI is present, and a LICENSE is included. No secrets were detected in the repo. Several dependencies lag several major versions (e.g., react-dropzone, better-sqlite3), which could affect future compatibility.

The Bottom Line

compasso delivers a complete local finance‑tracking stack with clear separation between API, UI, and shared types. The architecture is sound but hinges on a few high‑traffic hub modules (database.ts, errors.ts, workspaceService.ts); keeping these stable is essential. The project is ready for internal use, though updating out‑of‑date dependencies and tightening CI security would improve maintainability. Suitable for teams that require on‑premise financial data handling with minimal external exposure.