Introduction
What a custom app is and how it runs inside HUB.KI.
A custom app is a single, self-contained HTML document that HUB.KI embeds in a sandboxed iframe. Your app talks to the platform through a small message bridge — enough to store data, know the current user, react to their theme and language, publish and receive events, run AI agents, and share content.
Apps are ordinary web pages. Bring any framework, or none.
How it works
The platform serves your artifact into a sandboxed iframe and exchanges
JSON-RPC 2.0 messages with it over
postMessage. The @hub-ki/app-sdk package
wraps that exchange in plain async functions. Through the bridge your app can:
- read and write its own private workspace (per user)
- keep app state in a key/value store (per user, per version)
- read the signed-in user's identity and the shared workspace documents (with permission)
- get an access token to call HUB.KI APIs from its own backend (with permission)
- publish and receive events in real time, and run AI agents (with permission)
- show toasts, set the tab title, and open a share dialog
See the SDK reference for the full client API.
Everything a custom app can do is gated by the scopes it declares, so the platform — and the user's organization — stays in control.
Anatomy
An app is a folder with two required files:
my-app/
├── manifest.json # metadata, scopes, versioning
└── app.html # the single-file artifactOptionally add an icon image (icon.svg, icon.png, …) referenced from the
manifest.
Constraints
- Single file. The iframe loads exactly one HTML document of at most 10 MB. Inline all CSS and JavaScript — external URLs resolved relative to the artifact will not load.
- Sandboxed. The app runs with
allow-scripts allow-formsand no same-origin access, so cookies andlocalStorageare unavailable. Persist state through the app's key/value store (thelocalStoragereplacement) or the workspace. - Locked-down content policy. See below — it decides what may be inlined.
- SDK major version 1. Declare
sdkVersionin the manifest; the host currently supports major version1.
Content Security Policy
The platform serves every app with this policy:
default-src 'none';
script-src 'unsafe-inline';
style-src 'unsafe-inline';
img-src data: blob:;
worker-src blob:;
connect-src 'none';
base-uri 'none';
form-action 'none';
sandbox allow-scripts allow-formsWhat that means in practice:
| You want to… | Works? |
|---|---|
Inline <script> and <style> | Yes. Scripts and styles loaded from a URL do not. |
| Show images | Only as data: or blob: URLs. Inline SVG markup also works. |
| Use a web font | No — fonts are not allowed from any source, including data: URLs. Use system fonts or draw glyphs as SVG. |
| Play audio or video | No — media is not allowed from any source. |
Call eval / new Function | No. Bundlers and libraries that rely on it fail at runtime. |
| Run WebAssembly | Only with the capability:wasm scope, which adds 'wasm-unsafe-eval'. |
| Start a Web Worker | Yes, from a blob: URL. |
Submit a <form> | No navigation — handle submit in JavaScript and call preventDefault(). |
fetch your backend | Only origins declared in connectOrigins and approved by the organization admin. |
Ready to build one? Start with the Quick start.