Skip to content
AI Building

Build an Atrium app with AI

One minimised file with everything an AI tool needs: how to work, the hard rules, the full app contract and the design system. Upload it to any LLM, then describe your app.

ATRIUM-AI-BUILD.mdMarkdown
  1. Upload the file to ChatGPT, Claude, Cursor or any AI tool (or paste its contents).
  2. Describe the app you want in plain English.
  3. Let the AI ask you for the API key when it needs one.
View the file
Auto

Section 6 of 11

How the app appears in COHO

View .md

Default: web app with a quick view. If a manager must click, fill a form, approve something, pay, or view a report inside COHO, set quickViewPath (and usually openPresentation). Native Store config is only for a handful of scalar prefs. Background-only agents are a rare exception (roughly under 5% of apps).

Decision rule:

Manager needs to… Surface
Open a screen, run a workflow, see a report, collect payments, review applicants, or do one-off actions Quick view (quickViewPath) and/or external URL
Flip a few prefs (send time, dry-run, subject line) and leave the app running Optional light config (§5.3) in addition to the above when needed
Never open the app — pure background automation only Agent (omit quickViewPath) — justify this explicitly

Set config.quickViewPath. Self-hosted apps resolve it against the registered base URL. Hosted apps with browser UI set config.browserBaseUrl, and COHO resolves quick view and external config paths against that public HTTPS origin while runtime calls stay private. Absolute URLs are allowed only on the selected browser origin. COHO loads the page in an iframe after minting a short-lived signed launch URL (GET, empty body) with:

Query Role
connectionReference Which org connection opened
atriumUsageToken Short-lived JWT: signed-in person + organisation + connection (≈15 minutes). Use as Authorization: Bearer for interactive Public API calls. Remint while open via the postMessage bridge — do not treat expiry as “close the app”.
theme Opening manager’s COHO UI theme: light or dark (from persisted User.DarkMode, not OS preference). Covered by atriumSignature — use for first paint.
atriumSignature HMAC over the launch GET (same scheme as other signed GETs)

Verify atriumSignature the same way as other signed GETs. Read person/org from the usage JWT claims (personReference, organisationReference, connectionReference) after verifying it with COHO — do not trust unsigned query params for identity. theme is a UI hint only (safe after signature verify); it is not an auth claim.

You must:

  • Send Content-Security-Policy: frame-ancestors … using ATRIUM_FRAME_ANCESTORS when set (do not use a bare *). On Atrium Hosting, COHO injects one Store origin for that environment into the container — treat it as the source of truth. The same Docker image works everywhere because each env gets its own value; a domain move is a Hosting redeploy + re-provision, not an app rebuild.
  • Use ATRIUM_PARENT_ORIGIN as the exact target for atrium.quickView.close postMessage (Hosting sets it to the same origin as ATRIUM_FRAME_ANCESTORS).
  • Treat the page as third-party chrome — no requirement to match COHO CSS.
  • Do not render the app’s name as a page title. COHO’s header above the iframe already shows it from the Store listing, so an h1 with the name shows it twice. Start the page with its first panel.
  • Never put the API key or signing secret in the query string. The launch signature is not a substitute for checking method, path, and connection.
  • For interactive UI calls, prefer Authorization: Bearer <atriumUsageToken>. Effective scopes are connection grant ∩ opening person’s role. Keep the connection API key for background/webhooks only.
  • Keep the Bearer fresh for as long as the quick view stays open: listen for COHO remints and update your client. You cannot mint a usage token yourself.

lifecycle.setup does not carry iframe parents (connect is the wrong place to pin CSP — a domain move should not require reconnect). Hosting injects PORT, ATRIUM_DATA_DIR, ATRIUM_SETUP_SECRET, ATRIUM_FRAME_ANCESTORS, and ATRIUM_PARENT_ORIGIN into the container at provision time.

When self-hosting, you set both env vars yourself. They are always the same value: the Store / manager SPA origin for the COHO environment you are embedded from. Do not hardcode a multi-environment list into the image, and do not use *.

