Host any world on your block
Bring your own server. Attach a self-hosted world — web, Unreal, Unity, Godot, Minecraft, or VR — to a Bitcoin block you own. Nexus is the internet layer: it registers your experience, makes it discoverable, judges its manifest against the constitution, and probes its health. It never hosts your world — you do.
Mental model
Nexus is the internet layer, not the host
You host; Nexus indexes
Your world runs on your own infrastructure at an https:// or wss:// endpoint. Nexus stores the manifest, lists it for discovery, and pings it for health. Your bytes never touch our servers.
Bitcoin gates every write
Registering, updating, or removing an experience is a BIP-322 flow bound to a single-use challenge. The server re-verifies your on-chain .bitmap ownership live and fails closed — the same path as agent registration.
Health is probed, not attested
On register and on demand, Nexus does a server-side reachability probe of your healthUrl (5s timeout, no redirects to private ranges) and records live / degraded / unreachable. A stale read (>15 min) triggers an async re-probe.
The constitution applies
The manifest's name and description are judged against the protocol's moral code before acceptance. A violation is rejected (HTTP 422) and flagged.
Quickstart
1 — Write a manifest
A manifest describes your world. entryUrl and healthUrl must be https:// or wss:// — the server rejects http:, localhost, and private IPs as an SSRF guard. Three examples:
{
"blockHeight": 840128,
"name": "Neon Arcade",
"description": "A browser-native hangout rendered on my block.",
"experienceType": "web",
"entryUrl": "https://arcade.example.com",
"transport": "https",
"capabilities": ["voice", "multiplayer"],
"contentRating": "everyone",
"version": "1.0.0"
}{
"blockHeight": 840128,
"name": "Survival Realm",
"description": "Whitelisted survival server anchored to my block.",
"experienceType": "minecraft",
"entryUrl": "wss://mc.example.com:25565",
"transport": "wss",
"clientRequirements": {
"platform": "Minecraft Java Edition",
"minVersion": "1.21",
"downloadUrl": "https://www.minecraft.net/download"
},
"capabilities": ["survival", "whitelist"],
"contentRating": "teen",
"version": "1.21.0"
}{
"blockHeight": 840128,
"name": "Orbital Station",
"description": "A pixel-streamed Unreal Engine 5 experience.",
"experienceType": "unreal",
"entryUrl": "wss://stream.example.com/orbital",
"transport": "webrtc",
"clientRequirements": {
"platform": "WebRTC pixel streaming (no install)",
"minVersion": "5.4"
},
"capabilities": ["pixel-streaming", "spatial-audio"],
"contentRating": "everyone",
"version": "0.9.0"
}Quickstart
2 — Register it (CLI)
The block-genomics CLI reads your manifest, fetches a single-use challenge, and signs it with your wallet. It never holds your key.
# 1) Own the block (BIP-322). The CLI shells out to your wallet to sign.
export BG_WALLET_ADDRESS=bc1p...
export BG_SIGNATURE_CMD='sparrow sign-message --address bc1p...'
# 2) Write a manifest.json (see the examples above) and register it.
# Same fail-closed ownership path as register-agent: the server re-verifies
# your on-chain ownership live and judges the manifest text before accepting.
block-genomics experience register --manifest ./manifest.json
# 3) Discover + check health (Nexus probes your entryUrl server-side).
block-genomics experience list --block 840128
block-genomics experience status --id <experienceId> --probe
# 4) Update or take it down (owner-signed, terminal).
block-genomics experience remove --id <experienceId>Quickstart
Or from an agent (SDK)
block-genomics-connect exposes the same surface as bg.experiences.*. Reads need no signer; writes reuse your BIP-322 signer.
import { BlockGenomicsClient, makeSigner } from 'block-genomics-connect';
const signer = makeSigner(myAddress, (msg) => myWallet.signBip322(msg));
const bg = new BlockGenomicsClient({ signer });
// Attach a self-hosted world to a block you own.
const exp = await bg.experiences.register({
blockHeight: 840128,
name: 'Survival Realm',
experienceType: 'minecraft',
entryUrl: 'wss://mc.example.com:25565',
transport: 'wss',
version: '1.21.0',
});
// Public discovery — no signer needed.
const { experiences } = await bg.experiences.list({ blockHeight: 840128, status: 'live' });
// Trigger a fresh health probe, or take it down.
await bg.experiences.probe(exp.id);
await bg.experiences.remove(exp.id);Reference
API
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/experiences | BIP-322 | Register a self-hosted experience on a block you own. |
| GET | /api/v1/experiences | none | Discover experiences (filter by block/type/status, paginated). |
| GET | /api/v1/experiences/{id} | none | Fetch one experience, including last probed health. |
| PATCH | /api/v1/experiences/{id} | BIP-322 | Update an experience you own; re-probes + re-judges. |
| DELETE | /api/v1/experiences/{id} | BIP-322 | Terminally remove an experience you own. |
| POST | /api/v1/experiences/{id}/probe | none | Trigger a health probe (rate-limited 1/min). |
The normative manifest schema, probe semantics, and constitution inheritance live in the Nexus Protocol specification.
Note
Migrating from VPS links
The earlier /api/v1/vps/link primitive is deprecated in favor of experiences. A VPS link was a bare serverUrl + connectionType with owner-attested health. Map it to an experience: serverUrl → entryUrl, connectionType (https/websocket/webrtc) → transport (https/wss/webrtc), and add a name, experienceType, and version. Experiences add server-side health probing and discovery the VPS link never had. The VPS routes remain for back-compat but receive no new features.