Pre-release — Help us build this

Three hooks.
Zero backend.

Build local-first apps with React and TypeScript. Your data lives on the device, syncs peer-to-peer, and works offline. No servers to deploy. No auth to configure. No vendor to depend on.

$ pnpm add @xnet/react @xnet/data

Building apps shouldn't require a PhD in infrastructure

A "simple" collaborative app today
  • 1. Choose a database (Postgres? Mongo? Firestore?)
  • 2. Build an API layer (REST? GraphQL? tRPC?)
  • 3. Set up authentication (OAuth? Passkeys? Magic links?)
  • 4. Add real-time sync (WebSockets? SSE? Polling?)
  • 5. Deploy and host (AWS? Vercel? Railway?)
  • 6. Add offline support (...good luck)

Six decisions before you write a single line of product code.

The same app with xNet
// That's it. Really.
import { useQuery, useMutate }
  from '@xnet/react'
const { data } = useQuery(TaskSchema)
const { create } = useMutate()
// Data persists locally (IndexedDB)
// Syncs P2P automatically (WebRTC)
// Works offline by default
// Cryptographic identity built in
// Type-safe from your schema

Two packages. Zero infrastructure decisions.

The entire API: three hooks

useQuery reads. useMutate writes. useNode syncs. Everything else — storage, crypto, networking — is handled for you.

1

useQuery

Read any data with full TypeScript inference. Queries are reactive — your UI updates automatically when data changes. Filter, sort, and paginate, all type-checked against your schema.

Data is local, so reads are instant. No loading spinners for local data — it's already there.

Replaces: React Query + REST/GraphQL client + Database queries
TaskList.tsx
import { useQuery } from '@xnet/react'

function TaskList() {
  // Fully typed — schema defines the shape
  const { data: tasks } = useQuery(TaskSchema, {
    where: { status: 'active' },
    orderBy: { createdAt: 'desc' },
    limit: 20
  })

  // No loading state for local data
  // Auto-updates when peers sync changes
  return (
    <ul>
      {tasks.map(t =>
        <li key={t.id}>{t.title}</li>
      )}
    </ul>
  )
}
2

useMutate

Create, update, and delete nodes with compile-time type safety. Invalid property names and wrong value types are caught before your code runs.

Mutations apply locally first, then sync to all connected peers. Works offline — changes queue and merge when connectivity returns.

Replaces: API routes + ORM mutations + Optimistic updates
TaskActions.tsx
import { useMutate } from '@xnet/react'

function TaskActions() {
  const { create, update, remove } = useMutate()

  // Schema-validated at compile time
  const add = () => create(TaskSchema, {
    title: 'Ship the landing page',
    status: 'active'
  })

  // Syncs to all peers automatically
  const done = (id: string) =>
    update(TaskSchema, id, {
      status: 'done'
    })

  // Works offline — queued until reconnect
  const del = (id: string) => remove(id)
}
3

useNode

Load a single node with its Yjs document for real-time collaborative editing. Plug the Y.Doc into TipTap, ProseMirror, or any Yjs-compatible editor.

Character-level conflict resolution via CRDTs. See who else is editing with presence awareness. Every change is Ed25519-signed and verified.

Replaces: WebSocket server + Operational transforms + Presence service
PageEditor.tsx
import { useNode } from '@xnet/react'

function PageEditor({ pageId }) {
  const {
    data: page,    // Typed node data
    doc,           // Yjs Y.Doc
    peerCount,     // Connected collaborators
    syncStatus,    // 'connected' | 'offline'
    update         // Type-safe mutations
  } = useNode(PageSchema, pageId)

  return (
    <div>
      <h1>{page?.title}</h1>
      <span>{peerCount} peers online</span>
      <TipTapEditor doc={doc} />
    </div>
  )
}

A fundamentally simpler architecture

Stop managing infrastructure. Start building products.

Traditional Architecture
React App
API Layer
Auth
Database
Cache
WS Server
CDN
Queue
Hosting
6+ services 3+ vendors Monthly bills No offline
xNet Architecture
React App
@xnet/react hooks
Local Store
P2P Sync
That's the whole stack
2 packages 0 vendors $0/month Offline-first

What you can build

xNet gives you the data primitives. You decide what to make.

Collaborative Document Editor

Rich text with Yjs CRDTs. Character-level merging. Real-time cursors. Like Notion, but data never leaves your devices.

