Golang-based web application for personal expense management, focused on a clean monthly workflow and intuitive tracking of recurring and non-recurring costs.
Live demo: cost.coderustle.ro
User: admin@gocost.ro, Password: secret123
- Pick a month: Move between months to review past spending or plan upcoming costs.
- Create Groups: Create groups (e.g., Housing, Transportation) to organize your expenses.
- Set up Categories: Inside each group, create categories (e.g., Rent, Groceries). Define a budget for the category and choose if it is recurrent or for the current month only.
- Record Expenses: Add specific expenses to a category (e.g., "Weekly Shop"). Mark them as paid or unpaid to track cash flow.
- Review Status: Visually track spending against your category budgets and see what's left to pay.
- Category Management: Organize expenses into groups (e.g., Housing, Transportation).
- Flexible Category Types:
- This month only: applies only to the currently selected month.
- Recurrent: persists across months until a specified end date (or indefinitely).
For each expense category, the user can record expenses by providing:
- an amount, and
- a payment status (paid or unpaid).
The payment status is visually reflected in the category so the user can immediately see which expenses are settled and which are pending.
- Intuitive navigation centered on monthly context.
- Clear grouping of categories and expenses.
- Efficient handling of both recurring and non-recurring costs.
- Backend: Go (1.26.1+),
net/http,a-h/templfor server-side UI rendering. - Frontend: Tailwind CSS, HTMX for server-driven updates, Alpine.js for lightweight client state.
- Data: SQLite database with migrations managed by
goose. - Configuration: Environment-driven configuration via
.envrc(generated fromenvrc.template). - Tooling:
maketargets for build/dev/test;airfor live reload.
Required:
ALLOWED_HOSTS: comma-separated list of allowed hostnames (e.g.localhost,example.com).DOMAIN: base domain for the app (e.g.localhostorgocost.example).
Optional:
CURRENCY: ISO 4217 currency code (default:USD).TRUSTED_PROXIES: comma-separated list of trusted proxy IP addresses or CIDR ranges.APP_ENV: application environment, typicallyproductionordevelopment(default:development).APP_ADDR: the address the web server listens on (default:0.0.0.0).APP_PORT: the port the web server listens on (default:4000).DB_PATH: SQLite file path used by the Docker entrypoint (default:/app/data/data.sqlite).VERSION: Docker image tag used bycompose.yml(default:latest).GOOSE_DRIVER,GOOSE_DBSTRING,GOOSE_MIGRATION_DIR: used bygooseduring development (seeenvrc.template).
cmd/web: web server entry point.internal/domain: core business entities.internal/usecase: application use cases and interfaces.internal/interfaces: HTTP handlers, routing, and web adapters.internal/infrastructure: configuration and storage implementations.ui: Templ components and static assets.migrations: SQL migration files.
Use the provided Dockerfile and compose.yml to build and run the app locally.
# build the image for local use
docker build -t ghcr.io/madalinpopa/gocost-web:local .
# create the external network used by compose (safe if it already exists)
docker network create public
# start the app on http://localhost:4000
VERSION=local docker compose upOptional environment overrides (set before docker compose up):
ALLOWED_HOSTS, DOMAIN, CURRENCY.
To run the container without Docker Compose:
# build the image
docker build -t ghcr.io/madalinpopa/gocost-web:local .
# run the container
docker run -d \
--name gocost \
-p 4000:4000 \
-e ALLOWED_HOSTS=localhost \
-e DOMAIN=localhost \
-v gocost_data:/app/data \
ghcr.io/madalinpopa/gocost-web:local- Go 1.26.1+
- Node.js + npm (Tailwind CLI)
- Optional:
direnvand 1Password CLI (op) for.envrcgeneration
make init: download deps, generate Templ, install npm packages, create.envrc.make dev: run server + Templ + Tailwind watchers with live reload.make build/web: build the web server binary tobin/server.make test: run Go tests under./internal....make test/race: run race detector tests.make check: rungo vetandstaticcheck.
Contributions are welcome. Please follow these steps:
- Fork the repository and create a feature branch.
- Keep changes focused and follow the existing project layout.
- Run
make test(andmake checkif you havestaticcheck) before opening a PR. - If you change
.templfiles or CSS, ensure generated files are up to date. - Open a pull request with a clear description of the change.
