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

# Placeable surfaces

> Understand the generic surface descriptor shape that lets a shell place product UI without importing each package's private UI code.

<div className="bf-article">
  <p className="bf-lead">
    A placeable surface is a product UI descriptor. It says what can appear, where it can appear, and which named data reads or targets the surface may use. The shell reads that descriptor and places the surface without importing the feature's private screens, stores, actions, or file layout.
  </p>

  ## What this explains

  This page explains the primitive. It is not the Runtime Kit Cookbook recipe.

  Your product grows from one launch surface into launch, help, support, settings, and billing. The shell should still behave like a generic place to put surfaces, not like a product-specific switchboard.

  Use this page when you need to understand why the architecture stays clean. Use [Placeable surface product loop](/runtime-kit/cookbook/placeable-surface-product-loop) when you want the full example succession with files and code.

  ## The separation

  The shell should not import launch dashboard code. It should not import support behavior. It should not import the package that owns help search.

  The shell should only use this descriptor data:

  | Generic part       | What it means                                    |
  | ------------------ | ------------------------------------------------ |
  | Surface descriptor | A piece of UI that can be placed in a region.    |
  | Region             | A named area such as `main`, `rail`, or `panel`. |
  | Data names         | Data names the surface is allowed to read.       |
  | Action names       | Work names the surface is allowed to request.    |
  | Component key      | The renderable body for that surface.            |

  That is the same class of idea as a command center: the arrangement model is generic, the sidebar is generic, and package-specific UI rules live in descriptors and surface bodies.

  ## Visual map

  The flow has four jobs. Each job stays separate.

  <div className="bf-flow" aria-label="Runtime Kit product flow from package material to placed product surfaces">
    <div className="bf-flow-node">
      <span className="bf-flow-step">01</span>
      <strong>Package set</strong>
      <p>Records, stored bytes, and named targets enter through package files.</p>
    </div>

    <div className="bf-flow-arrow" aria-hidden="true">→</div>

    <div className="bf-flow-node">
      <span className="bf-flow-step">02</span>
      <strong>Runtime Kit boundary</strong>
      <p>Package material becomes named data reads and callable action names.</p>
    </div>

    <div className="bf-flow-arrow" aria-hidden="true">→</div>

    <div className="bf-flow-node">
      <span className="bf-flow-step">03</span>
      <strong>Placeable surfaces</strong>
      <p>Descriptors say which region, component, inputs, and targets each surface uses.</p>
    </div>

    <div className="bf-flow-arrow" aria-hidden="true">→</div>

    <div className="bf-flow-node">
      <span className="bf-flow-step">04</span>
      <strong>Dumb shell</strong>
      <p>The shell renders labels, regions, and active surface ids without product branches.</p>
    </div>
  </div>

  ## Ownership lanes

  <div className="bf-lane-map" aria-label="Ownership map for package material, surface descriptors, and the product shell">
    <div className="bf-lane-card">
      <span>Data owner</span>
      <strong>Package file</strong>
      <p>Owns the records, package-owned bytes, and callable targets.</p>
    </div>

    <div className="bf-lane-card">
      <span>Access owner</span>
      <strong>Runtime Kit</strong>
      <p>Turns package material into public reads and requests.</p>
    </div>

    <div className="bf-lane-card">
      <span>Product owner</span>
      <strong>Surface descriptor</strong>
      <p>Declares where a surface belongs and what it may touch.</p>
    </div>

    <div className="bf-lane-card">
      <span>Arrangement owner</span>
      <strong>Shell and sidebar</strong>
      <p>Places surfaces. It does not import package-specific UI code.</p>
    </div>
  </div>

  ## The product map

  ```text theme={null}
  Package set
    -> packages
    -> data names
    -> targets
    -> surface descriptors

  Product shell
    -> reads surface descriptors
    -> renders a generic sidebar from labels and order
    -> renders the active surface in a generic region

  Surface body
    -> reads only the data names named by its descriptor
    -> calls only the targets named by its descriptor
  ```

  The product becomes larger without making the shell import package setup code or product-specific screen names.

  ## Placement sketch

  <div className="bf-rail-diagram" aria-label="Dumb product shell placing multiple surface descriptors">
    <div className="bf-rail-diagram__rail">
      <span>Sidebar</span>
      <strong>Launch</strong>
      <strong>Help</strong>
      <strong>Support</strong>
    </div>

    <div className="bf-rail-diagram__main">
      <span>Region: main</span>
      <strong>surface.launch.home</strong>
      <p>welcome-copy + launch-checklist → launch.next-step</p>
    </div>

    <div className="bf-rail-diagram__panel">
      <span>Region: panel</span>
      <strong>surface.launch.help</strong>
      <p>help.search</p>
    </div>
  </div>

  ## What this prevents

  | Bad shape                                               | Placeable-surface shape                                  |
  | ------------------------------------------------------- | -------------------------------------------------------- |
  | Sidebar branches on `dashboard`, `support`, and `help`. | Sidebar renders descriptor labels and active ids.        |
  | Layout imports product screens directly.                | Layout receives descriptors and resolves component keys. |
  | One new product area means editing the shell.           | One new product area means adding a descriptor and body. |
  | Each new surface adds another special case.             | Each new surface repeats the same descriptor contract.   |

  The descriptor is small on purpose. The shell can stay generic while the product becomes more capable.

  ## Dumb shell rules

  The shell owns arrangement. It does not own package-specific UI rules.

  | Shell may do                                                 | Shell must not do                                                       |
  | ------------------------------------------------------------ | ----------------------------------------------------------------------- |
  | Sort descriptors by `order`.                                 | Check whether a surface is a launch, billing, help, or support feature. |
  | Render descriptor labels.                                    | Import package files or target implementations.                         |
  | Place a surface in `main`, `rail`, or `panel`.               | Decide which package records the surface may read.                      |
  | Track the active surface id.                                 | Decode target reply payloads for a surface body.                        |
  | Resolve a `componentKey` through the app's surface registry. | Add a new `if` branch for each product area.                            |

  If the shell needs to understand a business noun to render the layout, the descriptor is missing something.

  ## Descriptor rules

  A descriptor should be plain data. It gives the shell placement facts and gives the surface body its allowed public names.

  ```ts theme={null}
  {
    id: 'launch.help',
    label: 'Help',
    region: 'panel',
    order: 20,
    componentKey: 'surface.launch.help',
    preparedInputs: [],
    targets: ['help.search'],
  }
  ```

  | Field            | Meaning                                 | Mistake to avoid                                      |
  | ---------------- | --------------------------------------- | ----------------------------------------------------- |
  | `id`             | Stable surface identity.                | Reusing one id for different surfaces.                |
  | `label`          | Human label for generic navigation.     | Making the shell translate package-specific UI rules. |
  | `region`         | Where the shell may place it.           | Hardcoding layout branches by surface id.             |
  | `order`          | Sort order inside a region or nav list. | Making order depend on import order.                  |
  | `componentKey`   | Which registered body renders.          | Importing that body directly in the shell branch.     |
  | `preparedInputs` | Public data names the body may read.    | Letting the body guess storage addresses.             |
  | `targets`        | Public action names the body may call.  | Letting the body import target code.                  |

  ## Failure modes

  | Symptom                                                     | Boundary crossed                                                               | Fix                                                                                                          |
  | ----------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
  | Adding a surface requires editing shell logic.              | Package-specific UI rules leaked into arrangement.                             | Add descriptor data and keep the shell generic.                                                              |
  | A surface reads a package address directly.                 | Prepared-read boundary was bypassed.                                           | Give the surface a data name and read it with `useBitfieldData(...)`.                                        |
  | A button imports the work implementation.                   | Target boundary was bypassed.                                                  | Declare/call an action name with `sendRequestToBitfieldTarget(...)`.                                         |
  | The same surface works in one region but breaks in another. | The surface body depends on layout context instead of its descriptor contract. | Pass only descriptor-approved inputs/targets and make layout region generic.                                 |
  | A new sidebar branch appears for every feature.             | The primitive was not visible enough.                                          | Use [Runtime Kit concept map](/runtime-kit/concept-map) and the Cookbook recipe before changing shell logic. |

  ## Build it

  The complete Runtime Kit Cookbook recipe lives in [Placeable surface product loop](/runtime-kit/cookbook/placeable-surface-product-loop). It walks through the package file, descriptors, shell, surface body, and review checklist as source-owned examples.

  Read [Runtime Kit concept map](/runtime-kit/concept-map) when you want to see how placeable surfaces fit with package files, named data reads, callable targets, and local state.

  Read [Package to screen](/runtime-kit/package-to-screen) when you want the first tutorial that builds one package-to-surface chain.

  Read [Runtime Kit API](/reference/runtime-kit-api) when you need the exact public read and request contracts used inside a surface body.
</div>
