Skip to content

crs48/xNet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2,521 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

xNet

CI npm: @xnetjs/react Electron App Demo App Hub Image Demo Hub Docs GitHub Stars License: MIT TypeScript pnpm Turborepo PRs Welcome

Decentralized data infrastructure and application. Local-first, P2P-synced, user-owned data.

xNet is both the underlying infrastructure and the user-facing app — one product, one brand. It starts with documents and databases, then expands via plugins to support ERP, MCP integrations, and more.

This repository is one implementation of xNet. xNet is also an open protocol you can re-implement in any language, over any database, and interoperate. See docs/specs/protocol/ (normative spec), conformance/ (golden vectors + a second-language kernel), and xnet.fyi/docs/protocol.

Try It Now

Try the demo at xnet.fyi/app — no signup required, just use your device's passkey (Touch ID, Face ID, Windows Hello).

Demo mode: Your data is stored locally in your browser (local-first). Encrypted backups sync to our demo hub with a 10MB quota and expire after 24 hours of inactivity. For reliable cross-device sync and permanent backups, download the desktop app.

Deploy a Hub

Deploy on Railway

Getting Started

# Install dependencies
pnpm install

# Run the root Storybook catalog and workbenches
pnpm dev:stories

# Build the static Storybook site
pnpm build:stories

# Build all packages
pnpm build

# Run unit tests (~2400 tests across 148 test files)
pnpm test

# Run integration tests (real browser via Playwright)
pnpm --filter @xnetjs/integration-tests test

# Type check
pnpm typecheck

# Lint
pnpm lint

Component Development

xNet now ships a root Storybook workspace for isolated component development across shared UI and app-facing surfaces.

  • Run pnpm dev:stories from the repo root to launch Storybook on http://127.0.0.1:6006.
  • Use pnpm build:stories to produce the static catalog and pnpm test:stories to run Storybook tests against a running server.
  • In Electron dev builds, open the embedded Storybook surface from Open Stories in the system menu or command palette.
  • In Web dev builds, open the embedded route at /stories.

Current Storybook coverage includes:

  • @xnetjs/ui primitives, composed components, comments, settings, and devtools catalogs
  • @xnetjs/editor rich collaborative editor workbench
  • @xnetjs/views database surface workbench
  • @xnetjs/canvas canvas workbench
  • selected Electron and Web renderer stories

Monorepo Structure

packages/           # 21 core SDK packages (@xnetjs/*)
apps/               # Electron, Web, Expo applications
site/               # Astro + Starlight documentation website
tests/              # Browser-based integration tests (Playwright)
docs/               # Vision, explorations, implementation plans

See the README in each directory for details:

Packages

Foundation

Package Description
@xnetjs/core Types, content addressing (CIDs), permissions, RBAC
@xnetjs/crypto BLAKE3 hashing, Ed25519 signing, XChaCha20 encryption
@xnetjs/identity DID:key generation, UCAN tokens, passkey storage

Infrastructure

Package Description
@xnetjs/storage SQLite/memory adapters, blob store, chunk manager, snapshots
@xnetjs/sync Change<T>, Lamport clocks, hash chains, Yjs security layer
@xnetjs/data Schema system, NodeStore, 15 property types, Yjs CRDT, built-in schemas
@xnetjs/network libp2p node, y-webrtc provider, peer scoring, security suite
@xnetjs/query Local query engine, MiniSearch full-text search, federated router
@xnetjs/hub Signaling server, sync relay, backup, FTS5 search, sharding, federation

Application

Package Description
@xnetjs/react useQuery, useMutate, useNode, hub hooks, plugin hooks, sync infrastructure
@xnetjs/sdk Unified client, browser/node presets, re-exports
@xnetjs/editor TipTap collaborative editor, slash commands, wikilinks, drag-drop, mermaid
@xnetjs/ui Radix UI primitives, composed components, theme system, design tokens
@xnetjs/views Table, Board, Gallery, Timeline, Calendar views with property renderers
@xnetjs/canvas Infinite canvas, R-tree spatial indexing, ELK.js auto-layout, Yjs-backed store
@xnetjs/devtools 9-panel debug suite (node explorer, sync monitor, Yjs inspector, ...)
@xnetjs/history Time machine, undo/redo, audit trails, blame, diff, verification
@xnetjs/plugins Plugin registry, sandboxed scripts, AI generation, MCP server, webhooks
@xnetjs/telemetry Privacy-preserving telemetry, tiered consent, k-anonymity, scrubbing
@xnetjs/formula Expression parser, AST evaluator, built-in function library
@xnetjs/vectors HNSW vector index, semantic search, hybrid keyword+semantic search

Apps

App Tech Description
Electron Electron + Vite + React + TanStack Router + Tailwind Desktop (macOS/Windows/Linux)
Web Vite + React + TanStack Router + Workbox PWA Browser progressive web app
Expo Expo SDK 52 + React Native + React Navigation Mobile (iOS/Android)

Architecture

flowchart TB
    subgraph Apps["Applications"]
        Electron["Electron<br/>(Desktop)"]
        Web["Web PWA"]
        Expo["Expo<br/>(Mobile)"]
    end

    subgraph UI["UI Layer"]
        Editor["@xnetjs/editor<br/><small>TipTap, slash commands,<br/>drag-drop, mermaid</small>"]
        Views["@xnetjs/views<br/><small>Table, Board, Calendar,<br/>Timeline, Gallery</small>"]
        Canvas["@xnetjs/canvas<br/><small>Infinite canvas,<br/>R-tree, ELK.js</small>"]
        UILib["@xnetjs/ui<br/><small>Radix primitives,<br/>theme system</small>"]
    end

    subgraph Client["Client Layer"]
        React["@xnetjs/react<br/><small>useQuery, useMutate,<br/>useNode, SyncManager</small>"]
        SDK["@xnetjs/sdk<br/><small>Unified client,<br/>browser/node presets</small>"]
        Devtools["@xnetjs/devtools<br/><small>9-panel debug suite</small>"]
        Plugins["@xnetjs/plugins<br/><small>Registry, sandbox,<br/>AI generation, MCP</small>"]
        Telemetry["@xnetjs/telemetry<br/><small>Privacy-first,<br/>consent-gated</small>"]
        History["@xnetjs/history<br/><small>Time machine,<br/>undo/redo, audit</small>"]
    end

    subgraph Data["Data Layer"]
        DataPkg["@xnetjs/data<br/><small>Schema system, NodeStore,<br/>Yjs CRDT, 15 property types</small>"]
        Query["@xnetjs/query<br/><small>Local engine,<br/>MiniSearch FTS</small>"]
        Vectors["@xnetjs/vectors<br/><small>HNSW index,<br/>hybrid search</small>"]
        Formula["@xnetjs/formula<br/><small>Expression parser,<br/>computed properties</small>"]
    end

    subgraph Infra["Infrastructure Layer"]
        Sync["@xnetjs/sync<br/><small>Change&lt;T&gt;, Lamport clocks,<br/>hash chains, Yjs security</small>"]
        Storage["@xnetjs/storage<br/><small>SQLite, blobs,<br/>snapshots</small>"]
        Network["@xnetjs/network<br/><small>libp2p, y-webrtc,<br/>peer scoring</small>"]
    end

    subgraph Foundation["Foundation"]
        Identity["@xnetjs/identity<br/><small>DID:key, UCAN tokens,<br/>passkey storage</small>"]
        Crypto["@xnetjs/crypto<br/><small>BLAKE3, Ed25519,<br/>XChaCha20</small>"]
        Core["@xnetjs/core<br/><small>CIDs, types,<br/>permissions, RBAC</small>"]
    end

    Apps --> UI & Client
    UI --> Client
    Client --> Data
    Data --> Infra
    Infra --> Foundation

    subgraph Server["Server"]
        Hub["@xnetjs/hub<br/><small>Signaling, sync relay,<br/>backup, FTS5, federation</small>"]
    end

    Network <--> Hub
Loading

Hybrid Sync Model

flowchart LR
    subgraph Local["Local Device"]
        UI["UI"]
        NodeStore["NodeStore<br/>(structured data)"]
        YDoc["Y.Doc<br/>(rich text)"]
        DB[("SQLite")]
    end

    subgraph Remote["Remote Peers"]
        Peer1["Peer<br/>(desktop)"]
        Peer2["Peer<br/>(mobile)"]
        HubNode["Hub<br/>(always-on)"]
    end

    UI -->|"mutate()"| NodeStore
    UI -->|"edit"| YDoc
    NodeStore -->|"Change&lt;T&gt;<br/>LWW"| DB
    YDoc -->|"Yjs updates<br/>CRDT"| DB

    Local <-->|"WebRTC / WebSocket"| Remote
Loading

Data Model

Everything is a Node (universal container). A Schema defines what the Node is.

import { defineSchema, text, number, select } from '@xnetjs/data'

const InvoiceSchema = defineSchema({
  name: 'Invoice',
  namespace: 'xnet://myapp/',
  document: 'yjs',
  properties: {
    title: text({ required: true }),
    amount: number(),
    status: select({
      options: [
        { id: 'draft', name: 'Draft' },
        { id: 'sent', name: 'Sent' },
        { id: 'paid', name: 'Paid' }
      ] as const
    })
  }
})

