S
supero.docs
Documentation/Building Your App/Build Your First App (App Studio)

Build Your First App (App Studio)

How App Studio turns a plain-English description into a running, deployable app: describe it, review the generated backend, choose a UI, generate, and publish to a supero.live address — including which plans include a live deployment, and what to do when a step fails.

Before You Put It in Front of Users

⚠️ A generated app is not hardened by default

Generating and deploying an app is the easy half. Before real customers use it, work through Going to Production: rotate the seeded demo credentials the bundle ships with, remove the demo login affordances, review the access policies (which are permissive by default), and confirm your customers are not in default-tenant.

Overview

⚠️ Publishing to a live URL depends on your plan — check it before you build to a deadline

Everything on this page up to the deploy step works on every plan, including the free trial. Publishing does not. A live deployment is an allowance your plan grants, and the two lowest tiers grant none of it: Trial and Basic are both build-and-preview only, so the deploy step answers with an upgrade prompt instead of a URL. Nothing is broken and retrying will not change it — Starter is the first plan that includes a live deployment. You can still download the app as a .tar.gz and run it on infrastructure you control. See Plans & Billing for the allowance tier by tier, and the deploy section below for what you actually see.
App Studio is Supero's guided app builder. You describe the app you want in plain English, App Studio generates a real backend for it — entities, fields, relationships, access policies, and starter data — plus a working UI on top, and you deploy the result to a live URL. Every entity, policy and screen App Studio produces is inspectable and editable — you can take over any part of it. Editing happens through the platform, but the source is not locked in: once a build completes you can download the app as a .tar.gz, or push it straight into a GitHub or Bitbucket repository you own. If you would rather write the code on your own machine from the start, build over MCP from your editor instead. Ways to Build compares the paths, and Continuity & Exit covers what you can take with you.
This page walks through that flow end to end: describing your app, reviewing what gets generated, choosing your UI, deploying, and iterating afterward.

ℹ️ Three different AI features — don't mix them up

App Studio (this page) builds your whole app: you describe it, review what's generated, and deploy. The In-App AI Agent is a separate, always-on chat built into every generated app for your end users — it answers questions and acts on the app's own data with no setup required. services.ai is yet another, separate thing: a keyed integration in the managed services catalog for when your app's own logic needs an AI-generated response as one feature among many (a summarize button, a draft-reply field) — like any catalog service, it has to be imported and configured before your app can call it, and it is not what powers the in-app assistant. See the In-App AI Agent page for the built-in chat.

From Description to Running App

Generating an app happens in a few reviewable steps rather than one big leap, so you can see and adjust the backend before the UI is built on top of it.
  • •Describe your app — write what you want in plain English: the entities, how they relate, and who uses the app. You can also start from a reference screenshot instead of typing, and App Studio will extract a starting description from it.
  • •Review the brief — App Studio elaborates a short description into a fuller requirements brief you can read and edit before anything is generated, so the result matches what you meant.
  • •Generate the backend — App Studio produces your schema (entities, fields, relationships), access policies, and starter seed data. Review this first: it is the foundation everything else is built on.
  • •Choose your UI — pick an app name and emoji, a colour theme, a tone for the AI-written copy, how people sign in, and which entities appear on the landing page.
  • •Generate the app — App Studio builds the web UI on top of the backend you reviewed. Generated applications target the web; a mobile surface is not part of the bundle.
  • •Deploy — publish your app to an address the platform generates for you. This is the one step in this list that your plan can refuse; see Deploying Your App below.
  • •Iterate — describe the next change in plain English and regenerate with your current app as context, or edit the generated files directly for full control.

ℹ️ Generation is a background job, not a chat

Describing your app kicks off an asynchronous job on the server; App Studio streams progress back to your browser as the job runs. It's a one-way build step, not a back-and-forth conversation — closer to watching a build log than chatting with an assistant. A full generation typically takes anywhere from under a minute to a few minutes depending on how much you asked for.

