Build on hostnought
The swarm is the machine. Apps are folds.
hostnought is a platform for apps with no application server. A static bundle boots browser peers into a self-repairing storage-and-compute swarm. You write event schemas, fold rules, and a UI; the swarm handles durability, replication, repair, sync, search, and verified compute.
This page is the whole developer story: why you'd build here, how to build your first app in ten minutes, what the API actually is, and what's genuinely possible — plus the constraints that make some ideas a bad fit.
Why build here
Be skeptical of platform pitches. Here is the honest one: a $5 VPS beats this on every axis except the ones that kill projects.
- Your app has no hosting bill and no ops. There is no database to run out of disk, no server to patch, no bill to lapse. Deployment is uploading a file.
- Your users' data outlives you. If you stop maintaining the app, the community keeps its archive — it lives in their browsers, erasure-coded and self-repairing. Nobody has to trust you to keep paying.
- You cannot be deplatformed from your own users. No API key to revoke, no app store, no account to suspend. The bytes are already on their machines.
- Verifiable by construction. Every event is signed and content-addressed; every compute result is checked by independent redundant execution. Your users don't have to take your word for anything.
- You get infrastructure most solo projects can't afford: durable erasure-coded storage that survives 60% hourly peer churn (chaos-tested), full-text search with no search server, end-to-end encrypted messaging, and a verified compute layer — all as SDK calls.
The niche, stated plainly: survival, not performance. Build here when the data matters longer than the funding, when the community should own its own archive, or when there is no infrastructure to depend on.
Install the CLI
curl -fsSL https://hostnought.com/install.sh | sh
The installer verifies the download's SHA-256 against the published manifest before extracting; read it first if you like (curl https://hostnought.com/install.sh). The CLI is standalone — it ships its own runtime, so you never need the platform repo:
hostnought new fieldnotes && cd fieldnotes
hostnought dev # a real local swarm (isolated playground) with your app
hostnought check # the validator swarms enforce, before you can ship
hostnought build # shippable bundle + content hash
Your first app in ten minutes
An app is id + schemas + folds + (optionally) a React view. That's it.
// guestbook.app.js — a complete, shippable hostnought app.
export default function register({ sdk, React }) {
const { registerApp, createEvent, submitEvent, dag, useDagVersion } = sdk;
const h = React.createElement;
function Main({ identity }) {
useDagVersion(); // re-render on new events
const entries = dag.getState('guestbook', 'entries') ?? [];
const sign = async (text) =>
submitEvent(createEvent(
{ app: 'guestbook', type: 'entry', scope: 'main', ts: Date.now(), body: text },
identity.privkey,
));
return h('div', { className: 'apppage' },
h('button', { onClick: () => sign('hello swarm') }, 'Sign'),
...entries.map((e, i) => h('div', { key: i }, e.text)),
);
}
registerApp({
id: 'guestbook',
icon: '✎',
title: 'Guestbook',
schemas: { entry: {} },
folds: [{
app: 'guestbook', name: 'entries', version: 1,
init: () => [],
step: (state, e) =>
e.type === 'entry' && typeof e.body === 'string'
? [...state, { who: e.author, text: e.body, ts: e.ts }]
: state, // ignore anything else — see law 2
}],
views: { Main },
});
}
Then:
hostnought check guestbook.app.js # validate + bench locally (no network)
hostnought build guestbook.app.js # bundle + content hash to hand a founder
Swarm founders ratify it (swarm apps add) and deploy; from then on every verified client loads it — no platform release involved.
The full working version ships in examples/guestbook.app.js. Poke at a live one in the Workbench tab of the app, and break things safely in the playground (/app?swarm=sandbox — isolated storage, throwaway identity).
The mental model
Everything is an event. A signed, content-addressed, immutable record: { id, app, type, author, scope, ts, body, sig }. Users emit events; the swarm floods, batches, erasure-codes, and repairs them forever.
All state is a fold. Your app's state is a pure function over the event log — init() plus a step(state, event) reducer. Every peer replays the same events in the same total order and gets the same state. There is no database, no migration, no write conflict: state is derived, always.
Two laws. The devkit enforces both before anything ships:
- Folds must be pure and deterministic. Same events, any arrival order → same state. No
Date.now(), no randomness, no network inside a fold. - Folds must tolerate junk. Anyone can emit any body under your app id. A fold that throws on unexpected input is a remote crash button. Check your types and ignore what doesn't fit.
Storage-neutral carriage. Peers store and repair your app's data even if they never load your app. You inherit the swarm's durability for free.
SDK reference
Everything an app may touch, and nothing else (src/sdk/index.ts — the boundary is enforced by a test).
Registration
| Export | What it does |
|---|---|
registerApp(def) | Register schemas, folds, views, jobs, hooks. The only entry point. |
getApp(id) / listApps() / registeredApps() | Reflection; getApp(x).views is the sanctioned way to mount another app's UI. |
subscribeApps(fn) | Fires when apps register (external apps land after first paint). |
AppDef: { id, title?, icon?, schemas, folds, jobs?, onSeal?, scatterResponders?, rpc?, views? }
Events & state
| Export | What it does |
|---|---|
createEvent(draft, privkey) | Sign an event. draft = { app, type, scope, ts, body, parent? }. |
submitEvent(event) | Insert locally + gossip to the swarm. |
dag.getState(app, name) | Current fold state. |
dag.getEvent(id) / dag.eventIds() / dag.size | Read the log. |
effectiveAuthor(event) | Collapse device subkeys to one account identity. |
useDagVersion() | React hook: re-render on any DAG change. |
Swarm & status
| Export | What it does |
|---|---|
swarmStatus() / subscribeSwarm(fn) / useSwarmStatus() | Role, room, peers, segments, fragments, anchor/compute flags, repair metrics. |
setAnchorMode(bool) / setComputeMode(bool) | The user's volunteering toggles (both opt-in). |
kvGet(key) / kvPut(key, value) | Small durable per-browser key/value store. |
stage1Init() | Boot provenance — verified stage-0 boot vs. dev entry. |
EPOCH_MS | The protocol's 10-minute epoch. |
Compute & queries (the advanced half)
| Export | What it does |
|---|---|
runCompute(wasm, input) | Run a WASM job on the swarm; resolves with the hash-majority-verified result. See JOBS.md. |
postJob(post) | Fire-and-forget job post (used by onSeal hooks). |
scatterQuery(app, payload, opts) | Fan a query out to peers; each answers via its scatterResponders. Powers search. |
segmentHolderTargets(ids) | Which peers hold given segments — target a scatter instead of broadcasting. |
callRpc(app, payload) | Call your app's leader-side rpc handler from any tab. |
App capabilities (fields on AppDef)
jobs— content-addressed compute modules your app can run.onSeal(header)— runs on the leader when a batch seals; the hook that turns new data into compute work (search uses it to post index jobs).scatterResponders— answer other peers' scatter queries.rpc— leader-side handlers callable from any tab (follower tabs proxy).views— React components;Mainputs your app in the app switcher.
What you can build
Things that are uniquely good here, not just possible:
- Community archives that outlive their maintainer — fan wikis, local history, mutual-aid directories, zine libraries. The archive lives as long as anyone cares, not as long as someone pays.
- Package/artifact registries — signed, content-addressed, undeletable. No more left-pad.
- Field tools for absent infrastructure — disaster response, remote research, anywhere the network is intermittent and there's no server to reach. Peers sync when they meet.
- Group messaging and private coordination — the swarm stores ciphertext it provably cannot read.
- Verifiable computation over shared data — indexes, aggregates, reports where users need to check the result rather than trust a server.
- Collaborative documents — folds are conflict-free by construction (total order + pure reducers), so no CRDT library is needed for last-writer-wins semantics.
What NOT to build here
Being straight with you saves your weekend:
- Anything needing secrets on the server. There is no server. Any key your app holds is on the user's machine.
- Latency-critical serving. Compute is verified by 3× redundant execution; that's fine for batch, ruinous for request/response.
- Private-by-default data. The event log is public by design. Privacy means encrypting before you emit (see the DM app).
- Anything requiring deletion. The log is append-only. Moderation hides; purge certificates drop payloads by community quorum; neither is
DELETE. - Big binary blobs. Peers carry your data in their browsers. Be a good guest.
Constraints worth knowing up front
- Fresh data isn't searchable instantly — indexing happens when a batch seals.
- Folds run on every peer's main thread. The devkit benches yours; keep them cheap.
- Compute is opt-in. If nobody volunteers, jobs don't run.
- Your app's code is trust-critical. External apps are ratified by the swarm's founder council, exactly like the platform itself — they run with full origin powers.
- Full measured capacity map: LIMITS.md.
Reference
- JOBS.md — compute jobs: ABI, compiling, safety model.
- The paper — the design, the threat model, and the measured results, in full (PDF).
examples/guestbook.app.js— complete external app.examples/jobs/sum-bytes.wat— complete compute job.- CLI —
curl -fsSL https://hostnought.com/install.sh | sh; runhostnoughtfor the command list. - Workbench tab (in the app) — live registry, fold inspector, event composer.
- Playground —
/app?swarm=sandbox, isolated world for breaking things.