YURT
YAK Unified Room Tags
Decentralized room discovery for YakApp chat rooms
v1.0.0The YURT Insight
Traditional chat apps require central servers to discover rooms. YURT provides three discovery modes that work independently:
-
1.
Direct Link — Click a yak:// link from any website. Works immediately, no gossip needed.
-
2.
Website Embed — "Join Chat" buttons on websites that link to yak:// or HTTPS gateway.
-
3.
Gossip — Browse rooms propagated through the mesh network.
The yak:// URI Scheme
YURT uses the yak:// URI scheme for direct room links.
Like clicking a Zoom link, but for decentralized chat.
Basic format: yak://host:port/bundleId
With invite attestation for private rooms
import { YurtLink } from 'yakmesh/mesh/yurt.js';
// Parse any yak:// link
const link = YurtLink.parse('yak://qrl-node.theqrl.org:8787/qrl-official');
console.log(link.host); // 'qrl-node.theqrl.org'
console.log(link.port); // 8787
console.log(link.bundleId); // 'qrl-official'
console.log(link.invite); // null (or attestation object if present)
// Create a yak:// link
const uri = YurtLink.create('my-node.example.com', 'my-room');
// → 'yak://my-node.example.com/my-room'
// Browser fallback (for browsers without yak:// handler)
const httpsUrl = YurtLink.toHttpsGateway(uri);
// → 'https://yak.to/join/my-node.example.com:8787/my-room'
Discovery Modes
Direct Link
The simplest path. User clicks a link, app connects directly to the host node. No gossip propagation required.
Website Embed
Websites embed join buttons. Works with yak:// for native apps or HTTPS gateway for browsers.
Gossip Propagation
Rooms are advertised through the mesh. Users can browse and search for public rooms.
QR Code
QR codes encode yak:// URIs. Scan to join rooms at events, conferences, or physical locations.
Room Entries
A YurtEntry represents a discoverable room listing. Entries are signed by the host node
and can be propagated via gossip or accessed directly.
import { YurtEntry, YURT_CONFIG } from 'yakmesh/mesh/yurt.js';
// Create a room entry
const entry = new YurtEntry({
bundleId: 'qrl-official',
hostNodeId: myNode.identity.nodeId,
hostEndpoint: 'qrl-node.theqrl.org:8787',
name: 'QRL Official',
description: 'Official Quantum Resistant Ledger community chat',
visibility: YURT_CONFIG.visibility.PUBLIC,
tags: ['qrl', 'crypto', 'quantum', 'official'],
memberCount: 500,
});
// Sign with host's secret key (proves ownership)
entry.sign(myNode.identity.secretKey);
// Generate shareable link
const link = entry.toUri();
// → 'yak://qrl-node.theqrl.org:8787/qrl-official'
// For invite-only rooms, include attestation
const inviteLink = entry.toInviteUri(attestation);
// → 'yak://...?invite=...'
Visibility Types
| Type | Badge | Gossip | Direct Link | Access |
|---|---|---|---|---|
| public | PUBLIC | ✓ Propagated | ✓ Works | Anyone can request to join |
| invite-only | INVITE | ✓ Propagated | ✓ Works | Requires GUMBA attestation |
| unlisted | UNLISTED | ✗ Not shared | ✓ Works | Only via direct link sharing |
Local Directory
The YurtDirectory maintains a local index of known rooms. It handles searching,
indexing by tags/host, and automatic cleanup of expired entries.
import { YurtDirectory } from 'yakmesh/mesh/yurt.js';
const directory = new YurtDirectory();
// Add entries (from gossip or manual)
directory.add(entry);
// Search rooms
const results = directory.search({
query: 'QRL',
tags: ['crypto'],
visibility: 'public',
limit: 20,
});
// Get by bundle ID
const room = directory.getByBundle('qrl-official');
// List all public rooms
const publicRooms = directory.listPublic(100);
// Get rooms by a specific host
const qrlRooms = directory.getByHost(qrlNodeId);
// Manual cleanup of expired entries
directory.cleanup();
Gossip Propagation
The YurtGossip module handles advertising rooms to the mesh network.
Entries expire after 7 days without refresh, preventing stale listings.
import { YurtGossip, YurtDirectory } from 'yakmesh/mesh/yurt.js';
const directory = new YurtDirectory();
const gossip = new YurtGossip(identity, directory, mesh);
// Start gossip (periodic announcements + refresh)
gossip.start();
// Announce a new room
gossip.announce(entry);
// Search the network
const queryId = gossip.query({ query: 'QRL', tags: ['crypto'] });
gossip.on('query:response', (response) => {
console.log('Found rooms:', response.entries);
});
// Withdraw a room from the network
gossip.withdraw('my-bundle-id');
// Stop gossip
gossip.stop();
Integration with GUMBA
YURT handles discovery. GUMBA handles access control. They work together seamlessly.
The Complete Flow
-
1
Discovery — User finds room via YURT (link, gossip, or embed)
-
2
Connect — App connects to host node at the endpoint
-
3
Challenge — Host issues GUMBA challenge to visitor
-
4
Proof — Visitor proves identity (challenge-response, attestation, or Merkle)
-
5
Session — Host grants session, messages delivered via ANNEX
YurtHub
YurtHub combines directory, gossip, and GUMBA integration into one convenient interface.
import { YurtHub } from 'yakmesh/mesh/yurt.js';
const hub = new YurtHub(identity, gumbaHub, mesh, options);
hub.start();
// Publish a room from your GUMBA hub
hub.publishRoom('my-bundle-id', {
name: 'My Awesome Room',
description: 'A great place to chat',
visibility: 'public',
tags: ['community', 'tech'],
});
// Browse public rooms
const rooms = hub.browse({ limit: 50 });
// Search by query
const results = hub.search('crypto', { tags: ['qrl'] });
// Join via direct link
const joinResult = await hub.joinViaLink('yak://example.com/room-id');
// Get a shareable link
const link = hub.getJoinLink('my-bundle-id');
// With invite for private rooms
const inviteLink = hub.getJoinLink('private-room', { invite: attestation });
Real-World Example: QRL Official
Setting Up the QRL Community Room
// On the QRL server (qrl-node.theqrl.org)
import { YurtHub, YurtEntry } from 'yakmesh/mesh/yurt.js';
import { GumbaHub } from 'yakmesh/mesh/gumba.js';
// Create the GUMBA bundle for the room
const gumbaHub = new GumbaHub(identity, annex);
const bundle = gumbaHub.createBundle('qrl-official', {
name: 'QRL Official',
description: 'Official Quantum Resistant Ledger community',
});
// Create the YURT hub and publish the room
const yurtHub = new YurtHub(identity, gumbaHub, mesh, {
endpoint: 'qrl-node.theqrl.org:8787',
});
yurtHub.start();
yurtHub.publishRoom('qrl-official', {
name: 'QRL Official',
description: 'Official Quantum Resistant Ledger community chat',
tags: ['qrl', 'crypto', 'quantum', 'official'],
visibility: 'public',
});
// Get the link to post on theqrl.org
const joinLink = yurtHub.getJoinLink('qrl-official');
console.log('Post this on the website:', joinLink);
// → yak://qrl-node.theqrl.org:8787/qrl-official
Now QRL can add a "Join Official Chat" button on their website that links directly to the room. Users with YakApp installed get a native experience. Browser users can use the HTTPS gateway.
Security Considerations
All entries are signed
Only the hosting node can create valid entries for its rooms. Signatures are verified before adding to directories.
Discovery ≠ Access
Finding a room in YURT doesn't grant access. GUMBA proofs are still required. YURT only handles visibility.
Spam dies naturally
Unsigned or invalid entries are rejected. Stale entries expire after 7 days. Nodes can filter by reputation.
Unlisted rooms are truly private
Rooms marked as "unlisted" never enter the gossip network. They only exist via direct link sharing.
Himalayan Protocol Family
YURT is part of the Himalayan Protocol Family for secure, decentralized communication: