Files
libnovel/v3/ui/AGENTS.md
Admin a85636d5db feat(v3): add v3 stack — backend rewrite, renamed env vars, docs
- New Go backend binary (backend + runner) replacing old scraper/
- Rename SCRAPER_API_URL → BACKEND_API_URL in UI env and docker-compose
- Rename scraperFetch → backendFetch across all 19 UI server files
- Remove SCRAPER_PROXY env var and proxy transport from browser.Config
- Add Meilisearch, Valkey, Caddy to docker-compose
- Add docs/: api-endpoints.md, request-flow.mermaid.md, data-flow.mermaid.md
2026-03-22 17:27:32 +05:00

2.5 KiB

LibNovel UI — Agent Context

SvelteKit 2 + Svelte 5 frontend. Node adapter for production; served behind Caddy.

Design System

ACTIVE_STYLE: branded

Custom amber + zinc dark palette. No shadcn CLI defaults — primitives are hand-authored to match.

Token Value
Accent #f59e0b (amber-400)
Surface-1 zinc-900
Surface-2 zinc-800
Surface-3 zinc-700
Text-primary zinc-100
Text-secondary zinc-400
Destructive red-400

Tailwind

Version: 4 — configured entirely via @theme {} in src/app.css and the @tailwindcss/vite plugin.

There is no tailwind.config.ts — do not create one. Do not run npx shadcn-svelte add ... — primitives are hand-authored in $lib/components/ui/.

shadcn-svelte Primitives

All in src/lib/components/ui/:

Component Variants / Notes
button default / secondary / outline / ghost / destructive / link; sizes: default / sm / lg / icon
badge default / secondary / outline / destructive
card Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter
textarea bindable value prop
dialog Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter
separator horizontal / vertical

Always use cn() from $lib/utils — never template-literal class conditionals.

Svelte 5 Conventions

  • @Observable / runes ($state, $derived, $effect, $props()) for all new code.
  • Do not add ObservableObject / @Published — they don't exist in Svelte; don't introduce legacy writable stores for new code.
  • Navigation: goto() from $app/navigation; page from $app/state.

iOS/UX Skill

For any view work, load the ios-ux skill at task start:

skill({ name: "ios-ux" })

Key Files

File Role
src/app.css Tailwind v4 @theme tokens — source of truth for all design tokens
src/lib/utils.ts cn() helper (clsx + tailwind-merge)
src/lib/types.ts Shared client-safe domain types
src/routes/+layout.svelte Root layout: sticky nav, persistent <audio> element, mini-player bar
src/lib/audio.svelte.ts Global audio store (Svelte 5 runes class)
src/lib/components/ui/ shadcn-style UI primitives

Persistent Audio Element

The <audio> element in +layout.svelte must never be conditionally rendered (no {#if}). Conditional rendering destroys and recreates the element, triggering onpause mid-playback. Keep it always in the DOM; control it via audioStore.