docs: setup, hosting, API, architecture and roadmap
ci / backend (push) Canceled after 0s
ci / frontend (push) Canceled after 0s

- SETUP: local dev guide (env vars, DB migrate, backend/frontend, troubleshooting)
- HOSTING: bare-metal guide (systemd + Nginx + TLS + backups) and Docker Compose
  guide (deploy, reverse proxy, updates, backup/restore)
- API: REST contract with curl examples and Socket.IO event protocol
- ARCHITECTURE: stack, data model, auth model, realtime design, theming
- ROADMAP: webapp MVP/next steps plus Tauri desktop clients for Windows, macOS
  and Linux with release-binary plan
This commit is contained in:
x3
2026-09-22 13:33:22 +02:00
parent 5252e3ab4f
commit a407a1381a
5 changed files with 413 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
# Architecture
## Stack
- **Frontend:** Vue 3 (Composition API + `<script setup>`), Vite, Vue Router, Pinia,
Axios, Socket.IO client, TipTap editor. Theme via CSS variables (`data-theme`).
- **Backend:** Node.js 20, Express 4, Socket.IO 4, `pg` (node-postgres), JWT, bcryptjs.
- **DB:** PostgreSQL 14+. Single schema file (`backend/src/db/schema.sql`), applied via
`npm run migrate` or `psql`.
## Data model
```text
users (id, email unique, name, password_hash)
└─< workspace_members (workspace_id, user_id, role) >─┐
workspaces (id, name, owner_id -> users) <───────────────┘
└─< pages (id, workspace_id, parent_id self-FK, title, icon, cover,
content_json JSONB, content_html TEXT, position, is_archived)
└─< comments (id, page_id, author_id, body)
```
- Nesting via `parent_id` self-reference (`ON DELETE CASCADE` removes subtrees).
- Owner auto-added as `workspace_members(role=owner)` via trigger.
- `updated_at` maintained by trigger.
## Auth & authorization
- Register/login return a signed JWT (`sub=user.id`). Client stores it in
`localStorage` and sends `Authorization: Bearer`.
- Every workspace/page route resolves the caller's membership role server-side;
viewers are blocked from mutations (`403`).
- Socket.IO handshake verifies JWT; `page:join` and `page:edit` re-check membership
and role against the DB (never trust client role).
## Realtime design (MVP)
- One Socket.IO room per page (`page:<id>`). Edits are debounced client-side (~800ms),
persisted via REST `PATCH /pages/:id`, then broadcast `page:updated`.
- `page:edit` socket events also persist server-side for clients that only use sockets.
- Presence: server keeps `room -> socketId -> user` map, emits `presence:update`.
- No CRDT/OT in MVP — last-write-wins. Concurrent edits converge on the last saved
version; remote updates are ignored while the local user is the sender (`from`).
See ROADMAP for planned Yjs-based conflict-free editing.
## Theming
- `useThemeStore` (`light`/`dark`/`system`), persisted in `localStorage`,
applied as `document.documentElement.dataset.theme`. All colors are CSS variables.