Use one image, different process env per deployment (same pattern as Hosting). Playground and production are not different apps or codebases — flip the two vars (and the usual secrets / API base) when you cut over.

COHO environment Set both vars to
Playground https://playground.coho.life
Production https://coho.life

Example for a Playground self-host deploy:

Terminal window
export ATRIUM_FRAME_ANCESTORS=https://playground.coho.life
export ATRIUM_PARENT_ORIGIN=https://playground.coho.life

These match what Atrium Hosting injects for that environment today. If COHO moves a Store host, Hosting apps are re-provisioned automatically; self-hosted apps update the two env vars and restart — no reconnect required.

Third-party API keys and other process env that must not live in git belong in Hosting runtime secrets, not in the image or a committed .env.

  • Set: My apps / partner portal (Hosting runtime secrets editor), organisation Store manage panel, Public API PUT /v1.1/public/atrium/apps/{appReference}/runtime-env, or MCP PutAtriumRuntimeEnv / PutPublisherAtriumRuntimeEnv.
  • Delete one key: Public API DELETE /v1.1/public/atrium/apps/{appReference}/runtime-env/{keyName}, MCP DeleteAtriumRuntimeEnvKey / DeletePublisherAtriumRuntimeEnvKey, or the Delete control next to each key in the editor.
  • Shape: full-replace map of NAME=value keys (^[A-Z][A-Z0-9_]{0,63}$, max 32 keys). Empty body clears all keys.
  • Read: list endpoints return names only — values are write-only — plus missingRequiredKeys when the manifest declares required entries that are unset.
  • Inject: on every provision, each key is injected as container env from the per-app Secrets Manager document (alongside SetupSecret). Saving or deleting on a Ready hosted app re-provisions so the running task picks up the map.
  • Manifest (optional): declare expected keys in runtimeEnv: [{ "name": "TAWK_API_KEY", "secret": true, "description": "…", "required": true }]. Required keys must be set before a Ready hosted app can re-provision (Update / regenerate setup secret / runtime-env save).
  • Reserved: PORT, ATRIUM_*, AWS_*, ECS_*, and a short list of OS names cannot be set.
  • Self-host: set the same names on your process; COHO does not inject them.

Thin postMessage bridge (parent is COHO):

Message type Direction Role
atrium.quickView.close app → COHO Close the shell
atrium.quickView.ready app → COHO Optional. Ask the host to (re)send theme after your page boots.
atrium.quickView.theme COHO → app { theme: "light" | "dark" }. Sent on iframe load, on ready, and when the manager toggles dark mode while the shell is open.
atrium.usageToken.refresh app → COHO Ask COHO to remint a usage JWT (optional requestId)
atrium.usageToken COHO → app Fresh { atriumUsageToken, expiresAt } (optional requestId) — keep iframe state; do not reload
atrium.usageToken.error COHO → app Remint failed; tell the manager to close and reopen

Apps may ignore theme messages. Matching COHO CSS is not required — this is optional host context for third-party chrome. Check event.origin against your allowed COHO parent origins before applying theme. Prefer the signed theme query for first paint, then listen for live updates.

COHO also remints the usage JWT proactively about every 12 minutes and when the manager’s tab becomes visible again. The Node kit helpers subscribeAtriumQuickViewTheme and createUsageTokenSession wire theme and token refresh. Resize, open-full-app, and toast remain reserved on the same bridge; do not invent parallel channels.

externalConfigureUrl opens in a new tab through the same short-lived signed launch flow as quick view (including atriumUsageToken). Verify the GET signature before showing connection-specific UI. Use this for an existing SaaS dashboard, or alongside quick view — not as a substitute for skipping UI when managers still need to work in the product.

Optional JSON Schema form, proxied to you (§5.3). Flat scalars only. Never use this as the main product surface.

Omit quickViewPath only when the product is truly background: webhooks + Public API + optional light prefs, and managers never need to open a screen. Birthday-style message senders fit; payments, reports, applicant review, multi-step setup, and one-off actions do not. The Store will not offer Open quick view. If you omit quickViewPath, write down why the product has no interactive manager surface before you list.

