# Findings — Anytype, AFFiNE, AppFlowy: the CRDT local-first workspace cohort Date: 2026-06-14 Source kind: **modern shipped products (cohort dive)** — three open-source, local-first "all-in-one workspace" tools studied together; candidate shards of a **new substrate family: CRDT-synced local-first stores** Lens: shard-wiki — the CRDT substrate and its native-merge / P2P / E2EE implications for the adapter contract > Why one combined memo. Anytype, AFFiNE, and AppFlowy are the open-source local-first > Notion/Miro alternatives, and they share the one trait the prior eleven systems never > had: **the store is a CRDT** (Anytype's *any-sync*, AFFiNE's *Yjs/y-octo*, AppFlowy's > *Yrs*). That single fact changes the adapter math — **the backend performs conflict- > free merge itself**, history is a CRDT update log (not git), and content arrives as a > replica/export, not files or rows. Studying them together isolates the *substrate* > contribution from each tool's surface features and avoids triplicating boilerplate. > Per-tool sections (§1–§3), then the cohort thesis and what it means for shard-wiki > (§4 onward). Contrast set: file-store (Obsidian/Logseq), client-DB (Roam), hosted-DB (Notion), SQLite-local+file-sync (Joplin). This cohort adds **CRDT-replica** as a substrate. --- ## 1. Anytype — P2P, E2EE, typed object graph (any-sync) - **Substrate:** the open **any-sync** protocol — **local-first, peer-to-peer, end-to-end encrypted** CRDT. Infrastructure is four node types: **sync, file, consensus, coordinator**; **backup nodes store ciphertext they cannot read**. Every change is **encrypted and signed with the user's private key**, verified via a shared public key. Files via **IPFS**. - **Data model:** **spaces** = graph-based databases; users define **custom object types with relations** ("everything is an object"; a user-editable **ontology**). Closest to Notion's typed model but **local-first + E2EE + user-owned schema**. - **Extension:** an **open API** for integrations, **plus MCP support** (AI-agent collaboration) — a notable modern surface (a shard speaking MCP). - shard-wiki read: the **most decentralized + encrypted** shard yet — no single canonical endpoint (attach a local replica or a node), content opaque without keys (UC-61), typed object graph (UC-58), CRDT merge (UC-64). ## 2. AFFiNE — docs + whiteboard + DB as views of one block set (Yjs/BlockSuite) - **Substrate:** **Yjs CRDT** via **y-octo** (native Rust Yjs) over **OctoBase** (Rust local-first engine). Local-first by default; optional **WebSocket realtime** sync to AFFiNE Cloud or self-host (MPL-2.0, Docker). - **Editor:** **BlockSuite** — an open block-editor framework providing the **page editor, the edgeless canvas, and block types (incl. databases/embeds)**. - **Headline:** **docs, whiteboards, and databases are *views of the same underlying data*** — one block set rendered as page mode, edgeless canvas, or DB views. CRDT guarantees offline edits "merge mathematically perfectly" on reconnect. - shard-wiki read: the **one-data-many-renderings** model shipped (ZigZag dimensions, UC-47/48), with **non-Markdown spatial content** (edgeless canvas, UC-55) and CRDT merge (UC-64). ## 3. AppFlowy — Rust/Flutter, Notion-style DBs over Yrs CRDT - **Substrate:** **Yrs** (Rust Yjs) wrapped as **AppFlowy-Collab** — CRDT primitives + persistence + domain objects (documents, **databases**, folders, importers, plugins, user state). **Pluggable storage/sync:** RocksDB (native) / IndexedDB (wasm) locally; **Supabase or AppFlowy Cloud** (self-hostable) for sync, via **trait-based local-only vs cloud**. - **Data model:** Notion-like **databases with views** (grid/board/calendar), typed fields. Flutter UI + Rust core, modular. - shard-wiki read: a **self-hostable CRDT Notion** — typed DBs + views (UC-58, UC-54), CRDT merge (UC-64), self-host sync endpoint (UC-57). --- ## 4. The cohort thesis — CRDT changes the adapter math All three converge on **CRDT-synced, local-first, open-source, self-hostable** stores with **typed/database object models** and **non-Markdown content** (canvas/DB). The *substrate* is the new thing, and it has four consequences shard-wiki must absorb: 1. **Native, conflict-free merge (UC-64).** The backend resolves concurrent edits itself (Yjs/Yrs/any-sync). shard-wiki must **not impose git/text merge** on a CRDT shard; it either speaks the CRDT (replica) or stays a **projection/overlay** that respects CRDT semantics. This adds a **merge-model** capability: `none → git/text → native-CRDT` — a candidate **thirteenth spectrum** for the contract (after Joplin's content-opacity twelfth). 2. **History is a CRDT update log, not git (UC-36).** No portable commit history; the coordination journal **supplements** (like Notion/Joplin), or shard-wiki snapshots the replica over time. 3. **The attach surface is a replica or a sync endpoint, not files/rows.** Attach a **local CRDT replica** (offline, full state) or the **self-host sync server's API** (AFFiNE Cloud / AppFlowy Cloud / any-sync node). Anytype adds **P2P with no single canonical endpoint** (UC-65) and **E2EE content opacity** (UC-61). 4. **Typed object graphs + multi-view (UC-58, UC-47/48, UC-55).** User-editable ontologies (Anytype types/relations), Notion-style DBs (AppFlowy), and one-block-set- many-renderings (AFFiNE page/canvas/DB) — the structured + dimensional demands the prior dives raised, now local-first. These are **sync layers** (any-sync, Yjs sync, AppFlowy Cloud) — like Joplin, the **not-a-file-sync-daemon** boundary applies: shard-wiki attaches a **replica/projection as pages** and does **not** re-implement or re-drive their CRDT sync. --- ## 5. Comparative matrix | | Anytype | AFFiNE | AppFlowy | |---|---------|--------|----------| | CRDT | any-sync (custom) | Yjs (y-octo) | Yrs | | Sync | **P2P + nodes, E2EE** | WebSocket, cloud/self-host | RocksDB local + cloud/Supabase | | Encryption | **E2EE (default)** | optional (transport/self-host) | self-host boundary | | Local engine | local + IPFS files | OctoBase (Rust) | RocksDB / IndexedDB | | Data model | **typed object graph (ontology)** | blocks; **doc/canvas/DB = one data, many views** | Notion-style **DBs + views** | | Non-MD content | objects, files | **edgeless canvas** | board/calendar/grid | | Extension | **open API + MCP** | BlockSuite framework | Flutter/Rust modules; plugins (roadmap) | | Self-host | backup/sync nodes | Docker (MPL-2.0) | AppFlowy Cloud | | Markdown | export (lossy) | import/export (lossy) | import/export (lossy) | --- ## 6. Combined capability profile (as a shard) | Capability | This cohort | Notes for the adapter contract | |------------|-------------|--------------------------------| | Read | yes (replica or sync API) | local CRDT replica (offline) or self-host/P2P endpoint | | Write | yes, **CRDT-mediated** | writes are CRDT ops; respect merge — don't overwrite | | Merge | **native CRDT (conflict-free)** | **new capability**: backend owns merge; no external git merge (UC-64) | | Write granularity | block/object | fine-grained | | Identity / addressing | object/block IDs (CRDT-assigned) | fine-grained, store-minted (UC-51) | | Structure | **typed object graph / DBs + relations** | user-editable ontology (Anytype); DB views (AppFlowy) (UC-58) | | History | **CRDT update log, not git** | supplement / snapshot (UC-36) | | Native query | varies (graph/DB filters) | delegate where present (UC-52) | | Subscribe | realtime CRDT sync / P2P | push by nature; attach as replica (UC-31) | | Content opacity | **Anytype E2EE → ciphertext** | opaque without keys (UC-61) | | Endpoint model | **replica / self-host server / P2P (Anytype)** | no single canonical URL for P2P (UC-65) | | Content types | docs + **canvas/DB/objects** | non-Markdown (UC-55); multi-view (UC-47/48) | | Markdown | lossy export | fidelity report (UC-59) | | Attach modes | CRDT replica · self-host API · (Anytype) MCP/open API | new substrate row in the taxonomy | Verdict: a **demanding but coherent new family** — best attached as a **local replica (offline, full CRDT state)** projected to pages, or via a **self-host sync endpoint**; Anytype additionally **P2P + E2EE** (replica-only/opaque). Standout demands: **native-CRDT merge** (UC-64) and **P2P/no-central-endpoint + E2EE** (UC-65/UC-61). --- ## 7. Mapping to shard-wiki INTENT (compare, do not equate) ### 7.1 Reinforcements - **Local-first sovereignty** is the cohort's whole pitch — strong INTENT alignment; each is a legitimate sovereign shard with user-owned data. - **Self-hostable + open-source** means shard-wiki can attach within a user's trust boundary (good for the L0→L4 authz ladder). - **One-data-many-views** (AFFiNE) and **typed object graphs** (Anytype/AppFlowy) are the dimensional (UC-47/48) and structured (UC-58) demands, now validated local-first. ### 7.2 Deliberate divergences (design bugs if conflated) 1. **Do not impose git/text merge on a CRDT shard.** The backend merges; shard-wiki respects CRDT semantics or stays a projection/overlay (UC-64). Treating a CRDT shard like a file shard corrupts it. 2. **Not a sync daemon.** any-sync/Yjs/AppFlowy Cloud already sync; shard-wiki attaches a **replica as pages**, never re-drives their sync (INTENT not-a-file-sync-daemon). 3. **P2P has no canonical endpoint.** Don't model the shard as a URL; attach a replica or a named peer/node (UC-65). 4. **E2EE shards are opaque** without keys — backup/structure-shell only (UC-61). 5. **Proprietary CRDT/object formats are lossy to Markdown** — translate with a fidelity report (UC-59), one workspace = one shard, not the federation layer. ### 7.3 What the cohort teaches that shard-wiki should keep - Add a **merge-model** capability (`none / git / native-CRDT`) so CRDT shards are handled correctly (UC-64) — a thirteenth capability spectrum. - Add **CRDT-replica** to the substrate/attachment taxonomy, and **P2P/no-central- endpoint** as a binding mode (UC-64/65). - **MCP as an integration surface** (Anytype) is worth noting — a shard may expose an AI-agent protocol shard-wiki could consume or coexist with. --- ## 8. Use-case seeds → catalog (promoted 2026-06-14) Last existing UC is **UC-63**. New UCs **UC-64, UC-65** added; existing UCs enriched. | Seed | Catalog action | |------|----------------| | **Attach a CRDT-synced local-first shard** whose backend performs native conflict-free merge; respect CRDT semantics (no git merge), consume a replica/export, CRDT-log history (supplement) | **UC-64 (new)** | | **Attach a peer-to-peer / decentralized shard with no single canonical endpoint** (Anytype any-sync: replica or peer/backup node; E2EE) | **UC-65 (new)** | | Typed object graph / user-editable ontology + Notion-style DBs, local-first | **enriches UC-58** | | E2EE content opacity (Anytype) reinforced; self-host trust boundary | **enriches UC-61** | | CRDT update log ≠ portable git history → supplement | **enriches UC-36** | | One block set rendered as page / canvas / DB views (AFFiNE) | **enriches UC-47, UC-48** | | Edgeless canvas / board / objects = non-Markdown content | **enriches UC-55** | | Self-host sync server (AFFiNE/AppFlowy Cloud) + Anytype open API/MCP as endpoints | **enriches UC-57** | | Object/block IDs CRDT-assigned (fine-grained) | **enriches UC-51** | | Lossy Markdown export | links UC-59 | --- ## 9. Architecture notes for SHARD-WP-0002 (no UC) - **Merge-model capability** (`none / git-or-text / native-CRDT`) — proposed **thirteenth spectrum** (with Joplin's content-opacity twelfth). CRDT shards reject external merge; shard-wiki overlays must be CRDT-aware or remain projections. (T11.) - **Substrate taxonomy gains CRDT-replica**; **attach modes gain "local CRDT replica" and "P2P/no-central-endpoint"** beside file-store / in-engine-host / external-API. (T14.) - **Endpoint model** as a capability: single URL vs self-host server vs **P2P peer set** (Anytype) — affects how a binding is addressed and how freshness/sync work. (T14.) - **MCP / AI-agent protocol** as a possible shard integration surface (Anytype). Note for the extension-surface catalogue. (T14.) - These three plus Joplin and Logseq all argue the contract must treat **substrate as a spectrum that tools migrate along and that shard-wiki must not hard-code**. --- ## 10. Open questions (for spec / workplans) 1. For a **CRDT shard** (UC-64), does shard-wiki embed a CRDT client (Yjs/Yrs) to hold a live replica, or only consume periodic **exports/snapshots**? The former gives live/writable; the latter is simpler but lossy on merge timing. 2. How are **overlays** expressed against a CRDT shard — as CRDT ops (requires the client) or as out-of-band patches reconciled later (projection-only)? 3. For **P2P shards** (UC-65), what is the "address" of the shard — a space ID + a peer/ node, a local replica path, or an invite/key? How does this fit shard attachment config? 4. Does shard-wiki ever hold **E2EE keys** (Anytype) to project content, or only ever treat such shards as opaque replicas/backups (UC-61)? 5. Is the **self-host sync server** (AFFiNE/AppFlowy Cloud) attached as an external API (UC-57) or by running a co-located replica? --- ## 11. Sources | Source | Used for | |--------|----------| | Anytype any-sync — Protocol overview (https://tech.anytype.io/any-sync/overview) | Local-first/P2P/E2EE CRDT; sync/file/consensus/coordinator nodes; encrypted backup | | anyproto/any-sync (https://github.com/anyproto/any-sync) | Protocol scope; keys signed/verified; IPFS files | | Anytype Docs (https://doc.anytype.io/anytype-docs) | Spaces, object types + relations (ontology); open API + MCP | | toeverything/AFFiNE + DeepWiki (https://deepwiki.com/toeverything/AFFiNE) | BlockSuite (page/edgeless/DB); y-octo Yjs; OctoBase; one-data-many-views; self-host | | AFFiNE — interactive whiteboard / blog (https://affine.pro/blog/interactive-whiteboard-app) | Edgeless canvas; CRDT offline merge | | AppFlowy-IO/AppFlowy-Collab (https://github.com/AppFlowy-IO/AppFlowy-Collab) | Yrs CRDT; collab domain objects (documents/databases/folders); persistence | | AppFlowy Architecture Overview — DeepWiki (https://deepwiki.com/AppFlowy-IO/AppFlowy/2-architecture-overview) | Flutter/Rust layers; pluggable storage/sync (RocksDB/IndexedDB; Supabase/AppFlowy Cloud); local vs cloud trait | | AFFiNE vs AppFlowy vs Anytype (https://affine.pro/blog/affine-vs-appflowy-vs-anytype) | Cohort comparison framing | Cross-references: `research/260614-notion-deep-dive/findings.md` (typed DB, hosted contrast), `research/260614-joplin-deep-dive/findings.md` (E2EE/content opacity, sync- daemon boundary), `research/260614-shard-spectrum-synthesis/findings.md` (the spectra this extends), `spec/UseCaseCatalog.md` (UC-36, UC-47, UC-48, UC-51, UC-55, UC-57, UC-58, UC-61), `workplans/SHARD-WP-0002-federation-architecture.md` (T11, T14). --- ## 12. Traceability - New UCs: **UC-64, UC-65** → `spec/UseCaseCatalog.md`. - Enriched UCs: **UC-36, UC-47, UC-48, UC-51, UC-55, UC-57, UC-58, UC-61** (links UC-59). - Architecture (no UC): **merge-model** capability (proposed thirteenth spectrum); CRDT-replica substrate + P2P/no-central-endpoint attach mode; endpoint-model capability; MCP integration surface → `SHARD-WP-0002` (T11, T14). - Boundary recorded: Anytype/AFFiNE/AppFlowy are **CRDT local-first candidate shards** (attach a replica/projection as pages; respect native CRDT merge; never re-drive their sync; P2P/E2EE shards are replica-only/opaque) — not substrates, not the federation layer (INTENT not-a-sync-daemon, graceful degradation, no silent mutation).