> ## 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.

# Build your own surface

> How to design another app-facing SDK without exposing Bitfield setup details.

<div className="bf-article">
  <p className="bf-lead">
    A good SDK gives app code a small surface and keeps Bitfield setup work outside app code. The public surface should stay narrow because the setup work is already packaged away.
  </p>

  The JavaScript Runtime Kit is the example. App code gets one read hook and one request function. Bitfield still handles boot, connection, package loading, storage readers, subscriptions, and validation outside that surface.

  A team wants the same package-backed feature to work from React today and a different app surface later. The SDK should preserve the same read/request shape instead of making every app call setup steps.

  <div className="bf-flow" aria-label="SDK boundary flow">
    <div className="bf-flow-step">
      <span>App</span>
      <strong>Calls product functions</strong>
      <p>Read named data. Send a named request. Render product states.</p>
    </div>

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

    <div className="bf-flow-step">
      <span>SDK</span>
      <strong>Owns setup seam</strong>
      <p>Connects, subscribes, decodes, retries, and keeps setup details out of app code.</p>
    </div>

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

    <div className="bf-flow-step">
      <span>Bitfield</span>
      <strong>Runs package contracts</strong>
      <p>Packages, data names, targets, local state, and runtime/device access stay outside app code.</p>
    </div>
  </div>

  ## The rule

  Expose the read or request the app actually needs. Do not expose the setup steps Bitfield had to take to make that possible.

  <div className="bf-grid">
    <div className="bf-card">
      <strong>Expose reads.</strong>
      Give app code a stable way to receive data, loading, and error.
    </div>

    <div className="bf-card">
      <strong>Expose requests.</strong>
      Give app code a stable way to send a target plus payload.
    </div>

    <div className="bf-card">
      <strong>Hide setup work.</strong>
      Keep boot, package binding, storage addressing, byte subscriptions, and transport setup outside the app surface.
    </div>
  </div>

  ## A public surface can be small

  ```ts theme={null}
  export { sendRequestToBitfieldTarget } from './request-surface';
  export { useBitfieldData } from './react-surface';
  ```

  That is enough for most app code. If you need a Swift, Kotlin, Python, or server-side surface later, keep the same shape: one way to read named data and one way to send a request.

  ## The setup surface can be large

  The setup surface can do real work. It may connect to Bitfield, load packages, prepare read scopes, subscribe to updates, decode payloads, validate package files, or recover from resets.

  That does not mean the app surface should expose those details. App developers should not have to call setup code just to render data.

  ## The boundary test

  Ask this before adding a public SDK function:

  <div className="bf-callout">
    Would an app developer call this because their product needs it, or because Bitfield setup needed a place to live?
  </div>

  If it is setup work, keep it outside the public app surface.

  ## Common failures

  | Symptom                                                        | Cause                                                             | Fix                                                         |
  | -------------------------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------- |
  | App code has to call three setup functions before reading data | The setup seam leaked into the app surface                        | Move setup into the SDK entry point                         |
  | SDK exposes raw package material                               | The SDK is making app code understand package admission           | Expose named data reads and named requests instead          |
  | Another language SDK has different product concepts            | The SDK copied implementation details instead of the public shape | Keep every SDK around read, request, state, and error       |
  | Error handling is different on every screen                    | The SDK does not have a stable error contract                     | Return consistent loading, error, empty, and success states |

  ## Verify

  The SDK boundary is right when app code can render a surface with one read call and one request call while setup work stays invisible to the product component.

  ## Next

  Use [App surfaces](/build-your-own-surface/app-surfaces) to design the caller shape and [Runtime Kit API](/reference/runtime-kit-api) for the exact JavaScript public surface.
</div>
