YotoShelf
Contribute

Architecture

Go huma API, SQLite/sqlc/goose, Astro + 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

LayerToolSource of truthGenerated 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

DirectoryPurpose
cmd/yotoshelf/CLI entrypoints. The binary's own usage line lists them: serve, create-admin, backup, restore, seed-llm, seed-eval, list-devices, version
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 + Svelte 5 frontend; embedded into the binary via go:embed
frontend/designGit 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.mdCanonical Yoto hardware specs

Tech stack

LayerTechnologies
Backend runtimeGo 1.25, CGO-free (modernc.org/sqlite)
HTTPhuma v2 + chi v5
DatabaseSQLite with sqlc (type-safe queries) and goose (migrations)
Authargon2id password hashing, gorilla/sessions, OIDC (PKCE S256)
Frontend buildAstro, Svelte 5 (runes, not stores), Tailwind v4
UI componentsshadcn-svelte
IconsPhosphor duotone only
i18nParaglide JS: all user-facing strings in frontend/messages/en.json
Image generationIdeogram (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

This sequence is read from the repository's CONTRIBUTING.md when the site is built.

YotoShelf uses four tools that enforce correctness at compile time. Follow this workflow for every change:

1. Write the SQL query

Add your query to internal/db/queries/{domain}.sql:

-- name: GetCardBySlug :one
SELECT id, title, slug, status FROM cards WHERE slug = ?;

Run sqlc generate (or just generate). Type-safe Go appears in internal/db/gen/.

2. Write the huma operation

Add your endpoint to internal/api/{domain}.go:

huma.Register(api, huma.Operation{
    OperationID: "getCard",
    Method:      http.MethodGet,
    Path:        "/cards/{slug}",
    Summary:     "Get card detail",
    Tags:        []string{"cards"},
}, func(ctx context.Context, input *GetCardInput) (*GetCardOutput, error) {
    // Call sqlc-generated query
    card, err := queries.GetCardBySlug(ctx, input.Slug)
    // ...
})

The OpenAPI spec updates automatically when the server starts.

3. Generate frontend types

just generate   # runs sqlc + openapi-typescript

TypeScript types appear in frontend/src/lib/api/types.ts.

4. Use the shared client

import { api } from '$lib/api/client';
const card = await api.getCard({ slug: 'my-card' });

5. Verify

just check      # lint + test + build + govulncheck + npm audit + i18n

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.