Contributing to HitKeep
HitKeep is an open-source project and contributions are welcome. This page covers the local development setup. The full CONTRIBUTING.md in the repository is the authoritative reference.
Prerequisites
Section titled “Prerequisites”| Tool | Version | Purpose |
|---|---|---|
| Go | 1.26+ | Backend — compiles to the single binary |
| C toolchain (gcc/clang) | system | Required by DuckDB’s CGo bindings |
| Air | latest | Go live-reload — auto-recompile on file change |
| Node.js | 24+ LTS | Angular dashboard (includes tracker snippet build) |
| npm | 10+ | Frontend package manager |
| Mailpit | latest | Local SMTP inbox for testing password resets, invites, reports, and magic links |
Quick Setup
Section titled “Quick Setup”# Clonegit clone https://github.com/pascalebeier/hitkeep.gitcd hitkeep
# Install Air (Go live-reload)go install github.com/air-verse/air@latest
# Install Mailpit for local email testingbrew install mailpit
# Install frontend dependenciescd frontend/dashboard && npm install && cd ../..
# Start Mailpit in another terminalmailpit
# Start the full dev stack (backend + frontend, hot reload)make devThe Makefile runs Air (backend, port :8080) and ng serve (frontend, port :4200) in parallel. Open http://localhost:4200 to access the dashboard in dev mode. The Angular dev server proxies /api/* and /ingest to the Go backend automatically.
make dev now defaults the backend mailer to SMTP via Mailpit on localhost:1025 with HITKEEP_MAIL_ENCRYPTION=none, so local email flows work out of the box once Mailpit is running. Open the Mailpit UI at http://localhost:8025 to inspect outgoing emails.
Seeded Dev Data
Section titled “Seeded Dev Data”If you want a ready-to-use local instance with demo traffic and users, start dev mode with seeding enabled:
make dev DEV_ARGS=--seed
# Shortcutmake dev-seedThis seeds ./hitkeep.db before the backend and frontend start. You can override the defaults with:
HITKEEP_DB=./tmp/dev.db \HITKEEP_SEED_EMAIL=demo@example.com \HITKEEP_SEED_PASSWORD=demo1234 \HITKEEP_SEED_DOMAIN=acme-analytics.io \HITKEEP_SEED_DAYS=90 \make dev DEV_ARGS=--seedBackend Development (Go + Air)
Section titled “Backend Development (Go + Air)”Air watches *.go, *.sql, and template files. On any change, it recompiles and restarts the server in ~1–2 seconds.
# Backend onlymake dev-backend
# Air is configured via .air.toml in the repo root# Entrypoint: cmd/hitkeep/main.go# Args injected by Air: -log-level=debug -dev=truemake dev-backend also defaults to Mailpit-friendly SMTP settings, so backend-only work can still exercise all mail flows as long as Mailpit is running locally.
Environment:
export HITKEEP_JWT_SECRET=hitkeep-dev-jwt-secret# Air injects this automatically via the Makefile
# Optional Mailpit overridesexport HITKEEP_MAIL_DRIVER=smtpexport HITKEEP_MAIL_HOST=localhostexport HITKEEP_MAIL_PORT=1025export HITKEEP_MAIL_ENCRYPTION=noneFrontend Development (Angular)
Section titled “Frontend Development (Angular)”The dashboard is Angular v21 with PrimeNG and Tailwind CSS v4.
# Frontend only (Angular dev server with HMR)make dev-frontend
# Or directly:cd frontend/dashboardnpm start # → ng serve → http://localhost:4200Production Build
Section titled “Production Build”make buildThis runs in order:
- Builds the Angular dashboard (
ng build --configuration production) - Minifies the tracker snippet (
hk.js) via esbuild into the dashboard output - Copies the output to
public/ - Compiles the Go binary (which embeds
public/)
Verification & Tests
Section titled “Verification & Tests”Before opening a pull request, try to run the checks that match your change:
# Backendgo test ./...go test -race ./...golangci-lint run
# Frontend formatting, linting, and unit testscd frontend/dashboardnpm run fmt:checknpm run lintnpm run test -- --watch=false --no-progressFor browser-level verification, HitKeep now standardizes on the Angular CLI entrypoint:
cd frontend/dashboardnpx playwright install --with-deps chromiumnpm run e2enpm run e2e runs ng e2e, which delegates to the seeded Playwright suite used in CI. The launcher automatically:
- builds the production dashboard bundle
- builds the Go binary
- seeds realistic demo data
- starts a disposable local HitKeep instance
- runs the browser journeys against the real app
If you are iterating on one area of the UI, you can still use the lower-level Playwright command directly:
cd frontend/dashboardnpm run test:e2e -- e2e/auth.seeded.spec.js --workers=1Project Structure
Section titled “Project Structure”hitkeep/├── cmd/hitkeep/ # Entry point — boots the modular registry│ ├── main.go│ └── mod_*.go # Module registrations (build-tag gated)├── internal/│ ├── modules/ # Feature modules (auth, analytics, ingest, ...)│ ├── database/ # DuckDB store — all SQL queries│ ├── server/ # HTTP server, middleware, shared handlers│ └── worker/ # Background jobs (retention, rollups, reports)├── frontend/│ └── dashboard/ # Angular v21 SPA + tracker snippet (src/tracker/index.ts)├── public/ # Embedded static files (built frontend output)├── scripts/ # Developer scripts├── Makefile└── .air.toml # Air live-reload configCommit Conventions
Section titled “Commit Conventions”HitKeep uses Conventional Commits for automated changelog generation:
feat(scope): add new featurefix(scope): fix a bugchore(deps): update dependencydocs: update contributing guideTypes: feat, fix, chore, docs, refactor, test, perf
Submitting a Pull Request
Section titled “Submitting a Pull Request”- Fork the repository, create a branch from
main - Write your change following existing patterns
- Run the relevant backend, frontend, and browser verification for your change
- Commit with a Conventional Commit message
- Open a PR against
mainwith a clear description
For repository-specific details and the latest contributor checklist, see the root CONTRIBUTING.md.
Reporting Issues
Section titled “Reporting Issues”- Bugs / feature requests: GitHub Issues
- Security vulnerabilities: GitHub Security Advisories