What App Studio Generates

Every app App Studio builds is made of the same plain, declarative pieces. A generated schema entity looks like this:
python
Task = {
    "schema_type": "object",
    "name": "Task",
    "namespace": "myapp",
    "parent_type": "tenant",
    "description": "A unit of work owned by a tenant.",
    "attributes": [
        {"name": "title", "type": "string", "mandatory": True},
        {"name": "status", "type": "string", "values": ["todo", "in_progress", "done"]},
        {"name": "due_date", "type": "datetime"},
        {"name": "priority", "type": "integer"},
        {"name": "owner_username", "type": "string"},
    ],
}
attributes and mandatory are the canonical spellings, and they are what App Studio emits. fields and required are accepted as synonyms when you write a schema by hand, but a body sent with fields is stored under attributes — so a read never returns the key you wrote. Prefer the canonical form when you edit generated schemas; the Schema Reference has the full field vocabulary.
Every record also carries system fields you never define yourself: uuid, created_at, updated_at, fq_name, parent_type, parent_uuid. Records are always keyed on uuid, never id.
WhatContains
SchemaEvery entity App Studio identified from your description, with its fields, types, and references to other entities.
Access policiesWhich roles can create, read, update, or delete each entity, including which records a role is scoped to.
Seed dataRealistic sample records, so your new app isn't empty the first time you log in. Coverage is not uniform: App Studio writes one coherent story, and entities on the edge of it can arrive with no rows at all.
UIPer-entity views (list, detail, cards), dashboard widgets, a landing page, and the theme and landing entities you chose.

💡 It stays editable

Everything App Studio generates is plain source you can edit by hand at any point. For deeper schema changes see the Schema Reference; for UI changes see Dynamic UI.

Choosing Your UI

Before App Studio builds the UI, you set a few things that steer it — you're not stuck with generic defaults.
SettingWhat it controls
App name & emojiThe display name and the emoji used as your app's icon throughout the UI.
ThemeThe colour palette applied to the generated UI — one of the presets, or a custom palette.
ToneThe voice used in AI-written copy — for example professional, casual, or friendly.
Auth mode & navigation styleHow people sign in to the generated app, and the shape of its navigation.
Global searchWhether the generated UI includes a search box.
Application type & primary consumersWhat kind of app this is and who uses it. Both steer the generated copy and layout, not your data model.
Landing page entitiesWhich of your entities appear on the generated public landing page.
Hero messageAuto-written from your description, or a headline you write yourself.
These choices only affect how the UI is generated — your schema and access policies are unaffected by them, so you can change theme or tone later without touching your data model.

Access Policies App Studio Generates

Along with your schema, App Studio generates access policies: one policy per role, each holding a list of rules that grant specific operations on specific entities, optionally scoped to a record field so users only see their own rows.
python
from supero.app_setup import PolicyDef, PolicyRule

access_policies = [
    PolicyDef(role="tenant_admin", default_access="full", rules=[]),
    PolicyDef(role="tenant_user", default_access="full", rules=[
        PolicyRule(entity="task", can_read=True, can_create=True, can_update=True,
                   filter_field="owner_username", filter_match="$user.name"),
    ]),
    PolicyDef(role="viewer", default_access="none", rules=[
        PolicyRule(entity="task", can_read=True),
    ]),
]
PolicyRule fieldDescription
entityThe schema this rule applies to.
can_create / can_read / can_update / can_deleteWhich operations this rule grants. can_read defaults to true; the others default to false.
filter_fieldThe record field compared for row-level scoping, e.g. 'owner_username'.
filter_matchThe value to match against, e.g. '$user.name' or '$user.uuid'.
hidden_fieldsFields stripped from read responses for this role.
readonly_fieldsFields stripped from create/update payloads for this role.
default_access is the fallback a role gets on any entity no rule mentions. "none" is fail-closed — no access unless a rule grants it. "full" is the opposite. App Studio typically assigns tenant_admin, tenant_user, and viewer to your app's own users — see Access Control for the full role model, custom roles, and field-level rules.