const { doc } = useNode(PageSchema, id)
// Plug into TipTap, ProseMirror, etc.
<Editor doc={doc} />

Local-First Database

15 property types, relations, views, filters. Like Airtable, with real-time P2P sync and offline support.

const schema = defineSchema({
  name: 'Contact',
  properties: {
    name: text({ required: true }),
    email: text({ format: 'email' }),
    company: relation({ target: CompanySchema }),
  }
})

Personal Knowledge Garden

Infinite canvas, linked notes, backlinks. Like Obsidian with structured data and cross-device sync.

const { data: notes } = useQuery(NoteSchema, {
  where: { linkedTo: currentNoteId },
  orderBy: { updatedAt: 'desc' }
})

Team Workspace

Schemas, views, and real-time collaboration. Like Linear, with P2P sync and no monthly per-seat fees.

const { data: tasks } = useQuery(TaskSchema, {
  where: { assignee: myDid, status: 'active' },
  orderBy: { priority: 'desc' }
})

AI-Augmented Tools

AI agents read/write via MCP protocol. Same type-safe API. Same schemas. AI as a collaborative peer.

// AI connects via MCP server
// Same typed operations as React hooks
await mcp.create(TaskSchema, {
  title: ai.suggestedTitle,
  status: 'review'
})

Media-Rich Apps

Content-addressed blob storage with BLAKE3 hashes. Upload images, files, and attachments — auto-compressed, deduplicated, and P2P synced between devices.

import { useImageUpload } from '@xnet/editor'

const upload = useImageUpload()
// Auto-compresses, generates CID
const ref = await upload(file)
// { cid: 'cid:blake3:a1b2...', name, size }
// Syncs to peers via blob-sync protocol

TypeScript all the way down

Define schemas in TypeScript. Get full inference everywhere — queries, mutations, hooks. No codegen step.

schema.ts
import {
  defineSchema, text, select,
  number, relation, richText
} from '@xnet/data'

export const RecipeSchema = defineSchema({
  name: 'Recipe',
  namespace: 'xnet://did:key:z6Mk/',
  properties: {
    title: text({ required: true }),
    difficulty: select({
      options: ['easy', 'medium', 'hard']
    }),
    prepTime: number({ min: 0 }),
    ingredients: relation({
      target: IngredientSchema,
      many: true
    }),
    body: richText(),
  }
})

Full Type Inference

Schema definitions generate TypeScript types automatically. Invalid property names and wrong value types are caught at compile time. No codegen step needed.

15 Property Types

Text, number, boolean, select, multi-select, date, URL, email, phone, relation, rich text, files, checkbox, color, and formula. Everything you need for real applications.

AI-Friendly Architecture

Pure TypeScript with strong types means excellent autocomplete in Cursor, Copilot, and Claude. AI agents can generate schemas, queries, and even plugins with high accuracy.

Built-in File & Image Handling

Upload files and images with content-addressed BLAKE3 storage. Automatic image compression, chunking for large files, and P2P sync between devices. All deduplicated by content hash.

One Language, Every Platform

TypeScript across client, data layer, sync engine, and plugins. Desktop (Electron), mobile (Expo), and web (PWA) share the same codebase and types.

Under the hood

Production-tested primitives across 17 packages. Every layer designed for local-first.

Sync

  • Yjs CRDTs for rich text
  • Lamport LWW for structured data
  • WebRTC peer-to-peer connections
  • Ed25519-signed envelopes

Crypto

  • BLAKE3 content hashing
  • Ed25519 signatures
  • XChaCha20-Poly1305 encryption
  • All browser-native

Identity

  • DID:key self-sovereign IDs
  • UCAN delegatable tokens
  • No central auth server
  • Portable across apps

Storage

  • IndexedDB on web
  • SQLite on desktop/mobile
  • Content-addressed blob storage
  • P2P file sync with BLAKE3 CIDs
  • Event-sourced history
Desktop

Electron — macOS, Linux, Windows

Mobile

Expo — iOS, Android

Web

PWA — any modern browser

Better for the planet

Every byte that crosses a network costs energy. Local-first keeps data where it's used — and eliminates most of the waste.

1M x
less energy per read
Local SSD vs cloud round-trip
99.9%
less data transferred
CRDT deltas vs REST re-fetching
$0
egress cost per GB
vs $0.05–$0.12/GB cloud egress
Zero
wasted poll requests
60–90% of cloud polls return nothing

