Docs menu
DocsBuild an app

Design guidance

The ChatOSS app pattern, the delivery checklist, and the mistakes every app in the catalogue had to be repaired for.

The ChatOSS app pattern

For most project- or collection-based apps, copy ChatOSS Kanban's three-column architecture:

  1. Left — project library: create/select/rename/delete projects or durable workspaces.
  2. Middle — project AI chat: show a model picker from chat.listModels(), keep chat history per project, include a fresh selected-project snapshot in the system message, and expose complete CRUD tools for everything the user can change.
  3. Right — app canvas: the product-specific surface (sticky notes, board, editor, diagram, preview, etc.). Usually this is the only column that should fundamentally change between apps.

Small single-purpose utilities may omit the pattern, but it is the default. The canonical example in the in-app Docs app is Sticky Notes — use it as the visual/architectural reference.

Design rules

  • Style from the platform classes and tokens (.app-shell, .btn, .list-row, var(--surface-2), …) — see Styling & theming. Never redefine :root colour tokens and never use @media (prefers-color-scheme: dark); the host stamps data-theme and both themes come for free.
  • Never use confirm()/alert()/prompt() — the sandbox has no allow-modals, so confirm() silently returns false and every destructive action guarded by it becomes a no-op. Build the confirmation with .overlay/.modal. → The runtime bridge
  • Stream AI output with onToken — never a spinner followed by a wall of text.
  • Disable buttons while work is running; show a short status line.
  • The app must work by hand too — treat AI as an alternative interface to the same data.
  • Agent tools must be complete and orthogonal: create/read/update/delete plus any domain actions the UI supports. Return truthful result strings and never let the model claim an unconfirmed mutation.

Checklist before delivering

  1. app.json is valid JSON with id (lowercase reverse-DNS), name, version, description; capabilities has ONLY what the code uses. → The manifest
  2. Entry HTML references your files with plain relative paths.
  3. Every window.chatoss call is awaited; every gated call handles null/denied.
  4. State persists via scopedData and restores on launch.
  5. If the app has chat, the user can choose a model from chat.listModels() and the choice persists per project/workspace. → AI chat
  6. Project/collection apps follow library → CRUD agent → product canvas, and the agent can perform every mutation available by hand.
  7. The UI is built from the platform classes + tokens; no :root colour overrides, no prefers-color-scheme rule. Check it in BOTH ChatOSS Light and Dark.
  8. No confirm()/alert()/prompt()/window.print() anywhere — they do not work in the sandbox. Destructive actions use an in-frame .modal.
  9. An icon file exists and is named in "icon".
  10. If the app exports documents (PDF/Word/Excel/PowerPoint/image): use the OS documents API (no vendored library, no window.print() — it's blocked in the sandbox). Declare "documents" (+ "fileAccess" if you use documents.save()). For PDF/DOCX with any formatting (bold, italic, headings, lists), pass the content as content.blocks (structured blocks + styled runs) — NOT plain paragraphs/text, which strips formatting. → Documents
  11. If the app produces files of its own (reports, exports, transcripts), they go in drive — not buried in a database row and not begging the user for a folder. The user's own project files stay in files. → Two filesystems
  12. If you're building outside ChatOSS: zip the files (they must sit at the zip root), rename the zip to yourapp.aip, and drop it on the ChatOSS Apps app.
  13. If you ARE inside ChatOSS Code: publish the finished app with the publish_app tool — the user gets a Publish / Cancel prompt, and on Publish the folder is zipped, validated, and installed.