# CLAUDE.md This file provides guidance to Claude Code when working with this {{PROJECT_NAME}} codebase. ## Project Overview **{{PROJECT_NAME}}** - An offline-first Progressive Web App for {{MODEL_DISPLAY_NAME}} management, built with SvelteKit frontend and Odoo Studio backend. ## Development Commands ### Development ```bash npm run dev # Start dev server at http://localhost:5173 ``` ### Building ```bash npm run build # Production build (outputs to /build) npm run preview # Preview production build locally ``` ### Type Checking ```bash npm run check # Run svelte-check for type errors npm run check:watch # Watch mode for type checking ``` ## Environment Setup Required environment variables in `.env`: ```env ODOO_URL=https://your-instance.odoo.com ODOO_DB=your-database-name ODOO_USERNAME=your-username ODOO_API_KEY=your-api-key ODOO_PRIMARY_MODEL=x_{{MODEL_NAME}} ``` **Important**: The app uses API keys (not passwords) for Odoo authentication. These are server-side only and never exposed to the client. ## Architecture ### Three-Layer Data Flow ``` Frontend Component (Svelte) ↓ Cache Store (Svelte Store) ↓ Odoo API Client (src/lib/odoo.js) ↓ Server Route (src/routes/api/odoo/+server.js) ↓ Odoo JSON-RPC Backend ``` Data also persists to localStorage for offline access. ### Key Architectural Patterns #### 1. **Smart Caching Layer** (`src/lib/stores/cache.js`) The centerpiece of the frontend architecture. This Svelte store provides: - **Immediate data availability**: Shows cached data from localStorage instantly on page load - **Background sync**: Automatically syncs with Odoo every 3 minutes if cache is stale (>5 minutes old) - **Incremental fetching**: Only fetches records with `id > lastRecordId` to minimize API calls - **Optimistic updates**: UI updates immediately, syncs to server in background **Key functions**: - `initialize()` - Call in `onMount()`, loads cache and starts background sync - `sync()` - Incremental sync with Odoo - `forceRefresh()` - Clears cache and does full sync - `createRecord()`, `updateRecord()`, `deleteRecord()` - CRUD operations with optimistic updates #### 2. **Server-Side API Proxy** (`src/routes/api/odoo/+server.js`) SvelteKit server route that acts as a JSON-RPC proxy to Odoo. This pattern: - Keeps credentials server-side (never exposed to client) - Caches Odoo UID to reduce authentication calls - Provides a simple `{ action, data }` interface for the frontend **Supported actions**: `create`, `search`, `search_model`, `update`, `delete` #### 3. **Odoo Field Formatting** Odoo uses specific formats for relational fields: - **Many2One (single relation)**: Send as integer ID, receive as `[id, "display_name"]` tuple - **Many2Many (multiple relations)**: Send as `[[6, 0, [id1, id2, ...]]]`, receive as array of tuples Helper functions in `src/lib/odoo.js`: - `formatMany2one(id)` - Converts ID to integer or `false` - `formatMany2many(ids)` - Wraps IDs in Odoo command format `[[6, 0, [...]]]` #### 4. **Offline-First Strategy** Two-phase data loading: 1. **Immediate Load**: Show cached data from localStorage 2. **Background Sync**: Fetch new data if cache is stale ```javascript // Phase 1: Load from cache immediately const cachedData = loadFromStorage(); updateUI(cachedData); // Phase 2: Background sync if stale if (cachedData.isStale) { syncInBackground(); } ``` ### SvelteKit Configuration - **Rendering**: `ssr: false`, `csr: true`, `prerender: true` in `src/routes/+layout.js` - **Adapter**: `adapter-static` configured for static output to `/build` directory - **Base path**: Configurable via `PUBLIC_BASE_PATH` env var (for GitHub Pages deployment) ### PWA Features Configured in `vite.config.js`: - **Service Worker**: Auto-generated with Workbox, caches all static assets - **Auto-update**: New versions automatically activate - **Manifest**: Configured for standalone mode, installable on mobile - **Icons**: 192x192 and 512x512 PNG icons in `/static` ## Odoo Model Structure ### Main Model: `x_{{MODEL_NAME}}` | Field | Type | Purpose | |-------|------|---------| | `x_name` | Char | Record name | | Add your custom fields with x_studio_ prefix | ## Important Development Notes ### Working with the Cache When modifying record-related features: 1. **Always call `{{MODEL_NAME}}Cache.sync()` after mutations** (create/update/delete) 2. **Initialize the cache in page components**: `onMount(() => {{MODEL_NAME}}Cache.initialize())` 3. **Clean up on unmount**: `onDestroy(() => {{MODEL_NAME}}Cache.destroy())` 4. **Cache invalidation**: Increment cache version in `cache.js` if store schema changes ### Odoo API Patterns When adding new Odoo operations: 1. **Frontend**: Add method to `src/lib/odoo.js` (calls `/api/odoo` endpoint) 2. **Backend**: Add new action case in `src/routes/api/odoo/+server.js` 3. **Use `execute()` helper** for model operations (wraps authentication) Example: ```javascript // Frontend (odoo.js) async customOperation(id) { return this.callApi('custom', { id }); } // Backend (+server.js) case 'custom': const result = await execute('x_{{MODEL_NAME}}', 'write', [[data.id], { custom_field: true }]); return json({ success: true, result }); ``` ### PWA Manifest Updates When changing app name, icons, or theme: 1. Update `vite.config.js` manifest section 2. Update `/static/manifest.json` 3. Replace `/static/icon-192.png` and `/static/icon-512.png` 4. Run `npm run build` to regenerate service worker ### Deployment **Vercel** (primary): - Automatically deploys from `main` branch - Set environment variables in Vercel dashboard - Outputs to `/build` directory (configured in `vercel.json`) **GitHub Pages**: - Set `PUBLIC_BASE_PATH=/repo-name` in GitHub Actions secrets - Configure GitHub Pages source as "GitHub Actions" - Workflow auto-deploys on push to `main` ## File Structure Reference ``` src/ ├── lib/ │ ├── stores/ │ │ └── cache.js # Core caching & sync logic │ ├── odoo.js # Frontend API client │ ├── db.js # IndexedDB manager │ └── utils.js # Utility functions ├── routes/ │ ├── +layout.js # Root layout config (SSR/CSR settings) │ ├── +layout.svelte # Root layout component │ ├── +page.svelte # Add record form │ ├── list/+page.svelte # List all records │ └── api/odoo/+server.js # Odoo JSON-RPC proxy endpoint └── app.html # HTML template with PWA meta tags ``` ## Common Gotchas 1. **Odoo field naming**: All custom fields use `x_studio_` prefix (Odoo Studio convention) 2. **Partner name format**: Odoo returns `[id, "name"]` tuples, must extract display name for UI 3. **localStorage limits**: Browser typically allows 5-10MB, sufficient for hundreds of records 4. **Service worker caching**: After PWA updates, users may need to close all tabs and reopen 5. **Base path in production**: GitHub Pages deployments require `PUBLIC_BASE_PATH` env var set 6. **API authentication**: Use API keys, not passwords. Generate in Odoo user settings. ## Adding New Features ### Add a New Field 1. Add field in Odoo Studio with `x_studio_` prefix 2. Update `fields` array in `src/lib/stores/cache.js` 3. Add form input in `src/routes/+page.svelte` 4. Display field in `src/routes/list/+page.svelte` ### Add a New Page 1. Create `src/routes/new-page/+page.svelte` 2. Add navigation link in layout or other pages 3. Import and use cache store if accessing data ### Add Partner/Relation Field 1. Add Many2one or Many2many field in Odoo 2. Use `odooClient.formatMany2one()` or `formatMany2many()` when saving 3. Use `odooClient.fetchPartners()` to load options 4. Display resolved names in UI --- **Generated with Odoo PWA Generator**