Architecture
Go huma API, SQLite/sqlc/goose, Astro 6/Svelte 5 frontend, go-yoto client, and the design system.
Four frameworks enforce correctness at compile time. Understanding them before making changes is essential — they interact, and bypassing one usually breaks another.
The four frameworks
| Layer | Tool | Source of truth | Generated output |
|---|---|---|---|
| API | huma v2 | Go I/O structs in internal/api/ | OpenAPI spec |
| Database | sqlc | SQL in internal/db/queries/*.sql | Go in internal/db/gen/ |
| Migrations | goose | SQL in internal/db/migrations/ | Schema with rollback |
| Config | koanf | internal/config/config.go | Validated config struct |
| Frontend types | openapi-typescript | huma's generated OpenAPI spec | frontend/src/lib/api/types.ts |
| Frontend client | openapi-fetch | Generated types | frontend/src/lib/api/client.ts |
Repository layout
| Directory | Purpose |
|---|---|
cmd/yotoshelf/ | CLI entrypoints: serve, create-admin, seed, migrate |
internal/api/ | huma API operations (HTTP layer). One file per domain. |
internal/db/ | SQLite, goose migrations, sqlc queries, and generated code |
internal/config/ | koanf configuration struct and loader |
internal/ | Domain packages: auth, card, icons, jobs, labels, and others |
frontend/ | Astro 6 + Svelte 5 frontend; embedded into the binary via go:embed |
frontend/design | Git submodule — this site's design tokens, components, and brand assets |
e2e/ | Playwright end-to-end tests |
scripts/ | CI helper scripts (file size check, i18n check) |
docs/hardware.md | Canonical Yoto hardware specs |
Tech stack
| Layer | Technologies |
|---|---|
| Backend runtime | Go 1.25, CGO-free (modernc.org/sqlite) |
| HTTP | huma v2 + chi v5 |
| Database | SQLite with sqlc (type-safe queries) and goose (migrations) |
| Auth | argon2id password hashing, gorilla/sessions, OIDC (PKCE S256) |
| Frontend build | Astro 6, Svelte 5 (runes — not stores), Tailwind v4 |
| UI components | shadcn-svelte |
| Icons | Phosphor duotone only |
| i18n | Paraglide JS — all user-facing strings in frontend/messages/en.json |
| Image generation | Ideogram (recommended AI provider) |
go-yoto sibling module
The Yoto API client lives in a separate module at
gitlab.com/yotoshelf/go-yoto.
It is a standalone library — not a subdirectory of this repository. Changes to Yoto API
integration belong there; changes to how YotoShelf calls it belong in internal/.
Design submodule
frontend/design is a git submodule pointing at
yotoshelf/yotoshelf.dev
— this documentation site, which is also the canonical home of the design system.
It provides design tokens, shared Svelte components, fonts, and brand assets.
The submodule must be initialised before building the frontend:
git submodule update --init New feature workflow
Every new feature follows this sequence:
- Write the SQL query in
internal/db/queries/{domain}.sql - Run
just generate— sqlc emits type-safe Go intointernal/db/gen/ - Write the huma operation in
internal/api/{domain}.go - Run the server — the OpenAPI spec updates automatically
- Run
just generateagain — openapi-typescript updatesfrontend/src/lib/api/types.ts - Use the shared typed client in Svelte:
import { api } from '$lib/api/client' - Build the UI component in Svelte 5 with typed props
Structural conformity
Before writing any new code, find an existing example of the same pattern and follow it exactly. See the lookup table in AGENTS.md for which file to reference for each kind of change. New patterns that have no existing precedent in the codebase require human approval.