Data centers consume ~460 TWh/year — 1.3% of global electricity. If just 10% of SaaS went local-first, we'd save the equivalent of Portugal's annual electricity consumption. — IEA 2024, Aslan et al. 2017, Andrae & Edler 2015

Extend everything

A four-layer plugin system inspired by VS Code, Figma, and Obsidian. The simplest plugin is one file. An AI can generate one in seconds.

1

Scripts

Single-file, AI-generatable. Think "formulas for your data pipeline." Run anywhere.

Web, Desktop, Mobile
2

Extensions

Multi-file packages with custom views, editors, and schemas. The building blocks of apps.

Web, Desktop, Mobile
3

Services

Background processes with full Node.js access. Heavy computation, custom protocols.

Desktop
4

Integrations

External connections via webhooks, MCP, and automation tools like N8N.

All platforms
word-count-plugin.ts
import { definePlugin } from '@xnet/sdk'

export default definePlugin({
  name: 'word-count',
  setup(ctx) {
    ctx.registerView({
      name: 'Word Count',
      component: () => {
        const { doc } = ctx.useCurrentNode()
        const words = doc?.getText()?.length ?? 0
        return <span>{words} words</span>
      }
    })
  }
})

A productivity app you can hack on

xNet ships with a full productivity platform — documents, databases, canvas, and tasks. It's free, self-hostable, and open source. But it's also the best way to start developing on xNet.

A real testing ground

Every feature in xNet is battle-tested here first. The app is the proving ground for the SDK — if it works for a full productivity suite, it works for your app.

The easiest way to contribute

Want to build on xNet? Start with a plugin. Or submit a PR to improve the editor, add a database view, or build a new canvas tool. It's all TypeScript, all open.

Documents

Rich text editor with TipTap and Yjs. Real-time collaboration, slash commands, block-based editing. Character-level conflict resolution.

Databases

15 property types, relations, views (table, board, gallery, calendar, timeline). Filter, sort, group — all reactive, all local-first.

Canvas

Infinite canvas with spatial indexing. Drag nodes, draw connections, embed documents. Think Miro meets Obsidian Canvas.

Tasks

Schema-first task management with status, priority, assignees, due dates. Kanban boards, list views, and calendar views.

Desktop

Electron — full features, plugins, background services

Web

PWA — works in any browser, installable

Mobile

Expo — iOS and Android (coming soon)

Free forever. Self-hostable. Every feature is open source and will stay that way.

Hubs: your infrastructure, your rules

xNet works fully P2P with zero infrastructure. When you want always-on sync, backups, and team access — deploy on Railway in one click or self-host on a $5/month VPS.

Desktop
Peer A
Phone
Peer B
Browser
Peer C
P2P when online Hub when offline
Hub
Railway or $5/month VPS — Docker, SQLite, single process
Sync relay Backups Auth Search Blobs
The Hub never sees your plaintext data. It relays encrypted updates and stores ciphertext. Optional — everything works without it.

Always-on sync relay

Peers sync directly when both are online. When one goes offline, the Hub holds updates and delivers them later. No data lost.

Encrypted backups

Your data is encrypted before it leaves your device. The Hub stores ciphertext it can't read. Restore to any device, anytime.

Authorization gateway

UCAN-based permissions enforced at the relay. Fine-grained access control — read, write, admin — without a central auth service.

Web UI

Your Hub can serve the xNet web app directly. One URL gives your team access to everything — documents, databases, canvas — from any browser.

Schema registry

Publish and discover schemas across your team or community. The Hub indexes available types so apps can find and use them.

Blob storage

Content-addressed file storage with BLAKE3 hashing. Images, attachments, exports — synced P2P between peers, with the Hub as an always-available fallback. Automatic deduplication by content hash.

Full-text search

Server-side FTS5 search index for your workspace. Find documents, tasks, and notes by content. Queries run locally first, with Hub results filling in the gaps.

terminal
# Deploy on Railway (recommended)
# https://railway.app/template/xnet-hub

# Or self-host with Docker
$ docker run -d -p 4444:4444 \
    -v xnet-data:/data \
    ghcr.io/crs48/xnet-hub:latest

# Point your app at wss://your-hub:4444

Deploy on Railway or Docker. Read the Hub setup guide.

The local-first landscape

We're building xNet because we believe in a future where users own their data. We're not alone — here are the projects pushing this vision forward. We encourage you to explore them all.

