Self-hosted coding-time tracking.
Editor extensions send heartbeats to the API, which derives coding time from the gaps between them and serves a per-user dashboard and leaderboard.
| Layer | Technology |
|---|---|
| Backend | ASP.NET Core (.NET 10) + PostgreSQL / TimescaleDB |
| Frontend | Next.js (standalone output) |
backend/ .NET solution (Api, Core, Infrastructure, Tests)
frontend/ Next.js app
docker/
dev/ Postgres only (run the apps locally)
stg/ Full stack, images built from source
prod/ Full stack, images pulled from Docker Hub
Start the database, then run each app against it:
docker compose -f docker/dev/docker-compose.yml up -d # Postgres on :5432
cd backend && dotnet run --project Epoch.Api # API on :5000
cd frontend && npm install && npm run dev # web on :3000Both stacks read configuration from a .env file next to their compose file.
Copy the example and fill it in:
cp docker/<env>/.env.example docker/<env>/.envBuilds the api and web images locally from the current checkout. Use this to
validate a change before tagging a release.
cp docker/stg/.env.example docker/stg/.env # then edit
docker compose -f docker/stg/docker-compose.yml up -d --buildPulls prebuilt, versioned images instead of building. Set the tag to deploy in
docker/prod/.env:
IMAGE_TAG=1.2.3 # a released version, or "latest"cp docker/prod/.env.example docker/prod/.env # then edit
docker compose -f docker/prod/docker-compose.yml pull
docker compose -f docker/prod/docker-compose.yml up -dTo roll out a new version, bump IMAGE_TAG, then pull and up -d again. To
roll back, point IMAGE_TAG at the previous version and repeat.
Publishing is automated by .github/workflows/publish.yml.
Pushing a v*.*.* tag whose commit is on main builds and pushes both images
to Docker Hub. The tag becomes the image version (v1.2.3 → 1.2.3) and
latest is updated too.
git tag v1.2.3
git push origin v1.2.3Configure these repository secrets (Settings → Secrets and variables → Actions):
| Secret | Purpose |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub namespace the images live under |
DOCKERHUB_TOKEN |
Docker Hub access token with write scope |
Published images: mirello/epoch-api and mirello/epoch-web.
Both services expose a liveness endpoint used by the container HEALTHCHECK, and
web waits for api to become healthy before starting:
| Service | Endpoint |
|---|---|
| API | /health |
| Web | /healthz |