Distributed Notes App
Build a local-first notes app that syncs across all your devices without a cloud server.
What you'll build
Vertical stack context: DOSFIUniversity (research) → DOSFI Academy (this course) → MeshNativeExchange (publishing & monetizing). Students progress from Learning → Building → Publishing → Monetizing. This course covers the construction of a distributed, distributed notes application built upon the DOSFI ecosystem. Participants will learn how to interface with DIUs, manage persistent state using the Vital storage subsystem, and orchestrate data propagation across a Mesh-Native environment. The course focuses on architectural determinism, requiring students to define Bundle Schemas for note objects and configure Routing Policies for local and remote node synchronization.
Skills you'll practice
- Implement a basic DIU interaction layer for state creation.
- Configure Vital storage for local and remote note persistence.
- Define and deploy a Bundle Schema for structured note data.
- Apply basic Routing Policies for Mesh-Native synchronization.
Before you start
- Foundational understanding of distributed systems
- Familiarity with CLI environments
- Basic knowledge of JSON-based configuration
- Active DOSFI local node installation
Lab steps5 steps
- 1Defining the Distributed Note Bundle Schema
In the DOSFI ecosystem, the bundle is the primary container for data transmission and persistence. When building a distributed notes application, you must treat every note as an immutable object encapsulated within a bundle. Unlike traditional CRUD applications that rely on central databases, a mesh-native app treats the note bundle as a self-contained unit of work that carries its own metadata, cryptographic provenance, and payload. The bundle schema is defined using a strictly typed protocol that the Transport Layer understands for efficient propagation across the mesh. Architecture: [Note Data] -> [Bundle Wrapper] -> [Transport Header] -> [Mesh Node]. To implement this, define your schema in JSON-LD. Example: { "type": "NoteBundle", "version": "1.0", "payload": { "content": "string", "author": "DID", "timestamp": "ISO8601" }, "signature": "signature_hash" }. Implementation: Use the DOSFI SDK to instantiate a new bundle constructor. Set your provenance headers to ensure that when the Transport Layer receives your note, it can route it based on locality or priority. Exercise: Create a script that initializes a bundle with a dummy note. Pitfalls: Forgetting to include the 'author' DID leads to orphan bundles that the Identity Fabric will reject during the verification phase. This lesson acts as the foundation for the next, where we configure how these bundles are routed across Vital storage.
- 2Configuring Vital Storage Routing
Vital is the distributed settlement and storage layer in DOSFI. It ensures that your note bundles are replicated across nodes that satisfy your latency and persistence requirements. Routing in Vital is policy-based, utilizing the Transport Layer to propagate bundles to nodes that hold enough DIU to guarantee storage duration. Diagram: [Bundle Source] -> [Vital Resolver] -> [Routing Policy Table] -> [Mesh Storage Nodes]. Configure your Vital storage policy using the DOSFI config interface. Example config: { "replication_factor": 3, "storage_class": "vital_permanent", "max_latency": "50ms" }. Implementation: Define the routing policy in your app's manifest file. Use the 'vital-cli' to announce your nodes' availability to the mesh. When the user saves a note, the Vital engine determines which nodes should hold the primary, secondary, and tertiary copies. Exercise: Setup a three-node local cluster and verify that a note bundle injected into node A appears on node B. Pitfalls: Setting an impossible replication factor for a small mesh will cause the bundle to hang in the Transport Layer's buffer. This lesson is critical because Vital provides the persistent state required for the sync mechanisms discussed in the third lesson.
- 3Implementing Mesh-Native Data Sync
Data sync in a mesh-native environment is not a request-response pattern but an event-driven broadcast model. We rely on the Transport Layer's ability to sync bundles between nodes asynchronously. When a note is updated, a new version of the bundle is propagated. The Identity Fabric ensures that only the authorized owner can append to the note chain. Logic: Node A (Write) -> Transport Layer (Propagate) -> Node B (Update Event). Implementation: Hook into the 'onBundleReceive' event in the DOSFI SDK. Pseudocode: function handleUpdate(bundle) { if (verifySignature(bundle)) { updateLocalStore(bundle); notifyUI(); } }. The sync engine uses gossip protocols to ensure all nodes eventually hold the latest bundle. Exercise: Simulate a network partition by disconnecting a node, updating a note, and reconnecting to observe the mesh self-healing. Pitfalls: Sync loops can occur if the versioning logic in the bundle metadata is not strictly monotonic. Always include a sequence number in your bundle headers. This provides the context for handling the conflicts we will discuss in lesson four.
- 4Handling Conflict Resolution and Versioning
In a distributed notes app, two users might edit the same note simultaneously, creating a divergent state. Mesh-native apps use Conflict-free Replicated Data Types (CRDTs) embedded within the bundle payload. The Vital layer ensures all nodes eventually reach consensus on the state of the note. Diagram: [Version 1] -> (Edit A + Edit B) -> [Vector Clock Conflict] -> [Merge Strategy] -> [Version 2]. Implementation: Use a Last-Write-Wins (LWW) or semantic merge strategy inside your application logic layer. Configure your bundle's metadata to include a 'parent_id' for tracking DAG (Directed Acyclic Graph) relationships. Example schema for conflict: { "parentId": "uuid-1", "operation": "merge", "delta": "text-diff" }. Exercise: Write a unit test that injects two conflicting bundles into a node and asserts the final merged state. Pitfalls: Misinterpreting the timestamp as a source of truth instead of the vector clock will cause lost updates. Relying on node-local time is a frequent anti-pattern. This knowledge of conflict handling is vital for managing the privacy and access tiers in our final lesson.
- 5Privacy Tiers and Mesh-Native Security
Security in DOSFI is governed by the Identity Fabric, which manages access control lists (ACLs) associated with each bundle. Privacy tiers allow you to categorize notes as public, encrypted for specific groups, or personal. Encrypted bundles are opaque to intermediate nodes in the Transport Layer, ensuring privacy. Diagram: [Note Content] -> [AES Encryption] -> [Bundle Encapsulation] -> [Mesh Transport] -> [Recipient Decryption]. Implementation: Assign a privacy policy to your note bundles at the point of creation. Use the Identity Fabric's public key infrastructure to sign and encrypt payloads. Example: { "acl": { "grant": ["did:key:123", "did:key:456"], "visibility": "private" } }. Exercise: Create a 'private' note and verify that nodes without the correct decryption key in the Identity Fabric cannot read the bundle payload. Pitfalls: Attempting to implement custom encryption instead of using the native DOSFI Identity Fabric tools often leads to vulnerabilities. Always use the built-in library for key rotation and management. This final lesson ties together the bundle, storage, and sync concepts to complete your fully functional Distributed Notes App.