docs: update FEATURES, ARCHITECTURE, and OpenAPI spec for image attachments

- FEATURES.md: document client-side optimization, thumbnails, offline support, SW caching
- ARCHITECTURE.md: add attachment data flow section (client → optimize → IDB/server → SW cache)
- openapi.yaml: add &thumb=1 query param, thumbnail FormData field, thumbnailPath in Attachment schema, attachments array in Note schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Frederic Cabassut
2026-03-08 22:37:50 +01:00
committed by Fred Cabassut
co-authored by Claude Opus 4.6
parent 6e1cf941fc
commit 2d001383fa
3 changed files with 37 additions and 5 deletions
+9 -1
View File
@@ -49,6 +49,14 @@ For a single-user app with multiple devices:
- If timestamps match: higher version wins
- If both match: local version is preferred
### Attachment Data Flow
1. User drops/picks image in NoteEditor
2. Client optimizes: resize ≤1920px, compress to WebP, generate 200px thumbnail
3. **Online**: POST optimized + thumbnail to `/api/notes/{id}/attachments` → server saves to `data/attachments/` + DB
4. **Offline**: store blobs in IDB `pendingAttachments` store → display via `URL.createObjectURL()` → on reconnect, sync pushes to server
5. **Display**: NoteCard uses `&thumb=1` URL (200px WebP), editor shows full-size
6. **SW Caching**: `CacheFirst` rule caches attachment URLs — previously-viewed images available offline
## Tech Stack Rationale
### SvelteKit
@@ -89,7 +97,7 @@ Key tables:
- `notes` - Core note data with version tracking
- `tags` - Unique tag names
- `note_tags` - Many-to-many note ↔ tag
- `attachments` - Image file metadata
- `attachments` - Image file metadata (path + thumbnailPath)
- `sync_log` - Sync operation history
## File Organization
+10 -4
View File
@@ -42,7 +42,13 @@
- Upload images via file picker or drag-and-drop
- Supports JPEG, PNG, GIF, WebP, SVG
- Max file size: 10MB
- Thumbnail previews in note cards
- **Client-side optimization**: images resized to fit 1920×1920, compressed to WebP (~80% quality), transparent PNGs preserved
- **Auto-generated thumbnails**: 200×200 WebP at 60% quality for fast card previews
- Thumbnail strip on note cards (up to 3 images, "+N" badge for more)
- Full-size images in editor, thumbnails on cards (`&thumb=1`)
- **Offline support**: optimized blobs stored in IndexedDB, displayed via blob URLs, auto-synced on reconnect
- Pending upload indicator on offline-queued images
- Service worker CacheFirst caching for previously-viewed images
- Remove attachments from editor
### Tag Organization
@@ -90,9 +96,9 @@
### PWA / Offline-First
- Installable as standalone app
- Web app manifest with icons
- Service worker for asset caching
- IndexedDB for local data storage
- Background sync every 30 seconds
- Service worker for asset caching (CacheFirst for attachments, NetworkFirst for API)
- IndexedDB for local data storage (notes + pending attachments)
- Background sync every 30 seconds (notes + offline attachments)
- LWW conflict resolution for multi-device use
- Sync status indicator (synced/syncing/offline/error)
+18
View File
@@ -185,6 +185,12 @@ paths:
in: query
schema:
type: string
- name: thumb
in: query
description: Set to "1" to return the thumbnail instead of the full image (requires attachmentId)
schema:
type: string
enum: ['1']
responses:
'200':
description: Attachment list (without attachmentId) or file content (with attachmentId)
@@ -209,6 +215,10 @@ paths:
type: string
format: binary
description: Image file (max 10MB)
thumbnail:
type: string
format: binary
description: Pre-generated thumbnail (WebP, ~200px)
responses:
'201':
description: Attachment metadata
@@ -368,6 +378,10 @@ components:
type: array
items:
type: string
attachments:
type: array
items:
$ref: '#/components/schemas/Attachment'
NoteInput:
type: object
@@ -415,6 +429,10 @@ components:
type: string
size:
type: integer
thumbnailPath:
type: string
nullable: true
description: Server path to thumbnail file (null if no thumbnail)
createdAt:
type: string
format: date-time