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

# Custom screens

> Register a full-screen native React component for a flow node. Status: accepted but not yet rendered.

A custom **screen** is the full-screen sibling of a [custom component](/expo-sdk/custom-components): instead of embedding native UI inside a flow screen, the whole screen node is your React component, while the flow still owns navigation and persistent zones around it. The SDK exposes the registration API and types for this today, but the renderer does not yet invoke them.

<Warning>
  **Custom screens are not rendered in this build.** `FlowPilot.registerCustomScreen(...)` accepts and stores the definition, but the renderer never looks it up or mounts the component. Treat the custom-screen types as a roadmap API. For native UI inside a flow today, use a [custom component](/expo-sdk/custom-components), which is fully rendered.
</Warning>

## The registration API (for forward compatibility)

The shape mirrors custom components, plus screen-level context. Registering now is harmless and keys your code to the eventual contract, but nothing renders yet.

```tsx theme={null}
import { FlowPilot } from '@flowpilotjs/react-native-sdk';
import { MyNativeScreen } from './MyNativeScreen';

FlowPilot.registerCustomScreen('native_paywall_screen', {
  inputs: {
    plan: 'string',
    is_trial: 'boolean',
  },
  outputs: {
    purchased: { description: 'User purchased', payload: { product_id: 'string' } },
    skipped: { description: 'User skipped' },
  },
  component: ({ props, context }) => {
    const plan = (props.inputs.plan as string) ?? 'monthly';
    return (
      <MyNativeScreen
        plan={plan}
        onPurchased={(id) => context.emit('purchased', { product_id: id })}
        onSkip={() => context.emit('skipped')}
      />
    );
  },
});
```

### What a custom screen would receive

Custom screens use `CustomScreenRenderProps`, which extends the custom-component context with screen-level capabilities:

```ts theme={null}
interface CustomScreenRenderProps {
  props: {
    inputs: Record<string, VariableValue>;
  };
  context: {
    // Inherited from the custom-component context
    containerSize: { width: number; height: number };
    containerConstraints: { /* min/max width/height, supportsIntrinsicSize */ };
    emit(eventName: string, payload?: Record<string, unknown>): void;

    // Screen-specific
    screenId: string;
    setZonesVisible(visible: boolean): void; // show/hide persistent nav bar, footer, overlay
  };
}
```

`setZonesVisible(false)` would let a custom screen take over the full surface by hiding the flow's persistent zones; `emit(...)` would fire output events the editor wires to navigation, exactly like custom components.

## Use a custom component instead, for now

Anything you would build as a custom screen can be built today as a custom component that fills the screen. Place it as the only component on an otherwise-empty screen node, bind its inputs, and wire its emitted events in the editor.

```tsx theme={null}
FlowPilot.registerCustomComponent('full_screen_paywall', {
  inputs: { plan: 'string' },
  outputs: { purchased: { payload: { product_id: 'string' } }, skipped: {} },
  component: ({ props, context }) => (
    <MyNativeScreen
      plan={(props.inputs.plan as string) ?? 'monthly'}
      onPurchased={(id) => context.emit('purchased', { product_id: id })}
      onSkip={() => context.emit('skipped')}
    />
  ),
});
```

See [Custom components](/expo-sdk/custom-components) for the full, working pattern.

## Common mistakes

* **Expecting `registerCustomScreen` to render.** It stores the definition but nothing mounts it in this build. Use a custom component.
* **Building around `setZonesVisible` today.** It is part of the not-yet-active custom-screen context. To control zones now, configure them in the editor.

## Related pages

* [Custom components and actions](/expo-sdk/custom-components)
* [Custom components (editor)](/editor/custom-components)
* [Persistent UI zones (editor)](/editor/zones)
* [API reference](/expo-sdk/api-reference)
