Build an app
Building a .vibe app
A .vibe app is a single JSON manifest that bundles your metadata and inline HTML. It needs no hosting and runs as a native-feeling window inside VibeOS.
Anatomy of a manifest
Everything lives in one JSON object. The html field holds a complete HTML document — your markup, CSS and JavaScript — that VibeOS renders inside a sandboxed window. Here's a complete, valid example:
{
"vibe": 1,
"name": "Markdown Notes",
"iconEmoji": "📝",
"iconBg": "linear-gradient(135deg,#10b981,#0ea5e9)",
"iconImage": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg…",
"description": "A fast, distraction-free markdown notepad that saves to your Home directory.",
"version": "1.0.0",
"author": "Jane Developer",
"genre": "productivity",
"width": 900,
"height": 640,
"closeBehavior": "close",
"fileExtensions": ["md", "markdown"],
"permissions": {
"read": ["home"],
"write": ["home"],
"ai": true,
"network": ["https://api.openlibrary.org/", "https://covers.openlibrary.org/"]
},
"screenshots": [
{ "url": "https://example.com/shot1.png", "caption": "Editing a note" }
],
"html": "<!doctype html><html><head><meta charset=\"utf-8\"><style>body{font-family:system-ui;margin:0;padding:24px;background:#0f172a;color:#e2e8f0}</style></head><body><h1>My Notes</h1><textarea style=\"width:100%;height:80vh\"></textarea></body></html>"
}One file, no external runtime
html field (single HTML string with embedded CSS/JS). System capabilities such as the filesystem and AI are reached exclusively through the window.vos SDK.Field reference
Fields marked with * are required. Anything else is optional and falls back to a sensible default.
| Field | Type | Description |
|---|---|---|
| vibe* | 1 | Format version. Always the literal number 1. |
| name* | string | Display name, 2–60 characters. |
| iconEmoji* | string | An emoji used as the app icon. |
| iconBg* | string | Background behind the icon — any CSS color or gradient, e.g. linear-gradient(135deg,#10b981,#0ea5e9). |
| iconImage | string | App icon embedded as a base64 data URI, e.g. data:image/png;base64,…. Overrides iconEmoji when present. Must be a data URI — external URLs are ignored; the host then falls back to iconEmoji over iconBg. Use a small square PNG or WebP (64–128px, under ~3 MB encoded). |
| description* | string | What the app does, 10–2000 characters. Shown on the listing. |
| html* | string | The full inline HTML document that renders inside the app window. |
| version | string | Semver, e.g. 1.0.0. Defaults to 1.0.0. |
| width | number | Initial window width in px (240–3840). Default 900. |
| height | number | Initial window height in px (180–2160). Default 640. |
| closeBehavior | "close" | "minimize" | What happens when the user closes the window. |
| fileExtensions | string[] | Extensions this app can open, e.g. ["md"]. Enables double-click to open. |
| author | string | Developer or studio name. |
| genre | string | Category slug used to place the app in the catalog. |
| screenshots | { url, caption? }[] | Up to 8 screenshots shown on the app listing. |
| appCenterId | string | Stable identifier linking updates to an existing App Center listing. |
| permissions | { read?: string[]; write?: string[]; ai?: boolean; network?: string[] } | Filesystem, AI, and network capabilities. See the section below. |
Permissions
Filesystem permissions
The filesystem is directory-scoped: your app declares the Home-relative directories it wants to read and/or write. The host re-checks every filesystem call against the installed grant, so an app can never widen its own scope at runtime.
{
"permissions": {
"read": ["home/Documents", "home/Pictures"],
"write": ["home/Documents"]
}
}Declaring capabilities
read / write (even an empty array []) declares the filesystem capability. An empty array means sandbox-only access at home/.apps/<appId>/. The user is prompted to approve the requested directories at install time, and re-prompted on upgrades that widen the scope.AI permissions
The ai flag gates access to the AI gateway. Set it to true to enable AI chat and other model-powered features through window.vos.ai. The host rejects every AI call when this flag is missing or false.
{
"permissions": {
"ai": true
}
}AI access requires the ai permission
To use the AI gateway (window.vos.ai.chat), set "ai": true inside permissions. AI requests run through VibeOS, so no API keys are required — see the SDK reference.
App metadata (window.vos.app.getInfo) is the only capability that needs no permission — it's available to every app with no declaration and no install-time prompt.
Network permissions
By default a .vibe app has no network access — the host injects a strict connect-src CSP and the browser blocks every outbound request. To call an external API, list its https:// origin (with an optional path prefix) in permissions.network. Each entry covers the origin and any URL beginning with that prefix.
{
"permissions": {
"network": [
"https://api.openlibrary.org/",
"https://covers.openlibrary.org/"
]
}
}https://api.example.com— the entire origin.https://api.example.com/v1/— origin plus path prefix.- Only
https://is allowed. Up to 32 entries.
Use window.vos.net.fetch for requests
Direct fetch() still hits CORS for most APIs. Use window.vos.net.fetch(url, init) — it routes through the VibeOS host, re-validates the URL against this list, and returns { status, headers, body | bodyBase64 }. See the SDK reference.
Users approve the requested origins at install time and can revoke individual entries from Web Apps → app details → Permissions after install.
The HTML runtime
Inside the window your document runs as a normal web page, with a few VibeOS specifics:
- The document is sandboxed — it can't reach other apps or the host desktop directly.
- System capabilities (Home filesystem, AI chat, app info) are reached through the global
window.vosSDK object — wait for thevos-readyevent, then see the SDK reference. - Use the window
width/heightas a design target, but make your layout responsive — users can resize.
Next steps
When your manifest is ready, paste it into the submit form as a draft, then follow the submission & review process.