# `lib/` conventions

Short rules. The patterns we already follow as of v0.16 — write new code that fits.

**One store per cross-cutting concern.** A single `*-store.ts` file owns each one:

- `auth.ts` — JWT / PIN in `localStorage`, `isAuthenticated` writable
- `ui-store.ts` — bottom-nav visibility, upload-sheet open state, FAB badge count
- `data-mode-store.ts` — Saver vs Original media-loading preference
- `privacy-note-store.ts` — admin-configured Datenschutzhinweis text
- `quota-store.ts` — live per-user storage snapshot
- `upload-queue.ts` — IndexedDB-persisted upload queue + processing state

Don't import these into other stores unless strictly necessary; let pages compose them.

**DTOs mirror Rust types.** All TS interfaces live in `types.ts`. Each one carries a
`// mirrors backend/src/path::TypeName` comment so the two stay searchable. If you add
a Rust DTO, add the TS twin in the same PR.

**Gestures via Svelte actions in `actions/`.** Long-press, double-tap, future swipe —
each is a `use:` action that fires a CustomEvent. Components stay free of gesture
plumbing.

**Reusable bottom sheets via `ContextSheet.svelte`.** Pass an `actions: ContextAction[]`
array. Any page that needs a long-press / kebab context menu uses the same primitive.

**SSE relays are listed in `sse.ts::KNOWN_EVENTS`.** New server event → add one entry
to that array, that's it.

**Diashow transitions live in `diashow/transitions/`.** Each is a Svelte component
plus one entry in `transitions/index.ts`. Adding a new animation is two-line work; no
diashow code needs to change.

**No new global stores** beyond the list above unless the new concept is genuinely
app-wide. Page state belongs in the page.
