The single-file model
A webAI app is a single, self-contained HTML file. All JavaScript, CSS, images, and other assets must be inlined or bundled into that one file. There are no external asset dependencies at runtime — your app needs to work without fetching anything from a server. This constraint exists because apps are distributed . When someone shares an app in a space, the entire app is transferred as a single payload. There’s no server to host static assets.If you’re building with a framework like React or Vue, you can still use your normal development workflow. A bundler like Vite produces the single-file output at build time. You develop normally and only bundle when you’re ready to upload.
How apps run
When you upload an app, the webAI shell:- Stores the HTML content in the browser’s
localStorageunder the keyapogee-uploaded-apps - Registers it in the launcher alongside the built-in apps
- When launched, loads your HTML into a sandboxed
<iframe> - Injects platform globals (
OasisHost,CollaborationManager, etc.) into the iframe’swindowbefore your code executes
Constraints
| Constraint | Details |
|---|---|
| Single file | All JS, CSS, and assets must be inlined into one HTML file |
| Client-side only | No server-side code. Your app runs in the browser |
| No external fetches | Don’t depend on CDN-hosted libraries or external APIs for core functionality |
| Iframe sandbox | Your app runs in an iframe — some browser APIs may be restricted |
| Graceful degradation | Shell APIs are null outside of webAI (e.g., during local development). Always check before calling |
Development vs. production
During development, your app runs outside the webAI shell — in a normal browser tab via a dev server. This means all shell APIs (OasisHost, CollaborationManager, etc.) will be null. Your app should handle this gracefully and still be functional for UI development and testing.
When your app runs inside the webAI shell, those globals are injected and available.
Recommended project structure
While you can build an app in a single hand-written HTML file, most developers use a framework with a bundler. Here’s a typical project layout:src/webai.jsis a thin helper module that wraps access to all shell-injected globals with null safety. This is your integration layer — it keeps shell-specific code out of your components.vite-plugin-singlefiletells Vite to inline all assets into a singleindex.htmlat build time, satisfying the single-file requirement.scripts/upload.jsgenerates a browser console script that uploads your built HTML into the webAI shell’slocalStorage.
Frameworks
webAI apps work with any framework — or no framework at all. The most common choices are:- React
- Vue
- Vanilla HTML
Use Vite with the React template. React’s component model maps naturally to the API patterns (polling AI status with
useEffect, managing space state with useState).Theme integration
The webAI shell sends theme updates to your app viapostMessage. This lets your app respond to light/dark mode changes in real time.
Listening for theme changes
Other shell messages
The shell communicates several event types to your app’s iframe:| Message type | Description |
|---|---|
canvas:theme | Theme changed (light/dark). Payload: { theme: 'light' | 'dark' } |
canvas:connected | Your app is now connected to a collaboration space |
canvas:disconnected | Your app disconnected from the space |
canvas:users | The user list in the space changed |
canvas:user-left | A user left the space |
Next steps
Accessing shell APIs
Learn the universal pattern for safely accessing all platform APIs from your app code.