@getrheo/rheo-skill 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @getrheo/rheo-skill
2
2
 
3
- Current release: **`2.3.0`** on npm (`PLATFORM_SDK_VERSION` in `scripts/publish-package-registry.mjs`). Public source: [getrheo/rheo-skill](https://github.com/getrheo/rheo-skill) (mirrored from this private monorepo via `pnpm extract:oss-repos`).
3
+ Current release: **`2.6.0`** on npm (`PLATFORM_SDK_VERSION` in `scripts/publish-package-registry.mjs`). Public source: [getrheo/rheo-skill](https://github.com/getrheo/rheo-skill) (mirrored from this private monorepo via `pnpm extract:oss-repos`).
4
4
 
5
5
  Source and build tooling for the **`rheo`** agent skill — a single, self-contained
6
6
  skill with two sub-skills:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getrheo/rheo-skill",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "type": "module",
5
5
  "description": "Rheo agent skill — SDK install guidance and flow manifest import tooling.",
6
6
  "main": "./src/index.ts",
@@ -9,8 +9,8 @@
9
9
  ".": "./src/index.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@getrheo/contracts": "2.4.0",
13
- "@getrheo/flow-runtime": "2.4.0",
12
+ "@getrheo/contracts": "2.6.0",
13
+ "@getrheo/flow-runtime": "2.6.0",
14
14
  "zod": "^3.23.8"
15
15
  },
16
16
  "devDependencies": {
package/rheo/SKILL.md CHANGED
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: rheo
3
- description: Work with Rheo, the headless onboarding/paywall flow engine for mobile apps. Use when a user wants to install or wire the Rheo SDK (React Native, Expo, or SwiftUI), follow Rheo SDK best practices, configure integrations (RevenueCat, AppsFlyer), wire auth/permissions/terminal callbacks, OR import/migrate an existing mobile flow into a compliant Rheo FlowManifest and validate it. Routes to the `rheo-best-practices` and `rheo-flow-import` sub-skills.
3
+ description: Work with Rheo, the headless onboarding/paywall flow engine for mobile apps. Use when a user wants to install or wire the Rheo SDK (React Native, Expo, or SwiftUI), follow Rheo SDK best practices, configure integrations (RevenueCat, Superwall, AppsFlyer), wire auth/permissions/terminal callbacks, OR import/migrate an existing mobile flow into a compliant Rheo FlowManifest and validate it. Routes to the `rheo-best-practices` and `rheo-flow-import` sub-skills.
4
4
  compatibility: Requires Node.js 20+. rheo-flow-import scripts are fully self-contained (no install step). Internet access fetches the latest Manifest Agent Profile; a bundled fallback works offline.
5
5
  metadata:
6
- rheo-version: "2.4.0"
6
+ rheo-version: "2.6.0"
7
7
  manifest-schema-version: "7"
8
8
  ---
9
9
 
@@ -15,7 +15,7 @@ Rheo is a headless flow engine: a hosted dashboard authors onboarding, paywall,
15
15
 
16
16
  | The user wants to… | Use sub-skill | Read |
17
17
  |--------------------|---------------|------|
18
- | Install the Rheo SDK, wire `Flow`/`FlowView`, follow SDK best practices, configure RevenueCat / AppsFlyer / auth / permissions / terminal callbacks, or implement Rheo in an existing app | **rheo-best-practices** | [rheo-best-practices/SKILL.md](rheo-best-practices/SKILL.md) |
18
+ | Install the Rheo SDK, wire `Flow`/`FlowView`, follow SDK best practices, configure RevenueCat / Superwall / AppsFlyer / auth / permissions / terminal callbacks, or implement Rheo in an existing app | **rheo-best-practices** | [rheo-best-practices/SKILL.md](rheo-best-practices/SKILL.md) |
19
19
  | Analyze an existing mobile onboarding/paywall/setup flow and export it as a compliant Rheo `FlowManifest` (or validate/repair a manifest) | **rheo-flow-import** | [rheo-flow-import/SKILL.md](rheo-flow-import/SKILL.md) |
20
20
 
21
21
  If a request spans both (e.g. "import my onboarding **and** wire the SDK"), run **rheo-flow-import** to produce the manifest first, then **rheo-best-practices** to implement the SDK — they are independent and can be done in sequence.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rheo-best-practices
3
- description: Install and wire the Rheo SDK in a host app and follow Rheo implementation best practices. Use when a user asks to install Rheo, add @getrheo/react-native-expo or @getrheo/react-native-bare or RheoSwiftUI, wrap a flow host in RheoProvider, render Flow/FlowView, wire terminal callbacks, configure RevenueCat or AppsFlyer integrations, wire OAuth or email/password auth callbacks, request OS permissions, or add in-app review. Part of the `rheo` skill.
3
+ description: Install and wire the Rheo SDK in a host app and follow Rheo implementation best practices. Use when a user asks to install Rheo, add @getrheo/react-native-expo or @getrheo/react-native-bare or RheoSwiftUI, wrap a flow host in RheoProvider, render Flow/FlowView, wire terminal callbacks, configure RevenueCat, Superwall, or AppsFlyer integrations, wire OAuth or email/password auth callbacks, request OS permissions, or add in-app review. Part of the `rheo` skill.
4
4
  ---
5
5
 
6
6
  # Rheo — Best Practices (SDK implementation)
@@ -30,7 +30,8 @@ Only install packages or edit host code when the user explicitly asks for implem
30
30
  - **Pass the channel public id**, not a flow id, to `Flow` / `FlowView`.
31
31
  - **Preserve the existing onboarding** as a fallback/rollback path (feature flag or route swap) unless the user explicitly asks to remove it.
32
32
  - **Read local conventions first** (package manager, navigation, env handling) and keep edits localized to the integration entry point and app config.
33
- - **RevenueCat and AppsFlyer are host integrations**, not SDK peers — the host configures and owns those SDKs and their secrets. Wire `fallback` for every external surface.
33
+ - **RevenueCat, Superwall, and AppsFlyer are host integrations**, not SDK peers — the host configures and owns those SDKs and their secrets. Wire `fallback` for every Integration / External Surface Node.
34
+ - **External Surface Nodes** need a host `externalSurfaces` registry keyed by Host key (`config.hostKey` or `surf_*` id; callbacks `onComplete` / `onBack` / `onDismiss`). No App settings toggle.
34
35
  - **Do not add `request_app_review`** prompts unless the user explicitly asks; Apple discourages prompting from raw button taps.
35
36
  - Run the **narrowest useful verification** (typecheck or a build of the touched module), not a full app build, unless asked.
36
37
 
@@ -15,7 +15,7 @@ Use this when the user explicitly asks to install or wire Rheo in a host app.
15
15
  6. Replace or gate the existing onboarding entry with the Rheo runtime component.
16
16
  7. Preserve old onboarding as a fallback/rollback path unless explicitly told to remove it.
17
17
  8. Wire terminal callbacks to continue host navigation.
18
- 9. Install **`@getrheo/react-native-expo`** or **`@getrheo/react-native-bare`** with all required peers (see platform reference). Wire optional auth, RevenueCat, AppsFlyer (host packages only), and resolve fallback when used.
18
+ 9. Install **`@getrheo/react-native-expo`** or **`@getrheo/react-native-bare`** with all required peers (see platform reference). Wire optional auth, RevenueCat, Superwall, AppsFlyer (host packages only), and resolve fallback when used.
19
19
  10. When `request_app_review` is present, tell the user TestFlight/production may not show prompts every tap and builder preview always advances as `not_shown`.
20
20
  11. Run the narrowest useful verification.
21
21
 
@@ -1,12 +1,19 @@
1
1
  # Integrations
2
2
 
3
- ## RevenueCat
3
+ In the flow builder, partner paywalls and host UI are **two add-menu nodes** that share the `externalSurfaceNodes` schema:
4
+
5
+ | Builder node | Manifest `config.provider` | App settings toggle |
6
+ | --- | --- | --- |
7
+ | **Integration Node** | `revenuecat`, `superwall` (and future partners) | Required |
8
+ | **External Surface Node** | `headless` | None (host registry) |
9
+
10
+ ## RevenueCat (Integration Node)
4
11
 
5
12
  Detect source calls such as `Purchases.configure`, `react-native-purchases`, `react-native-purchases-ui`, or existing paywall presentation code.
6
13
 
7
14
  Manifest mapping:
8
15
 
9
- - Create an external surface with `config.provider: "revenuecat"`.
16
+ - Create an **Integration Node** / external surface with `config.provider: "revenuecat"`.
10
17
  - Preserve offering or placement identifiers when visible in source.
11
18
  - Wire known outcomes:
12
19
  - `purchase_completed`
@@ -17,6 +24,50 @@ Manifest mapping:
17
24
 
18
25
  The host remains responsible for configuring RevenueCat. Rheo does not own purchase SDK secrets or receipt validation.
19
26
 
27
+ ## Superwall (Integration Node)
28
+
29
+ Detect source calls such as `Superwall.configure`, `SuperwallProvider`, `expo-superwall`, `@superwall/react-native-superwall`, or `register(placement:)` / `registerPlacement`.
30
+
31
+ Manifest mapping:
32
+
33
+ - Create an **Integration Node** with `config.provider: "superwall"`.
34
+ - Preserve the placement id from the Superwall dashboard / source.
35
+ - Wire the same IAP outcomes as RevenueCat (`purchase_completed`, `restore_completed`, `purchase_cancelled`, `dismissed`, `failed`).
36
+ - Always wire `fallback`.
37
+
38
+ The host remains responsible for configuring Superwall. Rheo registers the placement and maps dismiss / skip / error callbacks to normalized outcomes. Skip / holdout / already-entitled paths map to `dismissed`.
39
+
40
+ ## External Surface Node (headless host UI)
41
+
42
+ Use when a source screen is owned by the host (custom native UI, third-party screen Rheo does not ship) rather than a Rheo layer tree or a partner paywall.
43
+
44
+ Manifest mapping:
45
+
46
+ - Create an **External Surface Node** with `config.provider: "headless"`.
47
+ - Keep a stable `surf_*` id for graph routing / analytics. Optionally set `config.hostKey` for the host `externalSurfaces` registry (defaults to the node id).
48
+ - Wire outcomes:
49
+ - `completed` ← host `onComplete`
50
+ - `back` ← host `onBack`
51
+ - `dismissed` ← host `onDismiss`
52
+ - `failed` ← missing host component (SDK)
53
+ - Always wire `fallback`.
54
+
55
+ Host wiring (required for success):
56
+
57
+ ```ts
58
+ // React Native — key matches Host key (hostKey or surf_* id)
59
+ <Flow
60
+ channelId="…"
61
+ externalSurfaces={{
62
+ onboardingQuiz: ({ onComplete, onBack, onDismiss }) => /* host UI */,
63
+ }}
64
+ />
65
+ ```
66
+
67
+ SwiftUI / Flutter: pass the same map on `FlowView` as `externalSurfaces` (builders receive `onComplete` / `onBack` / `onDismiss`). Docs: product Developer Guide → Headless external surfaces.
68
+
69
+ Do **not** use an External Surface Node to wrap RevenueCat or Superwall when you need `iap_purchase` commerce events — use an Integration Node with `provider: "revenuecat"` or `provider: "superwall"`.
70
+
20
71
  ## AppsFlyer
21
72
 
22
73
  Detect `react-native-appsflyer` or Swift attribution setup. Do not include AppsFlyer secrets in manifests.
@@ -15,7 +15,7 @@ pnpm add @getrheo/react-native-bare \
15
15
  react-native-safe-area-context react-native-in-app-review react-native-video
16
16
  ```
17
17
 
18
- **Integrations (host only):** `react-native-appsflyer`, `react-native-purchases`, `react-native-purchases-ui` when needed.
18
+ **Integrations (host only):** `react-native-appsflyer`, `react-native-purchases`, `react-native-purchases-ui`, `@superwall/react-native-superwall` when needed. External Surface Nodes use `Flow` `externalSurfaces` (no extra native peer).
19
19
 
20
20
  ## Minimal Runtime
21
21
 
@@ -24,7 +24,13 @@ import { Flow, RheoProvider } from '@getrheo/react-native-bare';
24
24
 
25
25
  export const OnboardingHost = () => (
26
26
  <RheoProvider config={{ publishableKey: '…', userId: '…' }}>
27
- <Flow channelId="ch_…" onFlowCompleted={() => {}} />
27
+ <Flow
28
+ channelId="ch_…"
29
+ onFlowCompleted={() => {}}
30
+ externalSurfaces={{
31
+ // surf_*: ({ onComplete, onBack, onDismiss }) => host UI
32
+ }}
33
+ />
28
34
  </RheoProvider>
29
35
  );
30
36
  ```
@@ -15,7 +15,7 @@ pnpm add @getrheo/react-native-expo \
15
15
  react-native-safe-area-context expo-store-review expo-video
16
16
  ```
17
17
 
18
- **Integrations (host only, not SDK peers):** `react-native-appsflyer`, `react-native-purchases`, `react-native-purchases-ui` when the flow uses attribution or RevenueCat paywalls.
18
+ **Integrations (host only, not SDK peers):** `react-native-appsflyer`, `react-native-purchases`, `react-native-purchases-ui`, `expo-superwall` / `@superwall/react-native-superwall` when the flow uses attribution, RevenueCat, or Superwall Integration Nodes. External Surface Nodes use `Flow` / `useFlow` `externalSurfaces` (no extra native peer).
19
19
 
20
20
  ## Minimal Runtime
21
21
 
@@ -46,4 +46,4 @@ export const OnboardingHost = () => (
46
46
  - Pass channel public id, not flow id.
47
47
  - **Production:** default API is `https://api.getrheo.io`; omit `apiBaseUrl` unless self-hosting. Never use localhost with `ob_pk_live_*` keys.
48
48
  - Built-in OS permissions need `react-native-permissions` native setup (Expo plugin + Info.plist).
49
- - Expo Go cannot run native RevenueCat UI; use a dev client.
49
+ - Expo Go cannot run native RevenueCat or Superwall UI; use a dev client.
@@ -16,6 +16,7 @@ Optional products:
16
16
 
17
17
  ```swift
18
18
  .product(name: "RheoSwiftUIRevenueCat", package: "RheoSwiftUI")
19
+ .product(name: "RheoSwiftUISuperwall", package: "RheoSwiftUI")
19
20
  .product(name: "RheoSwiftUIAppsFlyer", package: "RheoSwiftUI")
20
21
  ```
21
22
 
@@ -46,7 +47,9 @@ struct OnboardingHost: View {
46
47
 
47
48
  ## Notes
48
49
 
49
- - Use `RheoSwiftUIRevenueCat` for RevenueCat external surface presenter helpers.
50
+ - Use `RheoSwiftUIRevenueCat` for RevenueCat Integration Node presenter helpers.
51
+ - Use `RheoSwiftUISuperwall` for Superwall Integration Node presenter helpers.
52
+ - External Surface Nodes: pass `externalSurfaces: [surfId: { ctx in AnyView(...) }]` on `FlowView` (`ctx.onComplete` / `onBack` / `onDismiss`).
50
53
  - Use `RheoSwiftUIAppsFlyer` for AppsFlyer attribution providers.
51
54
  - Host apps must include Info.plist usage strings for authored permission prompts.
52
55
  - Host apps must register branding fonts if relying on downloaded font families.
@@ -38,11 +38,11 @@ Fix workflow:
38
38
 
39
39
  ## Missing Fallback Edge
40
40
 
41
- Every external surface needs `fallback`. RevenueCat outcomes that are not explicitly mapped fall through to this target.
41
+ Every Integration / External Surface Node needs `fallback`. Outcomes that are not explicitly mapped (RevenueCat / Superwall purchase outcomes or headless `completed` / `back` / `dismissed`) fall through to this target.
42
42
 
43
43
  ## Integration Disabled
44
44
 
45
- The manifest may validate locally but fail dashboard import if the target app has RevenueCat disabled or the workspace lacks integration entitlements.
45
+ The manifest may validate locally but fail dashboard import if the target app has RevenueCat / Superwall disabled or the workspace lacks integration entitlements.
46
46
 
47
47
  ## Wrong Environment
48
48
 
@@ -27,6 +27,12 @@ Every layer `kind` accepted by the manifest:
27
27
  - `text_input`
28
28
  - `scale_input`
29
29
  - `wheel_picker`
30
+ - `date_time_input`
31
+ - `number_stepper`
32
+ - `number_stepper_button`
33
+ - `number_stepper_value`
34
+ - `phone_input`
35
+ - `address_input`
30
36
  - `oauth_provider`
31
37
  - `oauth_login`
32
38
  - `email_password_auth`
@@ -111,7 +117,12 @@ Valid `permissionKey` values for `request_os_permission`:
111
117
  - `email_password_auth` modes: `sign_in`, `sign_up` (sign_up requires email + password + confirm fields).
112
118
  - `icon` families: `ionicons`.
113
119
 
114
- ## External surface outcomes (RevenueCat)
120
+ ## External surface outcomes
115
121
 
116
- Normalized outcome keys for `externalSurfaceNodes[].outcomes`: `purchase_completed`, `purchase_cancelled`, `dismissed`, `failed`, `restore_completed`.
117
- Every external surface also needs a `fallback` jump target.
122
+ Builder add-menu kinds share `externalSurfaceNodes`: **Integration Node** (partner providers such as RevenueCat / Superwall) and **External Surface Node** (`provider: "headless"`). Every node needs a `fallback` jump target.
123
+
124
+ **Integration Node / RevenueCat** (`provider: "revenuecat"`): `purchase_completed`, `purchase_cancelled`, `dismissed`, `failed`, `restore_completed`.
125
+
126
+ **Integration Node / Superwall** (`provider: "superwall"`): `purchase_completed`, `purchase_cancelled`, `dismissed`, `failed`, `restore_completed`.
127
+
128
+ **External Surface Node / Headless** (`provider: "headless"`): `completed`, `back`, `dismissed`, `failed`. Host apps register UI via `externalSurfaces[hostKey]` (`config.hostKey` or node id) with `onComplete` / `onBack` / `onDismiss`.
@@ -199,7 +199,8 @@ instead of a plain footer CTA ([carousel-import.md](carousel-import.md)).
199
199
  ## Decisions and external surfaces
200
200
 
201
201
  `decisions` accepts full `@getrheo/contracts` `DecisionNode` objects (the scaffold
202
- passes them through). RevenueCat paywalls use `externalSurfaces`:
202
+ passes them through). External surfaces use `externalSurfaces` (builder:
203
+ **Integration Node** for `revenuecat` / `superwall`, **External Surface Node** for `headless`):
203
204
 
204
205
  ```jsonc
205
206
  {
@@ -208,7 +209,26 @@ passes them through). RevenueCat paywalls use `externalSurfaces`:
208
209
  "offeringId": "default",
209
210
  "presentation": "paywall",
210
211
  "outcomes": { "purchase_completed": "scr_done", "restore_completed": "scr_done", "dismissed": "scr_offer2" },
211
- "fallback": "scr_offer2" // required
212
+ "fallback": "scr_offer2" // required — Integration Node
213
+ }
214
+ ```
215
+
216
+ ```jsonc
217
+ {
218
+ "id": "surf_sw_paywall",
219
+ "provider": "superwall",
220
+ "placementId": "campaign_trigger",
221
+ "outcomes": { "purchase_completed": "scr_done", "restore_completed": "scr_done", "dismissed": "scr_offer2" },
222
+ "fallback": "scr_offer2" // required — Integration Node; placementId optional (uses app defaultPlacementId)
223
+ }
224
+ ```
225
+
226
+ ```jsonc
227
+ {
228
+ "id": "surf_custom_step",
229
+ "provider": "headless",
230
+ "outcomes": { "completed": "scr_done", "back": "scr_welcome", "dismissed": "scr_offer2" },
231
+ "fallback": "scr_offer2" // required — External Surface Node; host registers externalSurfaces.surf_custom_step
212
232
  }
213
233
  ```
214
234
 
@@ -109,7 +109,7 @@ If the user has not named an entry point, stop after question 1 and wait for an
109
109
  18. Generate `rheo-import.manifest.json`:
110
110
  - Emit a complete graph with explicit `next.default` edges.
111
111
  - Use decision nodes for clear branches.
112
- - Use RevenueCat external surfaces for detected RevenueCat paywalls.
112
+ - Use RevenueCat / Superwall **Integration Nodes** for detected partner paywalls (`provider: "revenuecat"` or `"superwall"`).
113
113
  - Prefer fidelity when the user chose visual fidelity: carousels, gradients, shadows, and centered stacks.
114
114
  - **Layer ids:** `scr_*` / `lyr_*` only on screens and layers; UUID placeholders **only** for `media.mediaAssetId` and font sidecars ([layer-schema-pitfalls.md](layer-schema-pitfalls.md#layer-ids-vs-media-placeholder-uuids)).
115
115
  - **Container layers:** every `button`, `back_button`, `hyperlink`, `stack`, choice input, and auth layer must include its `children` (or `slides`) array ([manifest-rules.md](manifest-rules.md#container-layers-required-children)).
@@ -67,7 +67,7 @@ Use only: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_b
67
67
  - Black-and-white fallback is acceptable only when the audit finds no style/token evidence and the user confirms no theme source.
68
68
  - Use at most one input layer kind per **active path** (`single_choice`, `multiple_choice`, `text_input`, `scale_input`, `wheel_picker`) — one per screen unless sibling `conditional` branches split the path.
69
69
  - Non-reserved `sdk.*` decision keys must be listed in `sdkAttributeKeys`.
70
- - RevenueCat paywalls are external surface nodes and always need `fallback`.
70
+ - RevenueCat / Superwall **Integration Nodes** and headless **External Surface Nodes** both live in `externalSurfaceNodes` and always need `fallback`.
71
71
  - Emit complete graph edges for imported flows.
72
72
  - Use placeholder UUID media ids and `rheo-import.assets.json`; never put file paths directly in `mediaAssetId`.
73
73
  - Do not silently drop media layers. If a traced asset cannot be copied, report the missing file and do not call the import complete.
@@ -195,9 +195,13 @@ Use `conditional` when the source renders different content on **one** screen ba
195
195
 
196
196
  ## External Surfaces
197
197
 
198
- - RevenueCat paywalls become `externalSurfaceNodes` with provider `revenuecat`.
199
- - Every external surface needs a `fallback`.
200
- - Map known paywall outcomes to `purchase_completed`, `restore_completed`, `dismissed`, and `failed`.
198
+ In the builder UI these are two add-menu kinds sharing `externalSurfaceNodes`:
199
+
200
+ - **Integration Node** — RevenueCat / Superwall paywalls become nodes with provider `revenuecat` or `superwall`.
201
+ - **External Surface Node** — Host-owned custom screens become nodes with provider `headless` (stable `surf_*` id; optional `config.hostKey` for the host `externalSurfaces` registry).
202
+ - Every node needs a `fallback`.
203
+ - Map paywall outcomes to `purchase_completed`, `restore_completed`, `dismissed`, and `failed`.
204
+ - Map headless outcomes to `completed`, `back`, `dismissed`, and `failed`.
201
205
 
202
206
  ## Assets
203
207
 
@@ -45,9 +45,10 @@ These mirror `apps/web/src/features/builder/validateFlow.ts` and API `preflightP
45
45
 
46
46
  ### Integrations (default: enabled)
47
47
 
48
- - External surfaces need `config.provider` (not `unspecified`).
48
+ - External surfaces need `config.provider` (not `unspecified`). Integration Nodes use partner providers such as `revenuecat` or `superwall`; External Surface Nodes use `headless`.
49
49
  - Every external surface needs `fallback`.
50
- - RevenueCat surfaces require RevenueCat integration enabled (import assumes enabled).
50
+ - RevenueCat / Superwall surfaces require the matching integration enabled (import assumes enabled).
51
+ - External Surface Nodes (`provider: "headless"`) do not require an App settings toggle; the host must supply `externalSurfaces`.
51
52
 
52
53
  ### Canvas editor gates (default: all enabled)
53
54
 
@@ -83,15 +83,18 @@ Paging is swipe by default; map the pager's own next button to a `button` with
83
83
  ## Integrations and native steps
84
84
 
85
85
  - `react-native-purchases` / `react-native-purchases-ui` / `Purchases.configure`
86
- / a `<Paywall>` → a RevenueCat **external surface** (`provider: "revenuecat"`,
87
- required `fallback`). See [integrations](../../rheo-best-practices/references/integrations.md).
86
+ / a `<Paywall>` → a RevenueCat **Integration Node** (`provider: "revenuecat"`,
87
+ required `fallback`). `expo-superwall` / `@superwall/react-native-superwall` /
88
+ `registerPlacement` → a Superwall **Integration Node** (`provider: "superwall"`,
89
+ required `fallback`). Host-owned custom screens → an **External Surface Node**
90
+ (`provider: "headless"`). See [integrations](../../rheo-best-practices/references/integrations.md).
88
91
  - `react-native-appsflyer` → represent stable attribution branches via decision
89
- nodes; add keys to `sdkAttributeKeys`. Never include AppsFlyer/RevenueCat secrets.
92
+ nodes; add keys to `sdkAttributeKeys`. Never include AppsFlyer/RevenueCat/Superwall secrets.
90
93
  - OAuth / email-password screens → `oauth_login` / `email_password_auth` (host
91
94
  owns the actual auth logic).
92
95
  - `react-native-permissions` prompts → a `request_os_permission` button action.
93
96
  - Signature pads, camera capture, custom WebViews → confirm with the user whether
94
- to keep native (host-owned) or approximate; flag unmappable behavior in chat.
97
+ to keep native (External Surface Node / host-owned) or approximate; flag unmappable behavior in chat.
95
98
 
96
99
  ## i18n
97
100
 
@@ -80,8 +80,11 @@ page. Paging is swipe by default; an explicit Next button becomes a `button` wit
80
80
  ## Integrations and native steps
81
81
 
82
82
  - RevenueCat (`Purchases.configure`, `RevenueCatUI` `PaywallView`, `.presentPaywall`)
83
- → a RevenueCat **external surface** (`provider: "revenuecat"`, required
84
- `fallback`). See [integrations](../../rheo-best-practices/references/integrations.md).
83
+ → a RevenueCat **Integration Node** (`provider: "revenuecat"`, required
84
+ `fallback`). Superwall (`Superwall.configure`, `register(placement:)`)
85
+ → a Superwall **Integration Node** (`provider: "superwall"`, required
86
+ `fallback`). Host-owned custom screens → an **External Surface Node**
87
+ (`provider: "headless"`). See [integrations](../../rheo-best-practices/references/integrations.md).
85
88
  - AppsFlyer (`AppsFlyerLib`) → represent stable attribution branches via decision
86
89
  nodes; add keys to `sdkAttributeKeys`. Never include secrets.
87
90
  - "Sign in with Apple" (`SignInWithAppleButton`) / OAuth / email-password →
@@ -90,7 +93,7 @@ page. Paging is swipe by default; an explicit Next button becomes a `button` wit
90
93
  `UNUserNotificationCenter`) → a `request_os_permission` button action; the host
91
94
  must declare the matching `Info.plist` usage strings.
92
95
  - `PencilKit` signature, camera capture, custom `WKWebView` → confirm whether to
93
- keep native (host-owned) or approximate; flag unmappable behavior in chat.
96
+ keep native (External Surface Node / host-owned) or approximate; flag unmappable behavior in chat.
94
97
 
95
98
  ## Localization
96
99