⚠️ The generated policies are usually permissive, not fail-closed

App Studio most often generates default_access="full" for tenant_admin and tenant_user, and either value for viewer. That is a sensible default for a demo and the wrong one for real customer data, because it decides what happens to entities no rule mentions — including every entity you add in a later regeneration, which inherits the fallback rather than being denied. Read the generated PolicyDefs before you publish, and switch any role that should not see everything to default_access="none" with explicit rules. Row-level scoping is separate and still applies: a rule carrying filter_field and filter_match narrows a role to its own records whatever the fallback is.

Deploying Your App

Deploying from App Studio publishes your generated app to Supero Cloud, with no cloud account of your own required. The address is generated for you from your domain and project name:
text
https://live-{domain}-{project}.supero.live
You do not choose that subdomain. It is stable across redeploys of the same project, so it is safe to share — but you cannot point your own domain at it, and there is no self-service flow anywhere in the deploy path that would let you. Read Custom Domains before you promise anyone a branded address.

Preview and Go Live are not the same deployment

A preview is a temporary deployment for checking your work. On a plan with no live-deployment allowance you get one preview per project and it expires on its own after a short window; relaunching it after that asks you to upgrade. Go Live is the permanent one — it is never reaped, it keeps the same address across redeploys, and it is what your plan's live-deployment allowance counts.

⚠️ On Trial and Basic, publishing answers with an upgrade prompt instead of a URL

When your plan includes no live deployments, App Studio shows an "Upgrade to deploy" card where the link would be. It is not a transient failure, there is nothing to retry, and it does not mean the build was bad — the bundle is finished and downloadable. Over the API the same refusal is an HTTP 402 carrying error: "quota_exceeded" and upgrade_required: true, alongside the meter, limit and used values an upgrade prompt needs; never retry a 402. See Plans & Billing for the allowance and Rate Limits & Quotas for the 402 contract.
The generated app is a plain, portable bundle: the same source can also run in your own AWS or GCP account, or fully on-premise, without changes to the app itself. That is also the escape hatch when the plan gate stops you — download the .tar.gz and run it yourself. See Cloud Deployment and On-Premise for those paths.

⚠️ Redeploy after changes

Regenerating a piece of your app or editing the generated files by hand does not push those changes live by itself — deploy again to publish them. A live app still showing old behaviour after a change you are sure you made is almost always a missing redeploy.

Iterating on Your App

After the first generation, there are two ways to keep changing your app.
  • •Describe the change — tell App Studio what to change in plain English (for example, "add a due_date field to tasks" or "let managers see every team's tasks") and it regenerates using your current app as context, rather than starting over.
  • •Edit the files directly — the generated schema, UI, and setup files are plain, readable source. Open them and change them by hand for full control, then redeploy.

⚠️ A backend regeneration builds neither the screens nor the tables

Regenerating the backend to add an entity or a field rewrites your schema, setup and config. It does not touch the UI, and it does not create anything in your database. Two more steps stand between it and something you can see: carry on through the UI steps so the new entity gets screens, then deploy — the tables are created at deploy, not at generation. Stopping after the backend step is the usual reason a newly added entity "does not show up".

ℹ️ Read the verdict, not just the progress bar

A regeneration that carried a change request ends with one of three verdicts, and only one of them means your change landed. "Your change is in this build" names the tables and fields that were added. "No data-model change was needed" means your existing entities already covered the request and nothing was added — name the entity and the fields it should hold if you expected a new one. "Your change was not applied" means the schemas were left exactly as they were. A build can also land part of a request and list the rest as not applied, so read the whole verdict: a completed build is not the same as a completed change.

💡 Review before you redeploy

Whichever path you take, review what changed before deploying again — especially access-policy changes, since they control who can read and write your data.

When Something Goes Wrong

