Builder Guide: Designing and Building Apps
Preview Feature
This Preview feature is still being developed. We do not recommend using it in a production environment, because the feature might not be fully tested or optimized for performance, and related documentation could be incomplete.
Please continue to submit feedback through normal Cribl support channels, but assistance might be limited while the feature remains in Preview.
Use this guide to design, build, and ship Apps on the App Platform (Preview). It covers how Apps run, how they store state, how they call APIs, and how you package and deploy them. It assumes you’ve completed the Quickstart and are ready to go deeper.
See the Cribl Apps GitHub repository for public example Apps.
App Structure
Before you start building, decide how much your App needs to do. Start small. A single-screen App that solves one problem well is more useful than a sprawling App that tries to do everything. You can always add views later.
Single-screen Apps: Use these for a focused dashboard, a simple form-driven workflow (for example, look up a value, trigger an action), or a single API interaction behind a purpose-built UI.
Multi-step Apps: Use these when you need to guide users through a sequential workflow, combine data from multiple Cribl APIs or external services, or maintain complex state across multiple views.
Runtime Model and Sandbox
Apps run as embedded web applications inside an isolated iframe in the Cribl UI. Treat your App as an API client running in a constrained browser environment. For a security-review-oriented summary of execution boundaries, credentials, and outbound traffic, see Runtime, architecture, and security.
- The Cribl shell owns global navigation and chrome.
- Your App runs in the iframe as a standalone Single Page Application (SPA).
- All reads and writes go through the documented Cribl APIs.
- Persistent App state lives in the App Platform (Preview) KV store.
Iframe Sandbox Constraints
Because your App runs in an isolated iframe, certain standard browser capabilities are restricted to ensure security and Cribl UI stability.
| Capability | Available? | Platform Alternative |
|---|---|---|
fetch() to Cribl APIs | ✅ | Handled seamlessly by the Cribl fetch proxy. |
localStorage / sessionStorage | ❌ | Not available in the sandbox. Use the KV store API. |
IndexedDB | ❌ | Not available in the sandbox. Use the KV store API. |
| Cookies | ❌ | Not needed, auth is proxied automatically. |
| File downloads | ✅ | <a download>, Blob URLs. |
| Popups / new tabs | ✅ | window.open(), <a target="_blank">. |
| Canvas with same-origin images | ❌ | Fetch images through the proxy. |
The AI-First Developer Workflow
The fastest way to build on the App Platform (Preview) is using AI coding assistants (like Cursor, GitHub Copilot, or Claude). The App Platform (Preview) provides explicit guardrails to help your AI write App Platform-compliant code, preventing it from hallucinating APIs or breaking sandbox constraints.
Expectations for Agent-Assisted Development
Agent-assisted (or “vibe-coded”) development is not the same as writing every line yourself. Assistants optimize for common web patterns and can still propose changes that break App Platform rules, even when AGENTS.md is in the project. Plan to iterate: a first green build or successful preview is a checkpoint, not necessarily done.
Typical missteps to watch for include:
- Using
localStorage,sessionStorage,IndexedDB, or cookies instead of the KV store. - Calling Cribl URLs or HTTP methods that are not in the bundled OpenAPI specification, or inventing request shapes the proxy cannot satisfy.
- Omitting an external hostname from
proxies.yml, or adding headers in App code that Cribl strips (useheaders.injectfor secrets instead). - Refactoring UI or fetch code in a way that drops iframe-safe patterns that already worked in an older revision.
When output is wrong, tighten your guidance. Paste console or network errors. Say what you clicked or loaded. Quote the relevant bullets from AGENTS.md or this guide so the tool realigns to documented behavior.
For prompting habits that reduce thrash, see Further Reading on Prompting and AI-Assisted Delivery.
1. Create and Scaffold
Create App and Live Preview require a Workspace Administrator. See Roles, permissions, and governance in the Admin Guide.
First, define the App in the Cribl UI to generate your scaffold script. The metadata step stores values in the App manifest and shows them in the Apps inventory (for example, ID, Display name, Version, and Author).
- App ID - Stable folder name and deep-link segment (
/apps/a/<app-id>/...). Prefer a short slug (letters, digits, hyphens). Keep it fixed once others bookmark links or automation depends on the path. - Display Name - Human-readable title in the Apps list. Plain language is fine. It does not need to match the App ID.
- Description - What the App does so admins and users can judge fit when browsing installed Apps.
- Author - Person, team, or company that builds or maintains the App.
- Version - Initial semantic version in
package.json.npm run packagebumps it when you ship (see Package, version, and deploy). - Minimum Cribl version - Earliest Cribl release you wrote and tested against so admins can judge compatibility.
- In the Cribl UI, go to Apps > Create App from the top bar.
- On the Create your App screen, describe what you want to build, then select Next.
- Enter App ID, Display Name, Description, Author, Version, and Minimum Cribl version, then select Next.
- On the scaffold step, open a terminal in your IDE and set the working directory to match your IDE project folder. Select Using Cursor, Using Claude, or Generic, then select Copy Script. Paste the
curlcommand into the terminal and run it. - Leave the Create App wizard open in the browser through Live Preview. For the full sequence, see the Quickstart.
2. Initialize Your AI Assistant
The scaffolded project includes a critical file: AGENTS.md.
Before you start iterative AI-assisted coding, ensure your AI assistant reads this file. It covers authentication, documented APIs, and the KV store. It also covers iframe and sandbox rules plus other platform constraints. AGENTS.md documents the UI stack your scaffold ships with. Ground your AI with AGENTS.md so it uses the KV store instead of localStorage, writes every API key and secret to KV with encrypted=true, and follows the rest of that guidance.
3. Develop With Live Preview
Iterate on your code locally while previewing it live inside the Cribl UI context. For Live Preview, use Chrome, Edge, or Firefox. See Browser Support.
The preview iframe loads your dev server from your machine (typically loopback). Browsers can block that path from an HTTPS Cribl tab until the user allows local network or local device access for the Cribl origin. If Live Preview is blank, confirm those permissions in the browser (and on macOS, under System Settings > Privacy & Security > Local Network for the browser). See Browser Permissions for Live Preview in the Quickstart.
- Start your local dev server by running
npm run devin your project directory. - In the Cribl UI, on the Create App wizard step that shows the scaffold instructions, select Live Preview. The preview pane opens in that flow.
- The App loads in an iframe inside Cribl and hot-reloads instantly as you or your AI assistant make code changes.
Live Preview binds your local dev server to the Cribl UI session where you opened it. After you switch Workspaces, Organizations, or move between a local deployment and Cribl.Cloud, stop the server (Ctrl+C in the terminal). Run npm run dev again before the next Live Preview. If you skip that restart, the App can fail to initialize in the iframe.
4. Package, Version, and Deploy
When you are ready to distribute your App, do not manually tar or zip directories. Use the provided build tooling. The version line you set at create time seeds package.json and the packaged manifest. For metadata you enter at create time, see Create and Scaffold.
- Run
npm run packagein your terminal. - This compiles your App, auto-increments the patch version in
package.json, and produces a valid.tgzarchive. (You can override the version bump usingnpm run package -- --minor,npm run package -- --major, ornpm run package -- --version x.y.zfor an explicit semantic version.) - Share this
.tgzfile. A Cribl administrator can install it by navigating to Apps > Installed Apps > Add App > Import from File. For the full install flow, see Install an App in the Admin Guide. For promoting builds across dev, staging, and production Workspaces and using Git for releases, see Development and release workflow for customer Apps in the Admin Guide.
Alternatively, from Live Preview in the Create App wizard you can select Deploy to package and upload in one step. See Step 6: Deploy in the Quickstart. Deploy installs into the Workspace where you started Create App. Use import into other Workspaces when you follow a multi-environment workflow.
State and Storage
The iframe runs in a sandboxed context without allow-same-origin. Do not use localStorage, sessionStorage, IndexedDB, or cookies. Doing so can cause your App to fail at runtime. The App Platform (Preview) provides a KV store as your only persistent store.
The KV Store
Each App has its own key-value store for persisting state, configuration, and secrets. The App Platform (Preview) isolates KV data per App, so each request from your App code applies only to that App’s keys.
REST shape: From App code, call fetch() with relative URLs /api/v1/kvstore/<key>. Replace <key> with any string your App owns (for example settings or user-preferences). PUT sends the raw body as the value. GET returns the stored string. Values are opaque to Cribl, so you typically stringify structured data before you write it and parse it after you read.
Values: A value can be any string you can send in the request body, not only small structured settings. Cribl treats the payload as opaque bytes for storage. In practice, Apps persist everything from short flags to large serialized documents, including multi-megabyte artifacts. If you store large values, load them asynchronously and keep the UI responsive. See Async hydration patterns.
Quota: Each App can store up to 1,000 keys by default. To raise the limit, contact Cribl Support.
API keys and credentials: Always write API keys, bearer tokens, passwords, and any other secret material to KV with
encrypted=true. Plain (unencrypted) KV values are visible to anyone in your Organization who can use the KV APIs for that App context, not only to users who open your App UI. Encryption is required for secrets and is the supported way to reference them fromproxies.ymlwith${kv...}expressions resolved on the server.
Secrets: On PUT, append encrypted=true for every credential. Encrypted entries are write-only from the client. Reads return a redacted placeholder. Do not store secrets without encryption.
Key-Value Stores UI: Administrators can pre-seed or edit keys under App Settings > Key-Value Stores. The External API Access tab in App Settings shows how outbound calls are governed for the App. Organization-wide policy is described in External API access in the Admin Guide. Keys you create in Key-Value Stores share the same namespace as /api/v1/kvstore/... calls from App code. In the UI, add API keys and tokens only as encrypted entries.
Example: Write and Read settings From App Code
This snippet is ordinary App JavaScript (for example inside a React effect or handler). It writes a stringified configuration object under the key settings, then reads that key back.
// Write a setting (values are opaque strings; use JSON for structured data)
const settingsPayload = JSON.stringify({ theme: 'dark', refreshInterval: 30 });
await fetch('/api/v1/kvstore/settings', {
method: 'PUT',
headers: { 'Content-Type': 'text/plain;charset=UTF-8' },
body: settingsPayload,
});
// Read it back
const resp = await fetch('/api/v1/kvstore/settings');
const raw = await resp.text();
const settings = JSON.parse(raw);Async Hydration Patterns
Because KV access is async, plan for “no data yet” on initial render:
- Loading gate: Wrap your root component in a loader that fetches required KV keys before rendering the main App.
- Write-after-hydrate: Track a
hasHydratedflag to prevent default local state from overwriting stored KV values during the initial load.
API Calls and Data Flow
Platform APIs
To call Cribl REST APIs, use standard fetch() with relative URLs. Cribl intercepts the request, injects the user’s auth headers, and routes it. Only call documented endpoints from the OpenAPI specification and API Reference.
External APIs and proxies.yml
To call external services, use standard fetch() with the full URL. Cribl intercepts the request and routes it through a server-side proxy.
You must declare all external domains in a proxies.yml file at your project root. Cribl enforces this declaration at runtime, ensuring administrators know exactly what external endpoints your App communicates with.
api.openai.com:
paths:
allowlist:
- /v1/responses
headers:
inject:
Authorization: '`Bearer ${kv.api_key}`'
timeout: 30000Sensitive headers set by App code are always stripped from outgoing requests for security. Use headers.inject in your proxies.yml to securely add credentials stored in the KV store.
Routing and Deep Links
Routing runs entirely inside your iframe using a client-side router (React Router, Vue Router, and so on) that integrates with window.history.
To allow users to bookmark specific views or share them with teammates, support deep linking by encoding minimal state into the URL.
In Safari, client-side routing in the iframe behaves differently than in Chrome, Edge, or Firefox. See Browser Support.
When a user opens a deep link, the host route uses this pattern:
/apps/a/<app-id>/<path-in-app>
For example: /apps/a/my-app/settings/general?tab=advanced.
Cribl restores the path segment below /apps/a/<app-id>/, plus the query string and hash, inside the iframe on load. Your App’s router reads that URL and renders the correct view.
Permissions and Access
Who can create Apps, install packages, and launch installed Apps is described in Roles, permissions, and governance in the Admin Guide.
Design your App to degrade gracefully based on permission variance:
- Handle 403 responses explicitly: Catch 403 status codes and display a helpful message explaining the user lacks required access. Do not let a single failing API call render an empty screen for the entire App.
- Dim or disable unavailable actions: If you can determine permissions via a preflight call, disable buttons rather than letting users hit a wall.
- Document required roles: List the permissions your App requires in your App’s README or first-run screen.
Logging and Troubleshooting
- Logging: Log significant events (API failures, destructive actions) with context, but do not log secrets or raw credentials.
- DevTools: Use your browser’s DevTools to inspect network requests and console output. Attach DevTools to the iframe context, not the top-level Cribl shell.
- Debug with your AI assistant: Copy failing console messages, stack traces, or redacted network error bodies from the iframe context. Paste them into your coding assistant with a short description of what you were doing. Because the assistant already has your repository, it can often propose a fix quickly. It does not run inside Cribl, so it may guess about App Platform behavior. When a suggestion looks off, ask it to reconcile the change with
AGENTS.md, the OpenAPI specification and API Reference, and the Runtime Model and Sandbox and External APIs andproxies.yml. - Stale preview: If you change your build tooling configuration, perform a full browser reload of the Cribl tab to re-establish the Live Preview connection.
- Preview after switching context: If you move between Workspaces, Organizations, or local and cloud deployments while using Live Preview, restart the local development server (
npm run dev) so the App can initialize cleanly in the new context. - Server logs: Cribl records structured access for proxied traffic. Work with your Cribl administrator to correlate server-side logs with your App if you need request-level forensics.
npmerrors or warnings: Switch your shell to Node.js 22.22.2 (for example withnvm install 22.22.2andnvm use 22.22.2, or your version manager’s equivalent). Open a new terminal and retry thenpmcommand.cursornot in PATH: If scaffolding fails withError: 'cursor' not found in PATH. Install Cursor from https://cursor.com, Cursor is installed but the CLI is not on yourPATH. Enable or reinstall the shell command from Cursor, or add Cursor’s install directory toPATHper Cursor documentation. Retry in a new shell.
UX Guidelines
- Bring your own UI: Build layouts, components, and styling in your App. Follow iframe rules in
AGENTS.mdand the Runtime Model and Sandbox. - Make primary actions obvious: Treat destructive actions explicitly with confirmation dialogs and clear danger styling.
- Write clear error messages: Tell the user exactly what failed, whether they can fix it themselves, and when they need to talk to an administrator.
Further Reading on Prompting and AI-Assisted Delivery
These resources are not specific to Cribl, but they match how teams iterate with coding assistants:
- Anthropic’s Prompt engineering overview and Prompting best practices are thorough reference material.
- Teresa Torres summarizes an end-to-end process for AI-assisted building in Vibe coding best practices. The article covers gotchas, testing, and debugging. Cribl does not maintain it. It’s an independent product-management perspective you can adapt alongside this guide.