Reference sample (exception only): CompanyForLife/atrium-app-samples → samples/hello-agent-node. Do not start from it unless you have confirmed the product has no manager UI. The four language hellos (hello-node, hello-python, hello-go, hello-dotnet) are the standard web-app starters.

Register and edit your listing in the Store (Build an app / Edit listing): icon, screenshot, and copy live on the app row you own. A local store/ folder (hello-node ships an example) is only a convenience if an AI or teammate prepares files for upload; it is not required.

The Store shows each app as a card. The card picture is the app’s first screenshot, with the app name over a fade at the bottom. An app with no screenshot gets a coloured card based on its name, so it still looks tidy, but a screenshot shows people what they are getting.

  • Make the first screenshot the screen that best shows what the app does. 1440 x 900 works well.
  • Keep the key content in the top two thirds. The bottom third fades to a dark colour behind the app name.
  • Show the app itself, not a sign-in, error or empty screen.
  • The card shows the first two lines of the short description, so lead with the benefit.
  • The icon is a square PNG, at least 512 x 512, and the picture fills the whole canvas. Do not add rounded corners, a border, a shadow or padding, and do not put a rounded icon on a coloured square: the corners would show. Transparent corners show the card colour behind. COHO rounds the corners itself.
  • Always supply an icon when registering or editing a listing, unless one is already on the app. With no icon, the Store shows the app’s initials on a coloured tile (e.g. “AL”, “CB”). That fallback is temporary scaffolding only — create and upload a real icon before you invite anyone to try the app in COHO (Default builder workflow step 4; design kit §20.1).
  • The Build an app form warns when an icon has obvious corners.
  • Before a public listing can be approved, fill company-level disclosures once on the publisher profile (country, support site and hours, privacy policy URL, sub-processors URL, licence — Atrium standard or your own terms URL), plus app-level fields on Edit listing: data location (COHO-built apps default to AWS London when blank), a plain-English reason for each requested permission, name/icon/description/screenshots. Design kit §20.3 lists the copy limits; the published listing guidelines are the product rules.

Set price on Build an app / Edit listing (not in listing marketing copy). The Store shows the catalogue price on the card and detail page.

Choice What the customer sees Notes
Free Free No app charge. The installing organisation still uses its shared API/MCP credit allowance for calls your app makes.
Paid — flat monthly Your price per month (+ VAT where shown) One amount for the organisation.
Paid — per unit / month Your price per active unit per month (+ VAT where shown) Units are stock rooms and properties that are not disabled. Counted when the invoice is raised.

Who bills. COHO is the merchant of record. Customers pay COHO by card. Organisations with no card, or with BACS as the only default method, cannot install a paid app until a card is on file. Free apps do not need a card for the app itself.

When a paid install is charged (UTC calendar months). Connecting on days 1–14 of the month can raise an install charge for the current month. Connecting on day 15 or later: the rest of that month is free for that connection, and the first charge is on the next 1st. Charges are whole months — no day-level proration. Disconnect ends billing after the month already paid; reconnect in a month already paid for that product does not charge again.

Your share. On paid catalogue sales, your developer share of Net Receipts is the percentage set out in your Commercial Schedule. You agree a Commercial Schedule with COHO before you publish your first app. The split is internal bookkeeping on COHO’s side (it is not a separate line on the customer’s invoice). Remittance timing and tax treatment follow the Atrium Distribution & Billing Addendum.

Price changes. New installs pay the new price immediately. For organisations already connected, a price change takes effect on the first 1st that is at least 30 days after you change it.

Not at launch. One-off payments and in-app purchases are not offered yet. Optional free trials exist as a product setting and are off by default.

Private apps (not listed). A COHO-hosted private app carries a £10 / app / month hosting seat (card required). Self-hosted private apps have no hosting seat fee; their API/MCP use still draws from the organisation’s credits.

Credits vs app price. Every connected app (free, paid, private, COHO-built) consumes the installing organisation’s shared Public API / MCP credit pool. App subscription price and usage credits are separate lines.