YotoShelf
Contribute

Conventions

File-size limits, structural conformity, conventional commits, i18n string naming, and error handling.

File size limits

CI enforces file size limits to keep code maintainable. These are hard limits — the pipeline fails if they are exceeded.

File typeLimitScope
Go files 400 lines Excludes generated files (internal/db/gen/) and test files
Svelte components 250 lines All .svelte files

If a file approaches the limit, split it. Every file should have a single responsibility. The goal is a codebase where any file can be read and understood without scrolling.

Structural conformity

Before writing any new code, find an existing example of the same pattern and follow it exactly. Never introduce a pattern that has no precedent in the codebase.

What you're buildingWhere to look
New API endpointinternal/api/cards.go — huma.Register pattern
New sqlc queryinternal/db/queries/cards.sql — query style
New job typeinternal/jobs/handlers_track_edit.go — Register + handler pattern
New Svelte componentAn existing component of similar size and purpose
New API client functionfrontend/src/lib/api/client.ts — existing function style
Error handling in GoErr(ctx, status, msg, err) — never raw errors
Error handling in Svelteconst { data, error } = await client.X() — never raw fetch
IconsPhosphor duotone only — import X from 'phosphor-svelte/lib/X'

Conventional commits

All commits follow the Conventional Commits specification. The type prefix is required.

TypeWhen to use
featA new feature
fixA bug fix
docsDocumentation only changes
refactorCode change that neither fixes a bug nor adds a feature
testAdding or correcting tests
choreTooling, deps, CI changes

Example: fix(cards): return 404 when card slug not found

Internationalization (i18n)

All user-facing strings live in frontend/messages/en.json and are accessed via Paraglide JS. CI fails on hardcoded English strings in Svelte files.

Key naming convention: area_context_description.

PrefixArea
nav_Sidebar / navigation
cards_Card grid, selectors
tracks_Track list, detail editor
publish_Publish matrix, progress
icons_Icon generation, editor
settings_Settings page
admin_Admin panel
common_Shared labels (Cancel, Save, Close, etc.)
aria_Accessibility labels

Error handling

Go handlers must use named error constants from internal/api/errors.go — never invent error strings inline:

// Correct — pick from the catalog
return nil, ErrCardNotFound

// Wrong — inventing a string
return nil, huma.Error404NotFound("card not found")

The Err(logger, status, msg, err) helper in internal/api/helpers.go logs the error and returns a huma error response in one call. Use it for all error paths that are not covered by a named constant.

Package READMEs

Every internal/ package has a README.md explaining its purpose, dependencies, and dependents. Read it before modifying a package. Keep it current when adding new dependencies or changing the package's scope.