Experimental SolidStart demo for offline conflict resolution with:
- SolidJS + SolidStart
- PowerSync (local-first queue + sync)
- TanStack DB (reactive collections)
- Self-hosted local stack via Docker (PowerSync + dual Postgres)
The app is intentionally demo-grade and optimized to show conflict strategy behavior, not production hardening.
work_order.titleandwork_order.priority: Last-write-wins (applied)work_order_note.crdt_payload: simple CRDT-style line merge (merged)part_usage_eventinserts: domain event handling with inventory checks (applied/rejected)work_order.statusand delete actions: role-restricted (rejectedfor tech)work_order.site_contact_phone: manual conflict records (needs_review)
tech: can edit safe fields and create note/part eventsmanager: can resolve conflicts and perform privileged transitions/actions
Role switch is in the top status bar (mock auth via cookie).
- Install dependencies
bun install- Create your env file
cp .env.example .env- Start local PowerSync + Postgres stack
bun run dev:stack:up- Verify PowerSync is up
curl -f http://localhost:8080/probes/liveness- Start the app
bun dev- Open the app and run the demo scenario
- Left: work order list
- Right: work order detail editor
- Top bar: online/offline toggle, role/user, pending queue count, open conflicts
- Bottom panels: sync activity timeline and conflict inbox
- Switch to Tech view and go offline.
- Edit title/priority/phone, edit note, add part event.
- Reconnect; queued writes upload in order.
- Observe sync activity outcomes:
applied,merged,rejected,needs_review. - Switch to Manager view and resolve open phone conflicts in Conflict Inbox.
- Token / audience mismatch:
- Ensure
.envanddocker-compose.ymlvalues match for:POWERSYNC_JWT_KIDPOWERSYNC_JWT_SECRET_B64URLPOWERSYNC_JWT_AUDIENCE
- If mismatched, restart stack:
bun run dev:stack:reset && bun run dev:stack:up
- Ensure
- Replication/publication issues:
- Check source DB publication exists:
docker exec -it powerchat-postgres-source psql -U postgres -d powerchat -c "SELECT pubname FROM pg_publication;"
- Confirm role exists:
docker exec -it powerchat-postgres-source psql -U postgres -d powerchat -c "\du"
- Check source DB publication exists:
- Stale local data / bucket state:
- Reset containers and volumes:
bun run dev:stack:reset - Delete local sqlite cache if needed:
.powersync/powerchat-server.db
- Reset containers and volumes:
- Source DB schema/seed live in
db/and are mirrored into Docker init scripts underdocker/postgres-source/init/. - Backend write handling now lives in vertical slices under
src/slices/(mutation,query,reactionmodules). - Public server functions remain in
src/server/powersync.ts.