CubiCube Platform
Real-time sync for local-first applications
Kraken provides WebSocket-based real-time sync for Yjs documents. Each app gets isolated namespaces for data separation.
Before connecting, your app must be registered with Kraken (contact admin or use the API):
POST /api/apps
Authorization: Bearer YOUR_ADMIN_TOKEN
Content-Type: application/json
{
"app_id": "my-app",
"name": "My Application",
"allowed_origins": ["https://my-app.example.com"],
"owner_email": "dev@example.com"
}
const ws = new WebSocket(
'wss://kraken.helixpods.ai/doc/my-document?token=YOUR_TOKEN'
);
Kraken uses a two-layer security model:
A shared secret that proves your app is authorized to use Kraken. Pass it as:
?token=YOUR_TOKENAuthorization: Bearer YOUR_TOKENYour app's origin (domain) determines which namespace your rooms belong to.
This is automatic - Kraken reads the Origin header from WebSocket connections.
Each registered app gets isolated data:
| Your Request | Internal Room ID |
|---|---|
/doc/readme from app-a.example.com |
app-a:readme |
/doc/readme from app-b.example.com |
app-b:readme |
Health check endpoint. No authentication required.
curl https://kraken.helixpods.ai/health
WebSocket endpoint for Yjs sync. Requires authentication.
wss://kraken.helixpods.ai/doc/my-room?token=TOKEN
List registered apps. Admin authentication required.
Register a new app. Admin authentication required.
{
"app_id": "string (required)",
"name": "string (required)",
"allowed_origins": ["array of strings (required)"],
"description": "string (optional)",
"owner_email": "string (optional)"
}
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
const doc = new Y.Doc();
const provider = new WebsocketProvider(
'wss://kraken.helixpods.ai',
'my-document',
doc,
{ params: { token: 'YOUR_TOKEN' } }
);
provider.on('status', ({ status }) => {
console.log('Connection status:', status);
});
// Use your Yjs document
const text = doc.getText('content');
text.insert(0, 'Hello, collaborative world!');
import * as Y from 'yjs';
import * as syncProtocol from 'y-protocols/sync';
import * as encoding from 'lib0/encoding';
import * as decoding from 'lib0/decoding';
const doc = new Y.Doc();
const ws = new WebSocket('wss://kraken.helixpods.ai/doc/my-room?token=YOUR_TOKEN');
ws.binaryType = 'arraybuffer';
ws.onopen = () => {
// Send sync step 1
const encoder = encoding.createEncoder();
encoding.writeVarUint(encoder, 0); // message type: sync
syncProtocol.writeSyncStep1(encoder, doc);
ws.send(encoding.toUint8Array(encoder));
};
ws.onmessage = (event) => {
const decoder = decoding.createDecoder(new Uint8Array(event.data));
const messageType = decoding.readVarUint(decoder);
// Handle sync messages...
};
import { useEffect, useState } from 'react';
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
function useYjsDocument(roomName: string) {
const [doc] = useState(() => new Y.Doc());
const [connected, setConnected] = useState(false);
useEffect(() => {
const provider = new WebsocketProvider(
'wss://kraken.helixpods.ai',
roomName,
doc,
{ params: { token: process.env.KRAKEN_TOKEN } }
);
provider.on('status', ({ status }) => {
setConnected(status === 'connected');
});
return () => provider.destroy();
}, [roomName, doc]);
return { doc, connected };
}
Use @nexartis/kraken-sdk (packages/sdk) for SvelteKit and Svelte 5 applications requiring real-time document sync.
| Code | Meaning | Solution |
|---|---|---|
| 401 | Unauthorized | Check your token |
| 403 | Forbidden | Origin not registered |
| 426 | Upgrade Required | Use WebSocket, not HTTP |