Sync Strategies

Data Type Sync Mechanism Conflict Resolution
Rich text (documents) Yjs CRDT Character-level merge
Structured data (nodes) NodeStore + Lamport Field-level LWW

Identity, Roles, and Authorization

xNet schemas can include an authorization block that maps identity (DID) to roles and actions.

  • Identity: Every node has createdBy: did:key:...
  • Roles: Resolved from creator, person properties, or related nodes
  • Actions: Canonical actions are read, write, delete, share, admin
  • Delegation: Grants (UCAN-backed) allow secure permission delegation
const ProjectDocSchema = defineSchema({
  name: 'ProjectDoc',
  namespace: 'xnet://myapp/',
  document: 'yjs',
  properties: {
    title: text({ required: true }),
    owner: person(),
    editors: person(),
    project: relation({ schema: 'xnet://myapp/Project@1.0.0' })
  },
  authorization: {
    roles: {
      owner: role.creator(),
      editor: role.property('editors'),
      projectAdmin: role.relation('project', 'admin')
    },
    actions: {
      read: allow('owner', 'editor', 'projectAdmin'),
      write: allow('owner', 'editor', 'projectAdmin'),
      delete: allow('owner', 'projectAdmin'),
      share: allow('owner', 'projectAdmin'),
      admin: allow('projectAdmin')
    },
    publicProps: ['title']
  }
})

Authorization builders (allow, role, etc.) come from the data auth module and compile to schema-level policy metadata.

Primary React Hooks

import { useQuery, useMutate, useNode, useIdentity, useCan, useGrants } from '@xnetjs/react'

// Structured data
function TaskList() {
  const { data: tasks, loading } = useQuery(TaskSchema)
  const { create, update, remove } = useMutate()

  return (
    <ul>
      {tasks.map((task) => (
        <li key={task.id}>{task.title}</li>
      ))}
      <button onClick={() => create(TaskSchema, { title: 'New', status: 'todo' })}>Add</button>
    </ul>
  )
}

// Rich text with Yjs CRDT
function PageEditor({ nodeId }: { nodeId: string }) {
  const { data: page, doc, syncStatus, peerCount } = useNode(PageSchema, nodeId)
  if (!doc) return null
  return <RichTextEditor ydoc={doc} />
}

// Identity + permissions
function SharingPanel({ nodeId }: { nodeId: string }) {
  const { did } = useIdentity()
  const { allowed: canShare } = useCan(nodeId, 'share')
  const { grant } = useGrants(nodeId)

  return (
    <button
      disabled={!canShare}
      onClick={() =>
        canShare && grant({ to: 'did:key:z6MkRecipient...', actions: ['read', 'write'] })
      }
    >
      Share as {did.slice(0, 16)}...
    </button>
  )
}

Hook Quick Reference

Hook Use for
useQuery Read lists/single nodes with realtime updates
useMutate Create/update/delete/transactional writes
useNode Rich text nodes (Y.Doc), sync status, presence
useIdentity Current DID identity context
useCan Check action permissions on a node
useCanEdit Quick editable state for UI gating
useGrants Grant, revoke, and inspect delegated access

Key Technologies

Layer Technology
Sync Event-sourced immutable logs, Lamport clocks, LWW
CRDT Yjs (conflict-free collaboration)
P2P libp2p + WebRTC
Storage SQLite (OPFS in browser, native on desktop/mobile)
Identity DID:key + UCAN authorization
Signing Ed25519 (via @noble/curves)
Hashing BLAKE3 (via @noble/hashes)
Encryption XChaCha20-Poly1305
Search MiniSearch (local), FTS5 (hub)
Build Turborepo, tsup, Vite
Testing Vitest, Playwright (browser mode)

Roadmap Status (Mar 2026)

Phase Focus Status
Phase 1 Product reliability (navigation, search, daily-driver polish) In progress
Phase 2 Collaboration + trust (invites, sharing UX, presence reliability) Next
Phase 3 Platform clarity (package lifecycle, API simplification, multi-hub integration) Planned

See docs/ROADMAP.md for the detailed execution plan.

Documentation

  • Site -- Astro + Starlight documentation website
  • Protocol Spec -- the normative, re-implementable standard (L0–L3 + conformance corpus)
  • Vision -- The big picture: micro-to-macro data sovereignty
  • Tradeoffs -- Why hybrid sync (Yjs + event sourcing)
  • Roadmap -- current 6-month execution plan (Mar-Sep 2026)

License

MIT

About

Local-first infrastructure and app for user-owned data: offline-first sync, CRDT collaboration, typed schemas, and secure identity/permissions

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

 
 
 

Contributors