Skip to main content
The cache covers a user who has seen a flow before. For a user’s first launch with no network, you need the flow shipped inside the app. A bundled default flow is Tier 3 of the fail-safe chain: when a live resolve fails and there is no usable cache, the SDK renders a flow you bundled, so onboarding still runs offline.

Bundle a flow’s JSON

Unlike iOS (which loads a bundle resource by name), React Native has no “bundle resource by name” lookup. Pass the flow JSON directly, typically require('./flows/onboarding.json') (Metro inlines it as a plain object). Declare it at configure time:
FlowPilot.configure({
  apiKey: 'fp_live_...',
  appId: 'your-app-id',
  bundledFlows: {
    onboarding: require('./flows/onboarding.json'),
  },
});
Or register one at runtime (for flows loaded after configuration):
FlowPilot.registerBundledFlow('onboarding', require('./flows/onboarding.json'));
The JSON can be a full resolve-response envelope exported from the editor (preferred, because it carries the media/icon base URLs and font manifest) or a bare flow definition. Both snake_case and camelCase keys are tolerated, and a thunk (() => object | null) is accepted for lazy loading.
A bundled flow’s JSON renders offline, but its remote images, Lucide icons, and custom fonts still hit the network and degrade to blank images / system fonts when offline, unless you also ship their bytes. Use the flowpilot-export CLI below to snapshot them, then register the asset bundle alongside the flow.

Export a fully-offline bundle with flowpilot-export

flowpilot-export snapshots a placement’s default flow (the deterministic default, not an A/B variant) plus its images, icons, and fonts into a self-contained .flowassets folder. Run it on a dev machine or in CI; it is never part of your app bundle.
npx flowpilot-export --env production --api-key fp_live_... --app-id <uuid> \
  --placement onboarding --out ./assets/OnboardingDefault.flowassets

Flags

FlagRequiredNotes
--api-key <key>yesWorkspace API key (fp_...).
--app-id <id>yesApp identifier (UUID).
--placement <key>yesPlacement key to export.
--out <dir>yesOutput .flowassets directory (created if missing).
--env <name>one of env/base-urldevelopment | staging | production (default production).
--base-url <url>one of env/base-urlFull API base URL, overrides --env.
--platform <p>noios | android | web (default ios).
-h, --helpnoShow usage.
The command writes flow.json, manifest.json, the downloaded asset files, and a generated index.ts that exports a ready-to-use asset bundle.

Exit codes

CodeMeaning
0Clean export.
1Fatal (resolve, decode, or write failed).
2Bad arguments.
3Partial export: some asset downloads failed, but the bundle is still usable. CI can flag this.

Register the exported bundle

The generated index.ts exports a named asset bundle (the command prints the exact name and a ready-to-paste snippet). Register it as the third argument to registerBundledFlow:
import { onboardingDefault } from './assets/OnboardingDefault.flowassets';

FlowPilot.registerBundledFlow(
  'onboarding',
  require('./assets/OnboardingDefault.flowassets/flow.json'),
  onboardingDefault,
);
Or declare both at configure time with bundledFlowAssets, keyed by the same placement key:
import { onboardingDefault } from './assets/OnboardingDefault.flowassets';

FlowPilot.configure({
  apiKey: 'fp_live_...',
  appId: 'your-app-id',
  bundledFlows: {
    onboarding: require('./assets/OnboardingDefault.flowassets/flow.json'),
  },
  bundledFlowAssets: {
    onboarding: onboardingDefault,
  },
});
You can also register assets on their own at runtime with FlowPilot.registerBundledFlowAssets('onboarding', onboardingDefault).

What an asset bundle is

A BundledFlowAssets is a manifest plus a resources map. The manifest lists the flow’s image/icon/font references; resources maps each manifest resource path to a require()’d Metro asset (a module number) or a local uri string. The exporter builds this for you; the shape if you author it by hand:
import type { BundledFlowAssets } from '@flowpilotjs/react-native-sdk';

const onboardingDefault: BundledFlowAssets = {
  manifest: {
    images: [{ url: 'https://cdn.flowpilot.io/ws/hero.png', resource: 'images/0-hero.png' }],
    icons: [{ url: 'https://cdn.flowpilot.io/icons/Star.svg', resource: 'icons/Star.svg' }],
    fonts: [{ family: 'Inter', weight: 700, resource: 'fonts/Inter-700.ttf' }],
  },
  resources: {
    'images/0-hero.png': require('./images/0-hero.png'),
    'icons/Star.svg': require('./icons/Star.svg'),
    'fonts/Inter-700.ttf': require('./fonts/Inter-700.ttf'),
  },
};
When a bundled flow renders offline, the SDK seeds these into its image, icon, and font caches before the first paint, so images and fonts render with no network. Seeding is best-effort: a missing or unreadable asset is logged and skipped, degrading to a blank image / system font rather than crashing. Icons survive offline because their raw SVG bytes are seeded into the icon cache.
The exporter and the runtime seeder share the same asset enumeration and URL resolution logic, so “what the export downloads” and “what the app looks up at render time” cannot drift out of sync.

Common mistakes

  • Bundling JSON but not assets. The flow renders offline, but images, icons, and fonts go blank or fall back to system fonts. Ship the .flowassets bundle too.
  • Pointing require at the wrong path. require('./assets/.../flow.json') must resolve at build time. Metro inlines it; a dynamic path will not work.
  • Expecting the export to include an A/B variant. The exporter snapshots the deterministic default flow only. Variants resolve live.
  • Ignoring exit code 3 in CI. A partial export still writes a usable bundle but some assets failed to download. Treat 3 as a warning to investigate.
  • Running flowpilot-export against development. It works, but make sure the placement has a published default flow on whatever environment you point at.

Troubleshooting

  • Offline render shows blank images. No asset bundle, or the manifest resource paths do not match the resources map keys. Re-export and register the generated bundle.
  • Fonts fall back to system offline. The font is not in the bundle’s fonts manifest. Re-run the export so it includes the font variants the flow uses.
  • flowpilot-export exits 2. A required flag is missing or --env is unknown. Run npx flowpilot-export --help.
  • flowpilot-export exits 1. Resolve/decode/write failed. Check the API key, app id, placement key, and that a default flow is published.