Developer Frameworks & Data Tools

What you'd use to build a local-first app today. Each has different tradeoffs.

Project Local-firstOfflineSyncConflict ResolutionRich TextSchemaReact HooksType SafetySelf-HostedLicenseIdentityPluginsPlatforms
xNet Yes Full P2P (WebRTC) Yjs + Lamport LWW Yjs + TipTap TypeScript defineSchema() useQuery / useMutate / useNode Full inference No server needed MIT DID:key + UCAN 4-layer system Electron + Web + Expo
Zero Yes Full Server (sync engine) Server rebase Postgres useQuery Via Postgres types Server required Apache 2.0 External Web
Triplit Yes Full Server (WebSocket) LWW per-attribute TypeScript useQuery Full inference Server required AGPL External Web + Mobile
ElectricSQL Yes Full Server (Postgres CDC) Server rebase Postgres useShape Via Postgres types Server required Apache 2.0 External Web
Jazz Yes Full P2P via relay Automerge-based CoValues (TypeScript) useCoState Full inference Relay optional MIT Built-in Web + React Native
LiveStore Yes Full Client-side events Event-sourced SQLite useStore Full inference Client-only MIT External Web
DXOS Yes Full P2P (MESH) Automerge (ECHO) Automerge TypeScript (ECHO) useQuery Full inference P2P optional MIT Built-in (HALO) Yes Web + Electron
Convex No Partial Server (reactive) Server authority TypeScript useQuery Full inference Cloud only Proprietary** External Web

** Convex runtime is proprietary; client SDKs are open source. All other projects are fully open source.

Protocols & P2P Infrastructure

The broader ecosystem of decentralized data. Different scopes, different goals — all pushing toward user-owned data.

Project ScopeData ModelSyncIdentityLanguageStatusBest For
xNet App frameworkSchema-typed nodes + YjsP2P (WebRTC)DID:key + UCANTypeScriptPre-releaseFull-stack local-first apps
AT Protocol Social protocolSigned repos (Lexicons)Federated relayDID:plcTypeScriptProduction (30M+ users)Social networking
Nostr Event protocolSigned JSON eventsRelay (WebSocket)secp256k1 keysAnyProductionSocial + payments
Hypercore / Pear P2P runtimeAppend-only logsP2P (DHT)Public keysJavaScriptProductionP2P apps + streaming
Iroh Networking libraryContent-addressed blobsP2P (QUIC)Public keysRustProductionP2P networking layer
p2panda P2P toolkitDAG of CBOR operationsP2P (QUIC / iroh)Public keysRustActive (v0.5)Encrypted group apps
Willow Sync protocol3D namespace modelProtocol-agnosticCapabilities (Meadowcap)Spec + JS/RustActiveFine-grained sync + access
Holochain Agent frameworkAgent chains + DHTDHT gossipAgent keysRust (WASM)Beta (7+ years)Agent-centric apps
Anytype App + protocolTyped objects + DAGsP2P (custom)Key pairsGo + TypeScriptProduction (1M+ users)Personal knowledge base
Solid Data podsRDF / Linked DataServer (REST)WebIDAnyActive (niche)Academic / government

Productivity Apps

How xNet's built-in app compares to the tools you might already use. Different philosophies — from cloud-first SaaS to local-first open source.

App Local-firstOfflineReal-time CollabRich TextDatabasesCanvasOpen SourceSelf-HostedPluginsPricingData OwnershipPlatforms
xNet App Yes Full P2P (Yjs) TipTap + Yjs 15 property types, views Infinite, spatial index MIT Full (Hub optional) 4-layer system Free forever Full — encrypted, local Desktop, Web, Mobile
Notion No Partial (cache) Server (OT) Block-based Full (views, relations) No No No Integrations API Freemium ($8+/mo) Cloud only Desktop, Web, Mobile
Obsidian Yes Full Paid plugin Markdown Via plugins Yes No (free for personal) Files on disk Community plugins Free / $50/yr sync Full — local files Desktop, Mobile
Anytype Yes Full P2P Block-based Relations + views Yes Source-available Self-hosted nodes No Free (paid tiers coming) Full — encrypted, P2P Desktop, Web, Mobile
Linear No Partial (cache) Server Minimal Issue tracker No No No Integrations Free / $8+/mo Cloud only Desktop, Web, Mobile
Coda No No Server Block-based Tables + formulas No No No Packs (marketplace) Freemium ($10+/mo) Cloud only Web, Mobile
Airtable No No Server Rich field type Full (views, automations) Interfaces No No Extensions + scripts Freemium ($20+/mo) Cloud only Web, Mobile
AppFlowy Yes Full Cloud sync Block-based Grid, board, calendar No AGPL Full Flutter plugins Free / cloud plans Full — local + optional cloud Desktop, Web, Mobile
AFFiNE Yes Full Yjs (cloud) BlockSuite Table views Edgeless mode MIT Full Plugin system Free / cloud plans Full — local + optional cloud Desktop, Web, Mobile

