pnpm workspace with apps/web, apps/api, apps/collab, and packages/shared; strict TypeScript base config, repo-wide ESLint (flat) + Prettier, Vitest per package, and root scripts lint/typecheck/test/ build. @dorfteich/shared ships a first health-response helper consumed by apps/api to prove workspace linking. Existing markdown docs are reformatted once by the new Prettier setup. Closes #1 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
106 lines
6.1 KiB
Markdown
106 lines
6.1 KiB
Markdown
# Dorfteich — Architecture Overview
|
|
|
|
This directory is the authoritative architecture documentation. Every
|
|
implementation story references the documents here; when a story and this
|
|
documentation disagree, clarify before coding.
|
|
|
|
## System context
|
|
|
|
Dorfteich is shipped as a set of Docker containers behind a reverse proxy.
|
|
One deployment = one **instance** (e.g. `dorfteich.online`, or a self-hosted
|
|
installation).
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph clients [Clients]
|
|
B[Browser SPA<br/>React + TipTap + Yjs]
|
|
end
|
|
subgraph instance [Dorfteich instance - Docker Compose]
|
|
RP[Reverse proxy]
|
|
WEB[web<br/>static SPA assets]
|
|
API[api<br/>NestJS REST]
|
|
COLLAB[collab<br/>Hocuspocus WebSocket]
|
|
PG[(PostgreSQL)]
|
|
PAN[pandoc-server<br/>doc conversion]
|
|
GOT[Gotenberg<br/>HTML to PDF]
|
|
VOL[/uploads + plugins volume/]
|
|
end
|
|
B -- HTTPS --> RP
|
|
RP --> WEB
|
|
RP -- /api --> API
|
|
RP -- /collab WebSocket --> COLLAB
|
|
API --> PG
|
|
COLLAB --> PG
|
|
API --> PAN
|
|
API --> GOT
|
|
API --> VOL
|
|
COLLAB -. permission checks .-> API
|
|
```
|
|
|
|
- **web** serves the single-page application (static assets).
|
|
- **api** owns all business logic: auth, ponds, pages, labels, permissions,
|
|
quotas, import/export, plugin management, admin functions.
|
|
- **collab** synchronizes CRDT documents (page content) and awareness
|
|
(cursors) over WebSocket and persists document state to PostgreSQL. It
|
|
authenticates clients with short-lived tokens issued by **api**.
|
|
- **pandoc-server** and **Gotenberg** are internal-only conversion sidecars
|
|
(Word/OpenOffice import/export, PDF export).
|
|
- All page content lives in PostgreSQL; binary uploads (images, attachments)
|
|
and installed plugins live on a Docker volume.
|
|
|
|
## Documents
|
|
|
|
### Architecture Decision Records (`adr/`)
|
|
|
|
| ADR | Decision |
|
|
| -------------------------------------------- | ----------------------------------------------------------------- |
|
|
| [0001](adr/0001-typescript-monorepo.md) | TypeScript everywhere, pnpm monorepo |
|
|
| [0002](adr/0002-postgresql.md) | PostgreSQL as the only database |
|
|
| [0003](adr/0003-yjs-crdt-collaboration.md) | Yjs CRDT + Hocuspocus for real-time and offline collaboration |
|
|
| [0004](adr/0004-tiptap-editor.md) | TipTap (ProseMirror) as the WYSIWYG editor |
|
|
| [0005](adr/0005-react-vite-frontend.md) | React + Vite single-page application |
|
|
| [0006](adr/0006-nestjs-prisma-backend.md) | NestJS + Prisma for the API server |
|
|
| [0007](adr/0007-auth-sessions-oidc-ready.md) | Cookie sessions, Argon2id, OIDC-ready identity model |
|
|
| [0008](adr/0008-plugin-sandbox.md) | Sandboxed iframe plugins with a message-based API |
|
|
| [0009](adr/0009-import-export-converters.md) | Pandoc + Gotenberg sidecars for import/export |
|
|
| [0010](adr/0010-postgres-fulltext-search.md) | PostgreSQL full-text search behind a search interface |
|
|
| [0011](adr/0011-file-storage-quotas.md) | Filesystem volume for uploads, DB-tracked quotas |
|
|
| [0012](adr/0012-i18n.md) | i18next with German and English from the start |
|
|
| [0013](adr/0013-versioning-and-trash.md) | Page version history via Yjs snapshots, soft-delete trash |
|
|
| [0014](adr/0014-gitea-actions-cicd.md) | CI/CD with Gitea Actions, staged promotion |
|
|
| [0015](adr/0015-backup-strategy.md) | Nightly pg_dump + uploads sync, 30-day retention, off-host mirror |
|
|
| [0016](adr/0016-self-hosted-fonts.md) | Self-hosted Google Fonts, per-pond font configuration |
|
|
|
|
### Concept documents
|
|
|
|
| Document | Contents |
|
|
| ------------------------------------------------------ | ---------------------------------------------------------------------------- |
|
|
| [data-model.md](data-model.md) | Entities and relations: users, ponds, pages, labels, grants, quotas, plugins |
|
|
| [permissions.md](permissions.md) | Role model and the "most specific setting wins" resolution algorithm |
|
|
| [realtime-collaboration.md](realtime-collaboration.md) | CRDT document lifecycle, cursor sync, offline behavior, versioning hooks |
|
|
| [plugin-architecture.md](plugin-architecture.md) | Plugin manifest, packaging, sandbox runtime, extension points, admin flows |
|
|
| [deployment.md](deployment.md) | Compose stacks for Dev/Test/Int/Prod, environments, promotion pipeline |
|
|
| [operations.md](operations.md) | Monitoring, logging, backup/restore, update strategy for self-hosters |
|
|
| [security.md](security.md) | Threat-driven security concept: authn/authz, sandboxing, uploads, secrets |
|
|
| [roadmap.md](roadmap.md) | Epics and milestones; the order stories are implemented in |
|
|
|
|
## Terminology
|
|
|
|
| German (product vision) | English (code, docs, issues) |
|
|
| ----------------------- | ---------------------------- |
|
|
| Teich | pond |
|
|
| Seite | page |
|
|
| Teich-Admin | Pond Admin |
|
|
| Bearbeitende | Editor |
|
|
| Lesende | Reader |
|
|
| Öffentlichkeit | Public |
|
|
|
|
## Conventions for implementers
|
|
|
|
- Language: English for code, comments, commit messages, and issues.
|
|
- Write clear, human-readable code; document the "why", not the "what".
|
|
- UI strings never appear hard-coded — always through i18n resources
|
|
(see ADR 0012), with German and English translations added in the same
|
|
change.
|
|
- Every story lists the ADRs it depends on; read them before starting.
|