Skip to main content

Acctz Node

Acctz Node is a Node.js / Fastify / TypeScript server with two independently deployable modes: a REST API that serves the Acctz UI, and a Firestore sync listener that keeps PostgreSQL and Firestore in sync. Both modes can run in the same process or as separate Cloud Run services.


Tech Stack

↑ Back to top

LayerTechnology
RuntimeNode.js
FrameworkFastify 5
LanguageTypeScript
DatabasePostgreSQL 18 (via pg)
AuthFirebase Admin SDK (ID token verification)
OpenAPI@fastify/swagger + @fastify/swagger-ui
Buildtsc
Devtsx watch

Startup Modes

↑ Back to top

The server requires at least one mode flag at startup — either as a CLI argument or environment variable.

FlagEnv varWhat it starts
--enable-restENABLE_REST=trueFastify REST API on PORT (default 3000)
--enable-syncENABLE_SYNC=trueFirestore sync listener; health check on PORT (default 8080)

Both flags can be combined to run both in a single process.

# REST only
npx tsx src/index.ts --enable-rest

# Sync only
npx tsx src/index.ts --enable-sync

# Both
npx tsx src/index.ts --enable-rest --enable-sync

If neither flag is set the process exits immediately with an error.


REST API

↑ Back to top

When started with --enable-rest, Fastify registers seven route groups, all protected by Firebase ID token verification:

TagRoutes
entitiesGET/POST /entities, GET/PUT/PATCH/DELETE /entities/:id
accountsGET/POST /entities/:entityId/accounts, GET/PUT/PATCH/DELETE …/:id
journal-entriesGET/POST /entities/:entityId/journal-entries, GET/PUT/PATCH/DELETE …/:id
partiesGET/POST /entities/:entityId/parties, GET/PUT/PATCH/DELETE …/:id
iam-usersGET/PATCH /iam/users/me
iam-orgsGET/POST /iam/organizations, GET/PATCH/DELETE …/:orgId
iam-membershipsGET/POST /iam/organizations/:orgId/memberships, GET/PATCH/DELETE …/:id

The OpenAPI spec is served at /documentation/json; the Swagger UI is at /documentation.


Firestore Sync

↑ Back to top

When started with --enable-sync, the server runs startFirestoreSyncListener — a pg_notify-driven listener that streams PostgreSQL changes into Firestore in real time. This is the write path for the Firestore read layer used by the UI.


Running Locally

↑ Back to top

cd node
npm install
ScriptWhat it runs
npm run devREST API only (--enable-rest)
npm run dev:syncREST API + sync listener
npm run dev:sync-onlySync listener only

The REST server listens on http://localhost:3000; OpenAPI UI at http://localhost:3000/documentation.


Deployment

↑ Back to top

The same Docker image is deployed as two separate Cloud Run services via node/scripts/deploy.sh:

ServiceModeVisibility
acctz-node-apiENABLE_REST=truePublic, scales to zero
acctz-node-syncENABLE_SYNC=truePrivate, min 1 instance, 1 Gi RAM
./node/scripts/deploy.sh

The script rebuilds the core package, regenerates the lockfile, builds and pushes the Docker image to Artifact Registry (us-east4, project acctz-ai-fs), then deploys both services to Cloud Run.


Integration with Acctz UI

↑ Back to top

The Acctz UI Vite dev server proxies /api requests to http://localhost:3000. In production, requests go to https://api.acctz.dev.