Where xNet fits

xNet combines TypeScript-inferred schemas, a dual CRDT strategy (Yjs for rich text + Lamport LWW for structured data), React hooks, a four-layer plugin system, and true P2P sync — all in one framework.

Building a React app and want local-first with minimal boilerplate? Start here.

Need a social protocol? Check out AT Protocol or Nostr.

Need low-level P2P networking? Check out Iroh or Hypercore.

Want a production knowledge base today? Check out Anytype.

Where this is going

From local-first primitives to the decentralized data layer of the internet. Each layer builds on the last.

Built

The Foundation

Core primitives for local-first apps

  • Crypto identity (DID:key, Ed25519, UCAN)
  • Schema system with 15 property types
  • P2P sync engine (Yjs + Lamport clocks)
  • Rich text editor, infinite canvas, devtools
  • Electron app with real-time collaboration
  • 350+ tests across 17 packages
Now

Daily Driver

Make xNet an app you actually use every day

  • Personal wiki & task manager
  • Query API improvements
  • Polished desktop experience
  • Plugin system & custom views
Next

Hubs & Multiplayer

Always-on sync nodes and shared workspaces

  • Hub MVP — backup, relay, search
  • Workspace invites & permissions
  • Presence & live cursors
  • Mobile app (Expo)
Then

Federation

Hubs talk to each other. Data flows freely.

  • Hub-to-hub federation protocol
  • Federated queries across hubs
  • Schema registry & discovery
  • ERP framework & domain modules
Vision

The Decentralized Data Layer

A global namespace for structured knowledge

  • Global namespace — xnet://*
  • Decentralized search engine
  • Social federation (follows, feeds, reputation)
  • Domain-specific networks (farming, science, education)
  • Data commons — humanity's shared knowledge graph
Every app built on xNet makes the network stronger

This is early. That's the point.

xNet is pre-release software. The APIs will change. There are rough edges. But the foundation is solid — and your contributions will shape what it becomes.

What's working now

~350 tests passing across 17 packages
Electron app with full P2P sync
Schema system with 15 property types
Real-time collaboration via Yjs
Cryptographic identity (DID:key + Ed25519)
Rich text editor with TipTap
Infinite canvas with spatial indexing
7-panel devtools suite

We're looking for developers who want to

Shape the API before it's set in stone — your feedback directly impacts the design
Build plugins for an extensible ecosystem — custom views, schemas, and integrations
Contribute to core — sync engine, query system, canvas, editor, devtools
Build apps on xNet and push the boundaries of local-first software

Start building in 60 seconds

Open source. MIT licensed. TypeScript all the way.

1 Install the packages
terminal
$ pnpm add @xnet/react @xnet/data
2 Define a schema
schema.ts
import { defineSchema, text, select } from '@xnet/data'

export const TaskSchema = defineSchema({
  name: 'Task',
  namespace: 'xnet://your-did/',
  properties: {
    title: text({ required: true }),
    status: select({
      options: ['todo', 'doing', 'done']
    })
  }
})
3 Use it in your components
App.tsx
import { useQuery, useMutate } from '@xnet/react'
import { TaskSchema } from './schema'

function App() {
  const { data: tasks } = useQuery(TaskSchema)
  const { create } = useMutate()

  return (
    <div>
      <button onClick={() => create(TaskSchema, {
        title: 'New task',
        status: 'todo'
      })}>Add</button>
      {tasks.map(t => <li key={t.id}>{t.title}</li>)}
    </div>
  )
}
// That's it. Sync, storage, crypto — all handled.

Or clone the full monorepo to explore the Electron app, canvas, editor, and devtools:

terminal
$ git clone https://github.com/crs48/xNet.git && cd xNet && pnpm install && pnpm dev

Requires Node.js 22+ and pnpm.