> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stardeck.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Surfaces

> Give one Stardeck app several audience-facing mini apps with their own URLs, icons, and access

A **Surface** is a distinct experience inside one app. To its users it feels like its own mini app: its own name, generated URL, icon / PWA identity, launch behavior, and public or internal posture.

Surfaces live inside one product. They are not separate Stardeck apps and not [Modules](/app-structure/modules). Modules are reusable capabilities; Surfaces are how people open and use parts of the product. See [One Product, One App](/app-structure/overview).

## Add a Surface

The normal workflow is conversational:

1. Ask the project agent for the experience you need — for example a POS for iPads, a kitchen display, or an internal admin.
2. Review the result in preview.
3. Commit or sync so the dashboard can discover the Surface.
4. Publish the app so ready Surfaces go live.
5. Use **Launch** from the Surfaces card when the Surface is live.

You do not need to hand-edit configuration files to get started. Tell the agent what audience and device the experience is for, and whether it should be public or internal.

## Dashboard states

Open **Settings** and find the Surfaces card. Common labels:

| Label                | Meaning                                                                       |
| -------------------- | ----------------------------------------------------------------------------- |
| **Live**             | Declared and available on production                                          |
| **Not deployed yet** | Declared on the branch, but not live until you publish                        |
| **Removed at tip**   | Removed from the branch tip; it can remain live until you publish the removal |
| **Sync**             | Re-read Surface declarations from the current sandbox branch                  |
| **Launch**           | Open the live Surface URL                                                     |
| **Show app shell**   | For internal Surfaces, keep or hide the Stardeck shell around the experience  |

A Surface can appear in the dashboard soon after you commit. 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 organization 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](/app-visibility).

<Warning>
  **Internal is authentication, not admin authorization.** Any signed-in organization member can
  open an internal Surface. If only some roles should use it (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.
</Warning>

## 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](/custom-domains) bound to that host).
* Non-root Surfaces use their generated Stardeck Surface URLs today — 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](/add-to-home-screen).

## Examples

* Restaurant: customer ordering, POS, kitchen display, and back office as Surfaces of one system — [Restaurant Surfaces](/app-structure/guide-restaurant-surfaces)
* Service business: marketing site, customer portal, and staff admin as Surfaces of one booking product

If the next experience needs its own product ownership, tenant boundary, or release cadence, step back to [When to Create a Separate App](/app-structure/separate-apps).
