Files
shard-wiki/research/260614-localfirst-workspaces-deep-dive/findings.md
tegwick 3e0c05a2b3 research: local-first workspaces cohort deep dive (Anytype/AFFiNE/AppFlowy) — CRDT substrate; UC-64/65
Combined cohort memo for the three open-source local-first all-in-one
workspaces, studied together because they share the trait none of the
prior eleven systems had: the store is a CRDT (Anytype any-sync, AFFiNE
Yjs/y-octo, AppFlowy Yrs). The cohort thesis: CRDT changes the adapter
math — the backend performs conflict-free merge itself (shard-wiki must
not impose git/text merge; speak the CRDT via a replica or stay
projection/overlay), history is a CRDT update log (supplement not git),
and the attach surface is a replica or self-host sync endpoint, with
Anytype adding P2P (no single endpoint) + E2EE (opaque). Added UC-64
(CRDT-synced shard with native merge), UC-65 (P2P/decentralized shard,
no single canonical endpoint); enriched UC-36/47/48/51/55/57/58/61.
Catalog now 65 UCs. Architecture for SHARD-WP-0002 T11/T14: merge-model
capability (proposed 13th spectrum: none/git/native-CRDT), CRDT-replica
substrate + P2P/no-central-endpoint attach mode, endpoint-model
capability, MCP as an integration surface. Boundary: CRDT local-first
candidate shards — attach a replica/projection as pages, respect native
merge, never re-drive their sync; not substrates and not the federation
layer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 16:21:08 +02:00

16 KiB
Raw Blame History

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-65spec/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).