This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
WhatsApp Backup Reader - a hybrid SvelteKit + Electron app for parsing and viewing WhatsApp chat exports offline. Runs as both a web app (GitHub Pages) and desktop app.
Core principles: 100% offline, privacy-first (no external API calls), all processing client-side.
# Development
npm run dev # Web app on localhost:5173
npm run electron:dev # Electron app (runs Vite + Electron concurrently)
# Build
npm run build # SvelteKit build → build/
npm run electron:build # Build + Electron packaging → dist-electron/
# Code quality
npm run lint # Biome check (NOT ESLint)
npm run lint:fix # Auto-fix lint issues
npm run format # Format with Biome
npm run check # TypeScript + Svelte validation
# i18n
npm run machine-translate # Auto-translate with inlangThis project uses Svelte 5 runes exclusively. Never use Svelte 4 stores (writable, derived, readable).
State lives in *.svelte.ts files using factory functions:
src/lib/state.svelte.ts- Main app statesrc/lib/bookmarks.svelte.ts- Bookmark managementsrc/lib/transcription.svelte.ts- Audio transcription statesrc/lib/gallery.svelte.ts- Media gallery state
Key patterns:
- Use
$state,$derived,$effectrunes - Never mutate state directly:
items = [...items, x]notitems.push(x) - Use
$props()for component props, notexport let - Use callback props for events, not
createEventDispatcher
Heavy operations run in workers to avoid blocking main thread:
src/lib/workers/index-worker.ts- Search index buildingsrc/lib/workers/search-worker.ts- Search queries with progress
Uses Paraglide JS (compile-time i18n). Source files in messages/. Never hardcode user-facing strings.
<script>
import * as m from '$lib/paraglide/messages';
</script>
<input placeholder={m.search_placeholder()} />To add translations: add key to messages/en.json, run npm run machine-translate.
- Web: Base path
/whats-readerfor GitHub Pages (whenGITHUB_PAGES=true) - Electron: Relative paths (
base: './') forfile://loading
Electron files: electron/main.cjs, electron/preload.cjs
- Tab indentation (width 2)
- Single quotes
- Semicolons required
- Many rules disabled for
.sveltefiles due to false positives
Use example files in examples/chats/ for testing:
private-chat/- Individual chat with audiofamily-group-chat/- Group chat
Create test ZIPs: cd examples/chats && ./build-zips.sh
feat: ... # Minor version bump
fix: ... # Patch version bump
perf: ... # Patch version bump
docs: ... # No release
chore: ... # No release
Merging to main triggers semantic-release, builds, and GitHub Pages deploy.
Never manually edit CHANGELOG.md or package.json version.
- No external API calls - violates privacy promise
- No Svelte 4 stores - use runes only
- No ESLint - project uses Biome
- No hardcoded strings - use paraglide
m.key() - No heavy main-thread operations - use workers