Documentation/Managing Your App/Admin vs Customer Views
Admin vs Customer Views
Every generated Supero app ships one bundle that renders two different experiences — an operator admin shell and a task-oriented customer view. Here's exactly what each one shows, and how the split is decided.
Overview
You don't build an admin panel and a customer-facing app as two separate projects. Every Supero app is one deployment, and the shell it renders for a given signed-in user — the operator sidebar with a dashboard, or a simplified task-oriented view of just their own stuff — is chosen automatically from that user's role. This page is for anyone deciding which of their app's own users should land where, and for anyone wondering why an app looks different depending on who's logged in.
It covers what's actually on screen in each view: the admin shell's dashboard, per-schema tabs, and System Settings modal; the multi-tenant Tenant Switcher; what a customer's reshaped tab list looks like; and how owner-scoping keeps a customer's "My X" lists limited to their own records. For the underlying role catalog and permission mechanics, see the Roles & Permissions Reference page — this page is about what renders, not how access is checked.
How the View Is Chosen
At login, Supero resolves the signed-in user's role and stamps a ui_view of either admin or customer onto the session (mirrored as context.surface in the response). The generated app's runtime reads this once at boot — via client.userInfo.ui_view, or the convenience helpers client.isAdmin() / client.isCustomer() — and picks a shell accordingly. Nothing in your own app code has to match role strings by hand.
http
POST https://api.supero.dev/api/v1/auth/login
Content-Type: application/json
{
"domain": "acme-corp",
"email": "[email protected]",
"password": "secret123"
}
# Response (relevant fields only)
{
"user": { "role": "tenant_user", "ui_view": "customer" },
"context": { "surface": "customer" }
}| ui_view = admin | ui_view = customer |
|---|---|
| domain_admin, project_admin, tenant_admin, developer | domain_user, project_user, tenant_user, viewer |
ℹ️ Full role mechanics live elsewhere
This table is the same admin/customer split covered in depth on the Roles & Permissions Reference page, including the domain_user/project_user pitfall (broad cross-tenant CRUD access, but still the customer surface). This page picks up from there and focuses on what each surface actually contains.
Touring the Admin Shell
A user in the admin view gets the operator shell: a sidebar (or top nav, depending on your app's layout) grouped into the sections you define on your tabs, plus a few things that are always there.
- •Dashboard — the first item in the first section, showing KPI tiles and charts computed from your schemas' data. It's an admin-only pseudo-tab; it never renders for a customer.
- •One tab per schema you've exposed, grouped by the section label you set on each tab (tabs without a section fall into a default "Navigation" bucket).
- •An account-menu footer with an AI Assistant shortcut (when your app doesn't already surface AI as its own tab), a System Settings entry, and Sign out.
- •For admin roles specifically, a quick link out to your app's own admin console in a new tab — covered on The Admin Panel page.
In a multi-tenant app, admin-shell users with the right scope also get an "Acting as" Tenant Switcher near the top of the sidebar — see the dedicated section below.
System Settings: Password, Services, Workflows
For the complete set, see Roles & Permissions Reference.
Every signed-in user — admin or customer — has a System Settings modal, opened from the gear icon in the account-menu footer. It's tabbed, and which tabs show up depends on role.
| Tab | Who sees it | What it does |
|---|---|---|
| Change password | Everyone | Current password, new password, confirmation. On success the user is signed out and has to log back in with the new password. |
| Services | Everyone | Lists the services your project has imported, each with a status badge — Active, or Needs config. It's a lightweight in-app view over the same object the services catalog API manages; it's not a replacement for the console. |
| Workflows | Everyone | Points to the Workflows console for this app's automations. |
| Login | Admin roles only | A per-browser toggle for the demo-account autofill chips shown on the sign-in screen — useful while previewing, irrelevant once an app is actually published (published apps hide demo chips automatically). |
| Landing | Admin roles only | Preview the customer-facing landing page inside the same session, with an option to swap hero and section images, then return to the admin view. |
On the Services tab, the two config paths split by permission. Anyone holding service:configure (platform_admin/platform_user, domain_admin, project_admin, and developer) additionally sees a one-click action to provision starter test credentials for services that offer them — clearly labeled for testing only, never for production. Every role, including tenant_admin, instead sees a direct link out to the console's Services page to enter real, per-service production credentials.
💡 Configuring integrations for real
System Settings > Services is a status view, not the primary place to configure an integration. Import and configure services through the managed services catalog — GET /api/v1/services/catalog to see what's available, POST /api/v1/services/import to add one to your project, and PUT /api/v1/services/{id}/config to set its credentials.
The Tenant Switcher
In a multi-tenant app (isMultiTenant on the project), the admin shell shows an "Acting as" dropdown near the top of the sidebar for roles that legitimately operate across tenants. It lists every tenant in the project except default-tenant, plus a 🔒 Default scope option and a Manage tenants… entry that jumps to the full tenant-management page.
| Role | Sees the switcher |
|---|---|
| platform_admin / platform_user | Yes |
| domain_admin | Yes |
| project_admin | Yes |
| tenant_admin | Yes |
| developer | No — a project-scoped technical role, not a tenant operator |
| Any customer-view role (domain_user, project_user, tenant_user, viewer) | Never — the switcher is admin-shell only |
Picking a tenant from the dropdown scopes the current browser session's reads and writes to that tenant without a fresh login — useful for support and QA across many customers without juggling separate accounts. Picking Default scope returns to the signed-in user's own tenant.
The Customer View
A user whose role resolves to ui_view=customer doesn't get a stripped-down copy of the admin shell — the same tab set is reshaped into a task-oriented journey before it ever renders.
- •The Dashboard is dropped entirely — customers don't see operator KPI tiles.
- •Any tab whose section is named System, Admin, Administration, or Settings is dropped, so schema authors can keep genuinely operator-only tabs out of the customer view just by naming their section one of those.
- •Every remaining tab is sorted into Browse (a read-only catalog — things to look at) or Mine (records the customer actually owns, relabeled "My <X>", where creating a new one happens too). Browse renders first, Mine after.
- •Purely internal linking entities (line items, cart items, and similar) never get their own tab on either surface.
Which group a schema lands in is automatic by default — based on whether the signed-in role can create that entity and whether it's wired to a transactional service — but a schema author can force it per record type with the customer_surface field on its UI schema (values: browse, mine, shop, hidden). The full field reference, including how it interacts with the surface value on each UI schema, is on the Dynamic UI page.
Owner Scope: What "Mine" Actually Means
A "My <X>" tab needs two things working together, not one. The real boundary is server-side: a per-schema access_policy / access_rule with a filter_field and filter_match (for example filter_field: "customer_email", filter_match: "$user.email") that scopes reads, writes, and record creation to the caller's own identity. That mechanism — including exactly how it resolves and what happens on a mismatched record — is documented on the Access Control (RBAC) page.
On top of that, the shell itself applies a best-effort client-side match on the signed-in user's own identity and drops rows that don't belong to them before rendering. This is a non-authoritative backstop only — it can be bypassed and is not a substitute for the server-side access_rule.
⚠️ The tab label alone scopes nothing
Setting customer_surface: "mine" on a UI schema controls navigation, labeling, and ordering only. Without a matching access_rule that actually scopes that entity to the caller, a permissive policy can still hand back every tenant's records to whoever opens a "Mine" tab — the client-side filter is a defensive backstop, not a substitute for configuring the real one.
Choosing the Right Role When You Provision Users
For the complete set, see Roles & Permissions Reference.
This is the one decision that determines which of the two experiences above someone gets — get it wrong and a customer either can't do anything, or ends up looking at your operator dashboard.
| Who they are | Assign |
|---|---|
| A real end customer of your app — a shopper, patient, guest, member | tenant_user |
| A read-only external party (auditor, reporting partner) | viewer |
| Your own staff running one tenant day to day | tenant_admin |
| Staff who need the operator shell across every tenant in the project (support, ops) | project_admin |
| A cross-tenant analyst or integration account that only needs API-level read/CRUD, not the operator UI | project_user or domain_user |
| Engineers who need schema, SDK, and cross-tenant testing access | developer |
⚠️ Cross-tenant read access is not the same as the admin shell
domain_user and project_user get full CRUD across every project/tenant they can see, but they still land on the customer view, not the admin shell — that split is by design (those roles are meant for cross-tenant data access, not operating the app). If you're building an internal cross-account tool on top of one of those roles, don't assume the admin shell renders for it automatically; you may want project_admin or tenant_admin instead, or a purpose-built API integration.
💡 Decide this once, at invite time
Whether someone sees your operator tools or your product's customer journey comes down entirely to the role you hand them when you create or invite the account — there's no separate flag for it. Changing someone's mind later means changing their role (see Users & Roles), not changing app code.
Next steps
Related pages:
- •Roles & Permissions Reference — the full role catalog, hierarchy, and sign-in flows behind the admin/customer split on this page
- •Access Control (RBAC) — how to configure the access_policy/access_rule owner-scoping that backs every "Mine" tab
- •Dynamic UI — the full customer_surface and surface field reference for controlling how a schema shows up per view
- •Building Multi-Tenant Apps — the Domain -> Project -> Tenant hierarchy the Tenant Switcher operates over
On this page