Liquidity Planning
git config core.hooksPath .githooksThis enables pre-commit hooks that run lint and tests before each commit.
No configuration is needed to start: every variable has a local dev default in docker-compose.yml, so
make up brings up the full stack without any accounts or secrets.
- E-mail: outbound mail goes to the local Mailpit service. Read it at
http://localhost:8025. Production uses any SMTP relay via the
SMTP_*variables. - Currency rates: with an empty
FIXER_IO_KEY, rates are loaded from fallback_rates.json instead of calling Fixer.io. - Secrets: production values are injected from Bitwarden Secrets Manager by the
maketargets. See CLAUDE.md for the setup.
We are using phpMyAdmin with Docker to provide an interface to the database.
- Configure it with the
PMA_*variables indocker-compose.yml, see the image documentation - You can check out your database (locally) at: http://localhost:8097/
Look at the Nuxt documentation to learn more.
Make sure you are in the frontend directory for all the following actions
npm install
npm run dev or npm run dev-host (to expose host and be able to connect from another device)
Make sure you are in the backend directory for all the following actions
go get OR go mod tidy
- Install Air:
go install github.com/air-verse/air@latest
air
- Install Goose:
go install github.com/pressly/goose/v3/cmd/goose@latest
We differentiate between static and dynamic migrations whereas static migrations are all migrations that actually hold data later and a migration down would lead to data loss such as table creation or alterations.
Dynamic migrations are stored functions, views or triggers, basically things that can be removed entirely and reapplied.
The placeholder must either be replaced by "static" or "dynamic" (without quotes)
- Create Migration:
goose --dir internal/db/migrations/<directory> create <name-of-migration> sql- Follow up with:
goose --dir internal/db/migrations/<directory> fixto apply sequential numbering
- Follow up with:
We run auto migrations on each app start. Since "air" will restart the app on any changes also in the .sql files the migrations will apply automatically but it might be helpful sometimes to rollback and reapply.
- Apply Migration:
goose --dir internal/db/migrations/<directory> mysql liquiswiss:password@/liquiswiss up - Rollback Migration:
goose --dir internal/db/migrations/<directory> mysql liquiswiss:password@/liquiswiss down - Or check out the Makefile
Optional step
You can fixtures from the fixtures directory if you desire. The dynamic migrations insert a minimal set of data required to make the app work properly. You can check out the minimal inserted data in 10000_apply_minimal_fixtures.sql
Make sure you are in the backend directory
Make sure you spin up the test database with
docker compose up
- Install Mockgen with
go install go.uber.org/mock/mockgen@latestto generate mocks- There are
go generatecommands already in the files so you can simply dogo generate ./...
- There are
- You can run all tests with
go test ./...locally - Locally the .env.local.testing is used
- For the Github Action the .env.github.testing is used
- Check out the ci.yml and check for the service used in the test_backend job
- The environment variable
TESTING_ENVIRONMENTdetermines which .env file to use
Make sure you are in the frontend directory
- Install dependencies:
npm install - Install Playwright browsers:
npm run test:e2e:install
npm run test:e2e # Run all tests headless
npm run test:e2e:ui # Open interactive UI mode
npm run test:e2e:headed # Run tests with visible browser
npm run test:e2e:debug # Run tests in debug mode- Frontend dev server running (
npm run dev) - Backend server running (
airorgo run .) - Test user credentials configured via environment variables:
E2E_TEST_EMAIL- Test user emailE2E_TEST_PASSWORD- Test user password
For production make sure you define the proper values for your envs (no matter in which way you provide them)
WEB_HOST- Reflects your Frontend URL (eg. https://yourdomain.com)JWT_KEY- Should be a long and secure passwordNUXT_API_HOST- Reflects your Backend URL (eg https://api.yourdomain.com)
The backend exposes an MCP (Model Context Protocol) server at /api/mcp (Streamable HTTP), protected by an embedded OAuth 2.1 authorization server (dynamic client registration, PKCE, rotating refresh tokens). AI clients like Claude can manage bank accounts, transactions, employees, salaries and read liquidity forecasts on behalf of a user.
Connect locally:
claude mcp add --transport http liquiswiss-local http://localhost:8087/api/mcpAuthentication runs through the browser: login, consent page (with an explicit notice that data flows to the chosen LLM provider), redirect back. Sessions match web logins (20 min access tokens, 90 day rotating refresh tokens). Users can revoke access anytime under Profile settings, "Verbundene Anwendungen". Public base URL of the backend is configured via BACKEND_PUBLIC_URL.