Skip to content
Start In Cloud

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.

ToolVersionPurpose
Go1.26+Backend — compiles to the single binary
C toolchain (gcc/clang)systemRequired by DuckDB’s CGo bindings
AirlatestGo live-reload — auto-recompile on file change
Node.js24+ LTSAngular dashboard (includes tracker snippet build)
npm10+Frontend package manager
MailpitlatestLocal SMTP inbox for testing password resets, invites, reports, and magic links
Terminal window
# Clone
git clone https://github.com/pascalebeier/hitkeep.git
cd hitkeep
# Install Air (Go live-reload)
go install github.com/air-verse/air@latest
# Install Mailpit for local email testing
brew install mailpit
# Install frontend dependencies
cd frontend/dashboard && npm install && cd ../..
# Start Mailpit in another terminal
mailpit
# Start the full dev stack (backend + frontend, hot reload)
make dev

The 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.

If you want a ready-to-use local instance with demo traffic and users, start dev mode with seeding enabled:

Terminal window
make dev DEV_ARGS=--seed
# Shortcut
make dev-seed

This seeds ./hitkeep.db before the backend and frontend start. You can override the defaults with:

Terminal window
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=--seed

Air watches *.go, *.sql, and template files. On any change, it recompiles and restarts the server in ~1–2 seconds.

Terminal window
# Backend only
make 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=true

make 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:

Terminal window
export HITKEEP_JWT_SECRET=hitkeep-dev-jwt-secret
# Air injects this automatically via the Makefile
# Optional Mailpit overrides
export HITKEEP_MAIL_DRIVER=smtp
export HITKEEP_MAIL_HOST=localhost
export HITKEEP_MAIL_PORT=1025
export HITKEEP_MAIL_ENCRYPTION=none

The dashboard is Angular v21 with PrimeNG and Tailwind CSS v4.

Terminal window
# Frontend only (Angular dev server with HMR)
make dev-frontend
# Or directly:
cd frontend/dashboard
npm start # → ng serve → http://localhost:4200
Terminal window
make build

This runs in order:

  1. Builds the Angular dashboard (ng build --configuration production)
  2. Minifies the tracker snippet (hk.js) via esbuild into the dashboard output
  3. Copies the output to public/
  4. Compiles the Go binary (which embeds public/)

Before opening a pull request, try to run the checks that match your change:

Terminal window
# Backend
go test ./...
go test -race ./...
golangci-lint run
# Frontend formatting, linting, and unit tests
cd frontend/dashboard
npm run fmt:check
npm run lint
npm run test -- --watch=false --no-progress

For browser-level verification, HitKeep now standardizes on the Angular CLI entrypoint:

Terminal window
cd frontend/dashboard
npx playwright install --with-deps chromium
npm run e2e

npm 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:

Terminal window
cd frontend/dashboard
npm run test:e2e -- e2e/auth.seeded.spec.js --workers=1
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 config

HitKeep uses Conventional Commits for automated changelog generation:

feat(scope): add new feature
fix(scope): fix a bug
chore(deps): update dependency
docs: update contributing guide

Types: feat, fix, chore, docs, refactor, test, perf

  1. Fork the repository, create a branch from main
  2. Write your change following existing patterns
  3. Run the relevant backend, frontend, and browser verification for your change
  4. Commit with a Conventional Commit message
  5. Open a PR against main with a clear description

For repository-specific details and the latest contributor checklist, see the root CONTRIBUTING.md.