From 85552e0f3f2b294abd1b0cd2a89e054c593a7cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Doma=C5=84ski?= Date: Thu, 2 Apr 2026 15:21:05 +0200 Subject: [PATCH] claude.md --- CLAUDE.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..92ca320 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,71 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +```bash +npm run dev # Start Vite dev server (port 5173) +npm run build # Build production bundle +npm run preview # Preview production build +npm run check # Svelte type checker +npm run check:watch # Type checker in watch mode +``` + +Docker: +```bash +docker-compose up # Dev server with hot reload (port 5173) +``` + +There are no test commands — this project has no test suite. + +## Architecture + +**Fooder** is a Svelte 5 + SvelteKit PWA for tracking food/calories and macronutrients. It's a fully client-side SPA (static adapter, SSR disabled) that communicates with a backend API at `/api`. + +### Routing + +SvelteKit file-based routing with two route groups: +- `(auth)/` — public login/register pages +- `(app)/` — protected pages guarded by auth check in `src/routes/(app)/+layout.svelte` + +Main routes: `/diary/[date]` (primary view), `/diary/[date]/add-entry`, `/diary/[date]/edit-entry/[entry_id]`, `/presets`, `/products/new`. + +### State Management + +Three layers: +1. **Auth** (`$lib/auth/store.svelte.ts`) — Svelte 5 runes-based store holding `accessToken`, `user`, and refresh token (localStorage). +2. **Server data** — TanStack Svelte Query with 30s stale time. Cache keys follow `['diary', date]`, `['products']`, etc. +3. **Offline** (`$lib/offline/`) — Network status in `network.svelte.ts`; IndexedDB (via `idb`) in `db.ts` for persistent cache and mutation queue. + +### Offline-First Pattern + +When offline, mutating functions in `$lib/offline/mutations.ts`: +1. Generate a temporary entry with a negative ID as an optimistic placeholder +2. Update the TanStack Query in-memory cache immediately +3. Persist the change to IndexedDB (survives reload) +4. Enqueue the real API call in an IndexedDB mutation queue + +On reconnect, `$lib/offline/sync.ts` replays the queue FIFO. Sync stops on first failure to preserve consistency; malformed requests are dropped to unblock the queue. + +### API Layer + +`$lib/api/client.ts` is the core fetch wrapper. It handles: +- JWT access token injection and automatic refresh with deduplication (prevents simultaneous refresh races) +- Offline detection: write mutations are queued via the offline system instead of failing +- Auth endpoints (`/token/*`) are never queued — they require a live response + +### Key Technologies + +| Purpose | Library | +|---------|---------| +| Framework | Svelte 5 (Runes: `$state`, `$derived`, `$props`, `$effect`) | +| Meta-framework | SvelteKit 2 | +| Server data cache | TanStack Svelte Query | +| Styling | Tailwind CSS v4 | +| Offline persistence | idb (IndexedDB wrapper) | +| PWA | vite-plugin-pwa (NetworkFirst for `/api/*`) | + +### Svelte 5 Runes + +This project uses Svelte 5 runes syntax throughout — no legacy `writable`/`readable` stores. Use `$state`, `$derived`, `$props`, and `$effect` for all reactive patterns. \ No newline at end of file