A calmer, server-backed habit tracker for consistent daily follow-through.
SvelteKit 2 · Svelte 5 · Quarkus 3 · PostgreSQL · Flyway · Docker · GitHub Actions
Product · Try the live showcase · Open in Telegram · Engineering · Showcase · Run locally · Quality
- 🎯 Product
- 🧩 Engineering highlights
- 🧭 Interactive showcase
✈️ Telegram Mini App- 🖼️ Product screens
- 🏗️ Architecture
- 🚀 Run locally
- 🧪 Quality evidence
- 🗂️ Repository map
- 📚 Further reading
⚠️ Scope and limitations
Habit Runner is a focused PWA for people who want the next useful action to be obvious. It surfaces today’s habits, completion context, streak momentum, and longer-term progress without turning the product into a dashboard maze.
This repository is a portfolio project demonstrating end-to-end ownership of a small production-shaped web system:
- authenticated habit and check-in workflows;
- durable account preferences restored after re-login;
- schedule-aware streak, flame, and inactivity/ice signals;
- responsive cards and compact rows for desktop and mobile;
- a Telegram Mini App entry point for a quick daily check-in;
- a backend-first API contract with migration-safe persistence;
- reproducible local Docker smoke checks and path-aware CI.
| Area | Evidence in this repository |
|---|---|
| Frontend | SvelteKit 2, Svelte 5, typed API clients, shared TypeScript contracts, Playwright journeys |
| Backend | Quarkus 3 resources, service boundaries, JPA/Hibernate persistence, Jakarta validation |
| Data | PostgreSQL, additive Flyway migrations, optimistic versioning, stable ownership checks |
| Authentication | Google OAuth, HttpOnly access/refresh cookies, CSRF protection, refresh-token rotation |
| Reliability | Request trace IDs, explicit error responses, readiness/health checks, bounded smoke stack |
| Delivery | Maven/npm caches, OpenAPI snapshot drift checks, Trivy, path-aware GitHub Actions lanes |
| PWA | Installable application shell with production build verification; habit data remains server-backed |
The most important architectural decision is backend-first state ownership: authenticated habit and check-in mutations are accepted by the API before the UI reflects them. Browser storage is used only for intentionally local concerns and first-paint fallbacks.
Try the real application UI anonymously at habit-runner.freeddns.org. The public showcase uses fictional in-memory data, so you can check in habits, open detail views, create or edit a habit, archive/delete, reorder, and inspect progress without OAuth, API requests, database writes, or browser persistence.
The normal account flow remains available through Google OAuth; authenticated data is server-backed and is never mixed with the showcase fixture.
Open Habit Runner in Telegram when a quick daily check-in is enough. Link your account when you want to continue with the same habits in the web app for a larger view.
These are the private habit-management screens, rendered with a sealed fixture instead of a visitor account. The fixture reuses the same dashboard, habit detail, progress, and compact-webview components as the signed-in application.
| Desktop: habits | Desktop: habit detail |
|---|---|
![]() |
![]() |
| Desktop: progress | Compact webview |
|---|---|
![]() |
![]() |
The separate GitHub social-preview image also shows the private habit dashboard with fixture data. Upload it in GitHub repository settings when publishing the repository.
flowchart LR
browser[Browser / installed PWA]
web[SvelteKit static app + nginx]
api[Quarkus API]
auth[Google OAuth + HttpOnly cookies]
db[(PostgreSQL + Flyway)]
push[Optional Web Push]
browser --> web
web -->|/api proxy| api
api --> auth
api --> db
api --> push
The main runtime path is:
Svelte component
-> frontend store / typed client
-> authenticated REST resource
-> application service
-> repository / JPA entity
-> PostgreSQL migration-backed schema
-> normalized response DTO
The installed PWA caches the application shell for repeat visits. It is not an offline habit database, so users do not receive a false “saved” state when the server has not accepted a mutation.
For the current authenticated API contract, start with the generated OpenAPI snapshot and the short request examples.
- Docker Compose with a running Docker engine;
- Node.js 22.12 or newer;
- Java 25 and the Maven wrapper;
- Google OAuth credentials only if testing the real sign-in flow.
cp .env.example .env
docker compose --profile db up --build --waitOpen http://localhost:5137, or the configured
WEB_PORT. Stop the stack with docker compose --profile db down.
cd apps/web && npm ci
cd apps/web && npm run dev:serverFor environment variables, OAuth callback setup, and direct Quarkus mode, see
docs/setup/getting-started.md.
./scripts/ci/smoke-stack.shThe script builds the API and web images, starts PostgreSQL/Flyway, checks health
and /api proxy routing, then removes its containers, network, and test volume.
Run the cheapest checks first during development:
cd apps/web && npm run test
cd apps/web && npm run check
cd apps/web && npm run test:e2e
cd apps/backend && ./mvnw -B -ntp verify
cd apps/backend && ./mvnw -B -ntp verify -Ppostgres-it
actionlint .github/workflows/quality.yml
docker compose --env-file .env.example --profile db config --quietThe local browser matrix includes desktop, compact-mobile, a 390px mobile project, and a Telegram-webview project. Mobile UX coverage checks Today, Progress, More/theme controls, search focus, and Telegram entry states. Local checks prove the checkout; they do not prove a pushed GitHub Actions run, deployed OAuth, an official Telegram client session, or production-device PWA update behavior.
apps/web/ SvelteKit UI, API clients, unit and Playwright tests
apps/backend/ Quarkus resources, services, entities, migrations
spec/openapi/ Generated OpenAPI snapshot
scripts/ci/ Local and CI quality automation
docs/ Architecture, setup, operations, and delivery notes
docker-compose.yml Portable JVM + PostgreSQL + nginx stack
- Architecture overview
- API contract
- Getting started and OAuth setup
- GitHub Actions and smoke checks
- Monitoring contract
- Documentation hub
- License
- Google OAuth and external push delivery require configured credentials.
- Habit changes require a connection to the authenticated API.
- GitHub Actions minute savings must be confirmed from fresh remote workflow runs;
local
actionlintand build checks cannot measure hosted-run cost. - The screenshots use fictional showcase data and are not proof of a signed production deployment.