Most App Studio failures are one of four shapes. The unifying rule is that a step which finishes is not a step that worked — check the artefact, not the progress indicator. Errors & Status Codes is the reference for every failure that arrives wearing a success status.

Generation fails, or the progress stops updating

  • •The build runs on the server, not in your browser. If the page goes quiet — a sleeping laptop, a network change, a throttled background tab — the job has usually carried on and finished. Reopen the project in App Studio before regenerating anything: the most recent bundle is listed there with its own download and launch actions, and regenerating would only spend another app generation.
  • •A generation that genuinely fails ends with an error rather than going quiet. Re-run it with a shorter, more concrete description — a brief asking for several apps at once is the failure that repeats.
  • •App generations are metered per month by plan. Once that allowance is spent the request is refused with a plan response rather than an error you can retry — see Plans & Billing.

The app builds but a screen is empty

  • •Not every entity gets sample rows. App Studio writes one coherent narrative worth of seed data, and entities at the edge of that narrative — along with anything meant to fill at runtime, such as carts and order lines — routinely ship with zero rows. On a brand-new app, an empty tab is far more often "nothing was seeded here" than "the read failed".
  • •Check which account you are signed in as. A generated rule can scope a role to its own records, so a screen that is full for the admin account is legitimately empty for a demo user.
  • •A list read is scoped to the project carried in your credential, and answers with 200 and an empty array rather than an error when it finds nothing there. An empty list is also how some denials are expressed — see Errors & Status Codes before concluding a table is empty.
  • •If the entity came from a later regeneration, confirm you regenerated the UI and then deployed. Until that deploy, the entity has no screens and no table.

A button or service call appears to do nothing

  • •Transactional service calls report failure inside a success response. POST /api/v1/services/execute returns 200 with success: false plus error, error_code and status_code in the body, so a client checking only the status sees a call that silently did nothing. Branch on the body, not the status — see Transactional Services.
  • •An illegal state transition arrives in several wrappings — a 409, a 200 with success: false, or a plain string with the payload embedded in the error text. Match on INVALID_STATE_TRANSITION wherever it appears rather than on the status code.
  • •If workflows or event bindings never fire, check that "workflows" is the last entry in the services list in the generated config. An out-of-order list drops that registration with no error at all — see Anatomy of a Supero App.
  • •A write that returns success but changed less than you asked for is usually field-level policy: fields a role may not write are stripped from the payload rather than refused. Read the record back and compare.

A deploy hangs, or never produces a URL

  • •Publishing is asynchronous. The call is accepted immediately and the deployment moves from launching to running or failed, so App Studio polls rather than blocking. A deployment sitting in launching is still building; give it a few minutes before treating it as stuck.
  • •An upgrade prompt where the link should be is the plan gate, not a failure — see Deploying Your App above. Downloading the bundle and running it yourself is unaffected.
  • •A preview on a plan without a live-deployment allowance expires on its own, so an address that worked earlier and now does not has most likely been reaped rather than broken. Relaunch it, or publish properly on a plan that includes a live deployment.
  • •If the deploy succeeds but the app does not reflect your change, check that you deployed after the change. Regenerating and hand-editing both leave the live app untouched until the next deploy.

ℹ️ What to have ready if you ask for help

Your domain and project name, the address the app answers on, the step that failed, and the exact response body and status if you were calling the API — including the correlation_id when the response carried one. See Contact & Links.

Next Steps

Where to go from here:
  • •Schema Reference — model entities, fields, and relationships in depth, including editing the generated schema by hand.
  • •Dynamic UI — how the UI is generated from your schema and how to customize individual views.
  • •Access Control — the full role and policy model, including custom roles and field-level rules.
  • •In-App AI Agent — the built-in chat every generated app ships with for its end users.
  • •Plans & Billing — which plan includes a live deployment, and how app generations are metered.
  • •Errors & Status Codes — the failures that arrive as a 200, and the triage order that resolves most of them fastest.