Use this file to discover all available pages before exploring further.
This page walks through the full lifecycle of a webAI app: setting up your project, developing locally, bundling for production, and uploading to the webAI shell.
Update your vite.config.js to use vite-plugin-singlefile. This inlines all JavaScript, CSS, and assets into a single index.html at build time:
import { defineConfig } from 'vite';import react from '@vitejs/plugin-react'; // or vue() for Vue projectsimport { viteSingleFile } from 'vite-plugin-singlefile';export default defineConfig({ plugins: [react(), viteSingleFile()], build: { outDir: 'dist' },});
The vite-plugin-singlefile plugin is required for webAI compatibility. Without it, your build will produce separate JS and CSS files that can’t be loaded inside the shell.
Your app opens in a normal browser tab. Shell APIs (OasisHost, CollaborationManager, etc.) will be null — this is expected. Build your UI and logic around graceful fallbacks for these APIs so you can develop comfortably without the full shell running.
When you’re ready to deploy, build the single-file output:
npm run build
This produces dist/index.html — a single self-contained HTML file with all JavaScript, CSS, and assets inlined.
Check the file size of your build output. Apps under 1MB load quickly. If your build exceeds 5MB, consider optimizing — large apps may be slow to load inside the shell.
webAI apps are stored in the browser’s localStorage under the key apogee-uploaded-apps. The shell reads this on startup and registers each entry as an app in the launcher. There are two ways to upload.
If you’re running the webAI desktop app (Tauri), the app exposes a local install server at http://127.0.0.1:44280/install. You can POST your app directly:
node scripts/upload.js
The upload script detects whether the Tauri app is running and installs directly. If it’s not running, it falls back to Option 2.
Each uploaded app includes a sourceId — a SHA-256 hash of the HTML content. The shell uses this for:
Deduplication: re-uploading the same content overwrites the existing entry
Cross-device sync: the sourceId matches the approach used by the shell’s internal ApogeeShellManager
Version tracking: each upload increments the version field
The appId is derived from your package.jsonname field. The displayName is derived from the description field. Keep these meaningful — they’re what users see in the launcher.