···239239240240- Help page displays prominent notice that Malfestio is in active development
241241- Links to Bluesky and GitHub for community support
242242+243243+## 8. Offline-First Sync
244244+245245+**Goal**: Users can work seamlessly online or offline with automatic data synchronization.
246246+247247+### High-Level Workflow
248248+249249+1. **Local Storage**: All decks, notes, and cards stored in IndexedDB
250250+2. **Online**: Changes sync immediately to PDS
251251+3. **Offline**: Changes queued locally, sync when reconnected
252252+4. **Conflict**: Visual indicator when local and remote diverge
253253+254254+### Detailed Flows
255255+256256+#### Creating Content (Offline-Capable)
257257+258258+1. User creates/edits deck, note, or card
259259+2. Content saved to IndexedDB immediately
260260+3. If online: queued for sync → pushed to PDS
261261+4. If offline: marked "local_only" or "pending_push"
262262+5. SyncIndicator in header shows current status
263263+264264+#### Viewing Sync Status
265265+266266+1. Header → "Settings"
267267+2. Scroll to "Local Sync Data" section
268268+3. View tabs: Records (all local data) / Queue (pending sync)
269269+4. Actions: Refresh, Clear All, Sync individual items
270270+271271+#### Handling Conflicts
272272+273273+1. System detects conflict (HTTP 409 from PDS)
274274+2. Card marked with "conflict" status
275275+3. User sees conflict count in SyncIndicator
276276+4. Settings → Local Sync Data → "Keep Local" to resolve
277277+5. Or API: `POST /api/sync/resolve/:type/:id`
+56-20
docs/local-dev.md
···292930301. **Start PostgreSQL**
31313232- ```bash
3333- # Using Docker
3434- docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:14
3232+ ```bash
3333+ # Using Docker
3434+ docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:14
35353636- # Or use your local PostgreSQL installation
3737- ```
3636+ # Or use your local PostgreSQL installation
3737+ ```
383839392. **Run migrations**
40404141- ```bash
4242- just migrate
4343- ```
4141+ ```bash
4242+ just migrate
4343+ ```
444445453. **Start backend**
46464747- ```bash
4848- just start
4949- ```
4747+ ```bash
4848+ just start
4949+ ```
50505151- Server runs on <http://localhost:8080>
5151+ Server runs on <http://localhost:8080>
525253534. **Start frontend**
54545555- ```bash
5656- just web-dev
5757- ```
5555+ ```bash
5656+ just web-dev
5757+ ```
58585959- Frontend runs on <http://localhost:3000>
5959+ Frontend runs on <http://localhost:3000>
606061615. **Test OAuth login**
6262- - Navigate to <http://localhost:3000/login>
6363- - Enter your Bluesky handle (e.g., `thunderbot.bsky.social`)
6464- - Authorize the application on bsky.social
6565- - Verify redirect back to app with successful login
6262+ - Navigate to <http://localhost:3000/login>
6363+ - Enter your Bluesky handle (e.g., `thunderbot.bsky.social`)
6464+ - Authorize the application on bsky.social
6565+ - Verify redirect back to app with successful login
66666767### OAuth Flow Details
6868···83832. Click "Publish" to publish to your PDS
84843. Check your Bluesky profile at <https://bsky.app> to see the published record
85854. Verify record appears in your AT Protocol repository
8686+8787+## Testing Sync Flow
8888+8989+The app supports offline-first editing with automatic sync when online.
9090+9191+### Local Storage (IndexedDB)
9292+9393+All decks, notes, and cards are stored locally in IndexedDB via Dexie.js. You can view this data:
9494+9595+1. Navigate to Settings page
9696+2. Scroll to "Local Sync Data" section
9797+3. Use the Records/Queue tabs to view stored data
9898+9999+### Testing Offline Mode
100100+101101+1. Create or edit a deck while online → syncs immediately
102102+2. Disconnect network (DevTools → Network → Offline)
103103+3. Create/edit content → stored locally with "local_only" or "pending_push" status
104104+4. Reconnect → content auto-syncs when online status changes
105105+106106+### Sync Statuses
107107+108108+| Status | Meaning |
109109+| -------------- | -------------------------------- |
110110+| `local_only` | New content, never synced |
111111+| `synced` | Content matches PDS |
112112+| `pending_push` | Local changes waiting to sync |
113113+| `conflict` | Local and remote versions differ |
114114+115115+### Conflict Resolution
116116+117117+When conflicts occur:
118118+119119+1. Settings → Local Sync Data shows records with "conflict" status
120120+2. Click "Keep Local" to overwrite remote with local version
121121+3. Or use the API: `POST /api/sync/resolve/:type/:id` with strategy
8612287123## Verifying Your Setup
88124