Surfaces
Give one app several mini apps, such as a booking site and a staff POS, each with its own URL, icon and access.
A Surface is a distinct experience inside one app. To its users it feels like its own mini app, with its own name, generated URL, icon and PWA identity, launch behavior, and public or internal access.
Surfaces live inside one product. They are not separate Stardeck apps and not Modules. Modules are reusable capabilities. Surfaces are how people open and use parts of the product. See One Product, One App.
Add a Surface
Ask for the experience
Ask your coding agent, for example for a POS for iPads or an internal admin. Say which audience
and device it is for, and whether it is public or internal. The agent declares the Surface in
code, following the app's AGENTS.md. If you build in the browser, ask Starcat Developer in the
app's Build tab.
Review it
Try it in the sandbox or a branch preview. Its own URL comes later, with the production deploy.
Sync the Surface
Once the change is on the default branch and its sandbox runs that commit, click Sync
surfaces in Settings → Deployments → Production so the dashboard discovers it. Your agent
can do this with sync_app_branch_surfaces.
Deploy
Deploy the app so ready Surfaces go live. See Publishing & Deployment.
Open it
Where Surfaces appear
Surfaces are rows in Settings → Deployments → Production. Common states:
| Row state | Meaning |
|---|---|
| Live (shows a URL) | Served on production. Open it from the row. |
| Ships on next deploy | Declared on the branch. Not live until you deploy. |
| Removed at tip | Removed from the branch tip. It stays live until you deploy the removal. |
Each row's ⋯ menu has Show app shell. When it is off, opening the Surface from Stardeck skips the shell and goes straight to its own URL. Live Surfaces also appear as tabs in the app frame.
A Surface can appear in the dashboard soon after it reaches the default branch. Its launch URL becomes usable after a production deploy.
Access and project visibility
Surface access is either public or internal. Project visibility still wins:
| Project visibility | Surface access | Effective outcome |
|---|---|---|
| Public | Public | Public Surface URL |
| Public | Internal | Internal Surface URL; signed-in team members can enter |
| Internal or private | Public | Still internal: project visibility dominates |
| Internal or private | Internal | Internal Surface URL |
There is no per-Surface private access setting. Private stays an app-level visibility choice. See App Visibility for the full rules.
Internal is authentication, not admin authorization. Any signed-in team member can open an internal Surface. App users cannot: they sign in only to the deployed app and do not have Stardeck team access. If only some team members should use the Surface (for example managers only), ask the agent to add an in-app permission check on that Surface. API routes used by the Surface authorize separately. They are not covered by the Surface access setting alone.
Publish, URLs, and launch identity
- One app publish ships all ready Surfaces together.
- Non-root Surface hosts are production-only in the current release. Preview keeps working inside the sandbox; dedicated Surface URLs appear after production deploy.
- The root Surface uses the app's primary host (including any custom domain bound to that host).
- Non-root Surfaces use their generated Stardeck Surface URLs. There is no per-Surface custom-domain picker.
- If you need an internal experience on the root of a public app, make the whole app internal instead. An internal root Surface in a public app cannot receive the separate edge boundary.
Each Surface can have its own PWA name, icon, and launch path. Internal Surfaces can also override Show app shell so a pinned iPad or phone experience opens without Stardeck chrome. See Add to Home Screen.
Example: restaurant
One restaurant system app with four Surfaces:
| Surface | Audience | Access |
|---|---|---|
| Customer ordering | Diners and takeout | Public |
| POS | Counter staff on iPads | Internal, plus staff permission check |
| Kitchen display | Kitchen team | Internal, plus kitchen permission check |
| Back office | Managers | Internal, plus manager permission check |
They share the menu, orders and release cadence, so they belong in one app. Ask your agent:
Build a restaurant system with shared menu and orders. Add four Surfaces:
1) public customer ordering, 2) internal POS for iPads, 3) internal kitchen display,
4) internal back office for managers. Staff Surfaces should require the right roles;
internal access alone is not enough.Follow-ups:
Make the POS open straight into the order screen and use a clear home-screen icon for iPadsOn the kitchen display, show open tickets and let the kitchen mark items readyTo keep the whole system off the public internet, make the app internal or private.
Publish once:
- Review each Surface in preview.
- Merge the change, then click Sync surfaces in Settings → Deployments → Production. Declared Surfaces read Ships on next deploy.
- Click Review & Deploy there. One deploy ships all ready Surfaces.
- When a row shows a live URL, open it. For iPad POS or kitchen tablets, turn Show app shell off and add it to the home screen.
A service business works the same way: marketing site, customer portal and staff admin as Surfaces of one booking app.
If the next experience needs its own ownership, tenant boundary or release cadence, see When to Create a Separate App.