Architecture
Health Tracker uses a single-crate workspace with feature-gated compilation for SSR + hydration.
System overview
┌─────────────────────────────────────────────────────────┐
│ Health Tracker │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ Browser │◀──▶│ Axum Server │◀──▶│ SQLite │ │
│ │ (Leptos) │ │ (SSR + API) │ │ (Storage) │ │
│ └─────────────┘ └──────────────┘ └────────────┘ │
│ │
│ Feature gates: │
│ - `hydrate` → WASM client bundle │
│ - `ssr` → Server binary │
│ - `cli` → Admin CLI binary (stub) │
│ - `gen` → Code generator binary (stub) │
└─────────────────────────────────────────────────────────┘
Crate structure
src/
├── main.rs # Axum server entry (ssr feature only)
├── lib.rs # WASM hydration entry (hydrate feature only)
├── app.rs # Shared root component + router (both features)
├── api/ # Leptos #[server] functions (client-server RPC)
│ └── mod.rs # upsert_daily_log, get_daily_log, get_daily_logs_for_month
├── routes/ # Page components
│ ├── index.rs # Landing page (/)
│ ├── dashboard.rs # Dashboard placeholder (/dashboard)
│ ├── track.rs # Daily log form (/track?date=YYYY-MM-DD)
│ ├── login.rs # Auth stub (/login)
│ ├── register.rs # Auth stub (/register)
│ └── docs.rs # Docs page (/docs)
├── components/ # Reusable UI
│ ├── header.rs # Navigation bar
│ ├── footer.rs # Footer with external links
│ ├── daily_log_form.rs # Full daily log form (4 sections)
│ └── layouts/
│ └── main_layout.rs # Header + Outlet + Footer wrapper
├── server/ # SSR-only (#[cfg(feature = "ssr")])
│ ├── db.rs # AppState with SqlitePool
│ ├── api/
│ │ └── daily_logs.rs # REST CRUD handlers + OpenAPI
│ └── queries/
│ └── daily_logs.rs # sqlx queries + 7 unit tests
├── shared/ # Framework-agnostic domain types
│ ├── models.rs # DailyLog, DailyLogSummary, ExerciseIntensity
│ └── validation.rs # DailyLogForm with #[derive(Validate)]
├── styles/
│ └── main.scss # SCSS styles
└── bin/
├── ht-cli.rs # Admin CLI (cli feature) — stub
└── ht-gen.rs # Code generator (gen feature) — stub
Feature gating
| Feature | Target | Purpose | Status |
|---|---|---|---|
hydrate | cdylib (WASM) | Client-side hydration | Complete |
ssr | bin (native) | Server-side rendering + API | Complete |
cli | bin (native) | Admin CLI binary | Stub |
gen | bin (native) | Code generator binary | Stub |
Both hydrate and ssr share app.rs, routes/, components/, and shared/ for consistency.
SSR + Hydration flow
- Server renders the initial HTML via
shell()inmain.rs - Browser receives HTML + WASM bundle
- Hydration takes over in
lib.rs, attaching reactivity to existing DOM - Client-side navigation via
leptos_routerfor subsequent pages
Data flow
The app has two parallel data paths:
Path 1: Leptos #[server] functions (UI-driven)
User Action → Form Signal → #[server] function → sqlx query → Database → Response → UI Update
Used by the DailyLogForm component for interactive form submission and loading existing data.
Defined in src/api/mod.rs:
upsert_daily_log(form)— create or update a logget_daily_log(date)— fetch a single logget_daily_logs_for_month(year, month)— calendar summaries
Path 2: REST API (external/CLI-driven)
HTTP Request → Axum handler → sqlx query → Database → JSON Response
Standard HTTP endpoints for CLI tools and external consumers. Swagger UI at /api/docs.
Defined in src/server/api/:
GET /api/daily_logs— list all logs (optional?start_date=and?end_date=)POST /api/daily_logs— create or update a logGET /api/daily_logs/{date}— get single log by dateDELETE /api/daily_logs/{date}— delete log by date
Module dependency rules
routes → components, api (#[server] functions), shared
components → shared (never server, never routes, never api)
server → shared (never components, never routes)
api → shared, server (queries)
shared → (nothing)
This ensures clean separation: domain types have no framework dependencies, server code knows nothing about UI, and components are framework-agnostic where possible.
Database
Single SQLite table daily_logs with columns for body metrics (weight, waist), nutrition (protein, calories), wellness (meditation, exercise + intensity), and sleep. Migrations run automatically on server startup via sqlx.
Dependencies
| Crate | Purpose |
|---|---|
leptos | Reactive UI framework |
leptos_router | Client-side routing |
leptos_meta | Document head management |
leptos_axum | SSR integration |
axum | HTTP server |
sqlx (sqlite, chrono, runtime-tokio-rustls) | Database queries |
validator (derive) | Input validation |
utoipa + utoipa-swagger-ui | OpenAPI spec + Swagger UI |
tokio | Async runtime |
tracing | Observability |