A backend service for a budgeting and expense-tracking application.
Pennywise is the backend service for a budgeting and expense tracking application. It provides APIs for managing users, budgets, accounts, and transactions.
The system is designed with a Clean Architecture approach and supports two persistence setups:
- Appwrite TablesDB
- PostgreSQL
Key features include:
- Expense and income tracking
- Budget creation and monitoring
- Workspace-based collaboration with other users
- Transaction history
- User account management
- Session-based authentication
Detailed backend API documentation is available at docs/API.md.
Choose one of the two setup modes below.
- Install Docker.
- Clone this repository and
cdinto it. - Create env files:
cp .env.pennywise.example .env.pennywise
cp .env.appwrite.example .env.appwrite- Start Appwrite + Pennywise stack:
docker compose up- Open
http://localhost:8080and create your Appwrite account/project. - Generate an Appwrite API key with full database access.
- Update
.env.pennywisevalues:APPWRITE_ENDPOINT=http://localhost:8080/v1APPWRITE_PROJECT_ID=<your-project-id>APPWRITE_API_KEY=<your-api-key>SESSION_SECRET=<random-secret>REDIS_URL=redis://pennywise-redis:6379
- Bootstrap Appwrite TablesDB:
npm run bootstrap- Restart containers:
docker compose down
docker compose up- Create an Appwrite Cloud/self-hosted project.
- Generate an API key with full access to database resources.
- Configure
.env.pennywisefor your production Appwrite endpoint and keys. - Run Appwrite bootstrap:
npm run bootstrap- Build and run app image:
docker build -t pennywise-app .
docker run --env-file .env.pennywise -p 3000:3000 pennywise-appAppwrite bootstrap note: Appwrite resource creation is asynchronous. If bootstrap fails while creating indexes/columns, rerun
npm run bootstrap(safe and idempotent).
- Install Docker.
- Clone this repository and
cdinto it. - Create
.env.pennywisefrom example and fill required app settings:
cp .env.pennywise.example .env.pennywise- Start app + postgres + redis:
docker compose -f docker-compose.postgres.yml up- Bootstrap Postgres schema:
POSTGRES_CONNECTION_STRING=postgresql://pennywise:pennywise@localhost:5432/pennywise npm run bootstrap:postgres- If needed, restart the stack:
docker compose -f docker-compose.postgres.yml down
docker compose -f docker-compose.postgres.yml up- Provision PostgreSQL and Redis instances.
- Set
POSTGRES_CONNECTION_STRINGandREDIS_URLfor the app. - Run Postgres bootstrap once against the target DB:
POSTGRES_CONNECTION_STRING=<your-production-connection-string> npm run bootstrap:postgres- Build and run app image:
docker build -t pennywise-app .
docker run --env-file .env.pennywise -p 3000:3000 pennywise-appThe application follows Clean Architecture principles and is organized into three primary layers:
Defines the core entities of the system and the fundamental business concepts.
Implements use cases and business logic involving domain entities.
This layer depends on abstractions for external services such as:
- repositories (data storage)
- email services
- other integrations
These abstractions are defined as interfaces inside:
src/application/ports
Provides concrete implementations of the interfaces defined in the application layer.
This layer also includes presentation mechanisms that expose the application's functionality to external clients.
Currently, the system exposes its functionality through a REST API built with Express.
MIT License