@getrheo/rheo-skill 2.6.0 → 3.0.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 +17 -12
- package/package.json +7 -5
- package/rheo/SKILL.md +20 -11
- package/rheo/rheo-best-practices/SKILL.md +32 -19
- package/rheo/rheo-best-practices/examples/swiftui-install-snippet.md +3 -1
- package/rheo/rheo-best-practices/examples/web-install-snippet.md +26 -0
- package/rheo/rheo-best-practices/references/analytics.md +104 -0
- package/rheo/rheo-best-practices/references/engage.md +95 -0
- package/rheo/rheo-best-practices/references/implement-workflow.md +20 -15
- package/rheo/rheo-best-practices/references/integrations.md +24 -3
- package/rheo/rheo-best-practices/references/product-model.md +66 -0
- package/rheo/rheo-best-practices/references/react-native-bare.md +2 -0
- package/rheo/rheo-best-practices/references/react-native-expo.md +3 -2
- package/rheo/rheo-best-practices/references/react-web.md +78 -0
- package/rheo/rheo-best-practices/references/swiftui.md +20 -51
- package/rheo/rheo-best-practices/references/troubleshooting.md +13 -0
- package/rheo/rheo-flow-import/SKILL.md +4 -2
- package/rheo/rheo-flow-import/references/capabilities.md +1 -0
- package/rheo/rheo-flow-import/scripts/lib/rheo-cli.mjs +2289 -53
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Product model
|
|
2
|
+
|
|
3
|
+
Rheo is one SDK and one Customer. Analytics, Convert, and Engage are products on that SDK. Install once. Wire only the products the user asked for.
|
|
4
|
+
|
|
5
|
+
| Product | Host implements | Dashboard owns |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| **Analytics** | `RheoProvider` (sessions, page or screen views, `logEvent`), web consent, `setUserId`, `setBillingIdentity` | Visitors, retention, revenue reports |
|
|
8
|
+
| **Convert** | `Flow` / `FlowView` on a **channel** public id, terminal callbacks, Integration Nodes and External Surface Nodes | Canvas, experiments, channels, publish |
|
|
9
|
+
| **Engage** | `identify` for email and marketing consent. `track` for automation triggers on web and React Native | Email provider, broadcasts, automations, preference center |
|
|
10
|
+
| **Customers** | A stable `userId`, plus `identify` when email or consent exists | Profiles, segments, consent |
|
|
11
|
+
|
|
12
|
+
Customers are the shared record. The same id filters Analytics and targets Engage. Segments are dashboard (or CLI) objects. Do not invent a second user id per product.
|
|
13
|
+
|
|
14
|
+
## One provider
|
|
15
|
+
|
|
16
|
+
Mount `RheoProvider` once, high enough that the screens you care about sit under it. Product analytics starts when the provider mounts, including when no flow is on screen. A Convert-only request still gets Analytics unless the user opts out with `analytics={{ enabled: false }}` (web and React Native) or `analyticsEnabled: false` (SwiftUI `RheoConfig`).
|
|
17
|
+
|
|
18
|
+
Do not add a second product-analytics SDK, a second onboarding SDK, or a Rheo-owned email sender.
|
|
19
|
+
|
|
20
|
+
## Three event pipes
|
|
21
|
+
|
|
22
|
+
These are different APIs. Sending a product event does not start an automation.
|
|
23
|
+
|
|
24
|
+
| Call | Where it goes | Starts Engage automations |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| Flow funnel events (`flow_started`, `step_viewed`, …) | `POST /v1/sdk/events` | No |
|
|
27
|
+
| `logEvent`, `screen`, automatic `session_start` / `page_view` / `first_visit` / `first_open` | `POST /v1/sdk/analytics/events` | No |
|
|
28
|
+
| `track` (web and React Native) | `POST /v1/sdk/track` | Yes |
|
|
29
|
+
|
|
30
|
+
Use `logEvent` when the event should show up in Analytics. Use `track` only when that event should enroll an Engage automation or match a segment rule. Call both only when the user asked for a report and a journey from the same action.
|
|
31
|
+
|
|
32
|
+
`unknown` marketing consent does not send. Granted consent is required for live email and webhook delivery; email also needs an address. See [engage.md](engage.md).
|
|
33
|
+
|
|
34
|
+
## Identity
|
|
35
|
+
|
|
36
|
+
| Input | Sets | Does not set |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| `userId` on provider config | `appUserId` for analytics, experiment bucketing, and identify | Email or consent |
|
|
39
|
+
| `setUserId` / `customUserId` | CRM id on later product events | `appUserId` |
|
|
40
|
+
| `identify` | Email, marketing consent, optional topic consents on the Customer | A product-analytics event |
|
|
41
|
+
| `setBillingIdentity('revenuecat' \| 'superwall', id)` | Billing id used to attach webhook revenue to this person | A purchase by itself |
|
|
42
|
+
|
|
43
|
+
Email typed into a flow, or stuffed into event properties, is not marketing consent. Call `identify` after the person actually opts in or opts out.
|
|
44
|
+
|
|
45
|
+
When email is sent, `marketingConsent` is required (`granted`, `denied`, or `unknown`). `granted` requires an email.
|
|
46
|
+
|
|
47
|
+
Web and React Native `identify` also accept `attributes` (shallow-merged onto the Customer) and an IANA `timezone` for Engage quiet hours. SwiftUI `RheoRuntime.identify` takes email, consent, topic consents, and `customUserId` only.
|
|
48
|
+
|
|
49
|
+
## Revenue
|
|
50
|
+
|
|
51
|
+
Dollars come from the provider webhook, not from the device. After the host calls RevenueCat `logIn` / `Purchases.configure` or Superwall `identify`, call `setBillingIdentity` with that same id. Stripe on the web SDK records the charge from `checkout.session.completed` on the app webhook. There is no `setBillingIdentity('stripe', …)`.
|
|
52
|
+
|
|
53
|
+
One revenue source per store. App Store and Play are RevenueCat or Superwall. Web can be Stripe.
|
|
54
|
+
|
|
55
|
+
## Platforms this skill installs
|
|
56
|
+
|
|
57
|
+
| Stack | Package | Analytics | Convert | `identify` | Engage `track` |
|
|
58
|
+
| --- | --- | --- | --- | --- | --- |
|
|
59
|
+
| React Native + Expo | `@getrheo/react-native-expo` | Yes | Yes | Yes | Yes |
|
|
60
|
+
| React Native bare | `@getrheo/react-native-bare` | Yes | Yes | Yes | Yes |
|
|
61
|
+
| React web | `@getrheo/react` | Yes, consent required | Yes | Yes | Yes |
|
|
62
|
+
| SwiftUI | `RheoSwiftUI` | Yes | Yes | Yes | No |
|
|
63
|
+
|
|
64
|
+
Install one React Native flavor, never both. The web package is separate and can sit beside a native app. It is not a second flavor of the same binary.
|
|
65
|
+
|
|
66
|
+
Flutter exposes product analytics and `identify` in `rheo_flutter`. This skill has no Flutter install guide. Engage push and outbound webhooks are not SDK surfaces yet. Engage email sends through the app's own SES, Resend, Postmark, or SendGrid account, configured in the dashboard.
|
|
@@ -38,5 +38,7 @@ export const OnboardingHost = () => (
|
|
|
38
38
|
## Notes
|
|
39
39
|
|
|
40
40
|
- Do **not** install `@getrheo/react-native-expo` in the same app.
|
|
41
|
+
- `RheoProvider` starts Analytics even when `Flow` is omitted. Pass a channel public id only for Convert, never a flow id.
|
|
42
|
+
- `logEvent` / `screen` / `setUserId` / `setBillingIdentity` are Analytics. `identify` and `track` are Engage. Same exports as Expo. See [analytics.md](analytics.md) and [engage.md](engage.md).
|
|
41
43
|
- **Production:** default API is `https://api.getrheo.io`; omit `apiBaseUrl` unless self-hosting.
|
|
42
44
|
- Link native modules (permissions, video, reanimated babel plugin) per upstream docs.
|
|
@@ -12,7 +12,7 @@ pnpm add @getrheo/react-native-expo \
|
|
|
12
12
|
react-native-permissions react-native-gesture-handler react-native-reanimated \
|
|
13
13
|
react-native-linear-gradient react-native-svg lottie-react-native \
|
|
14
14
|
react-native-vector-icons @react-native-async-storage/async-storage \
|
|
15
|
-
react-native-safe-area-context expo-store-review expo-video
|
|
15
|
+
react-native-safe-area-context expo-store-review expo-video expo-notifications
|
|
16
16
|
```
|
|
17
17
|
|
|
18
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).
|
|
@@ -43,7 +43,8 @@ export const OnboardingHost = () => (
|
|
|
43
43
|
## Notes
|
|
44
44
|
|
|
45
45
|
- Do **not** install `@getrheo/react-native-bare` in the same app.
|
|
46
|
-
- Pass channel public id,
|
|
46
|
+
- `RheoProvider` starts Analytics even when `Flow` is omitted. Pass a channel public id only for Convert, never a flow id.
|
|
47
|
+
- `logEvent` / `screen` / `setUserId` / `setBillingIdentity` are Analytics. `identify` and `track` are Engage. See [analytics.md](analytics.md) and [engage.md](engage.md).
|
|
47
48
|
- **Production:** default API is `https://api.getrheo.io`; omit `apiBaseUrl` unless self-hosting. Never use localhost with `ob_pk_live_*` keys.
|
|
48
49
|
- Built-in OS permissions need `react-native-permissions` native setup (Expo plugin + Info.plist).
|
|
49
50
|
- Expo Go cannot run native RevenueCat or Superwall UI; use a dev client.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# React web
|
|
2
|
+
|
|
3
|
+
## Detect
|
|
4
|
+
|
|
5
|
+
A browser app: `react` and `react-dom`, often Vite, Next.js, or Remix. No `react-native` dependency.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @getrheo/react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Peers: `react` and `react-dom` ≥ 18.
|
|
14
|
+
|
|
15
|
+
## Minimal runtime
|
|
16
|
+
|
|
17
|
+
Analytics-only (no flow). Consent stays pending until the site grants it. See [analytics.md](analytics.md).
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { RheoProvider } from '@getrheo/react';
|
|
21
|
+
|
|
22
|
+
export const App = () => (
|
|
23
|
+
<RheoProvider
|
|
24
|
+
config={{
|
|
25
|
+
publishableKey: import.meta.env.VITE_RHEO_PUBLISHABLE_KEY,
|
|
26
|
+
analytics: { consent: 'pending' },
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</RheoProvider>
|
|
31
|
+
);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Convert: same provider, plus `Flow` and a channel public id. Add the site origin (scheme, host, and port) under **App settings → SDK**. A browser request from an origin the app did not list is rejected.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Flow, RheoProvider } from '@getrheo/react';
|
|
38
|
+
|
|
39
|
+
export const App = () => (
|
|
40
|
+
<RheoProvider
|
|
41
|
+
config={{
|
|
42
|
+
publishableKey: import.meta.env.VITE_RHEO_PUBLISHABLE_KEY,
|
|
43
|
+
analytics: { consent: 'pending' },
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<Flow channelId="ch_…" />
|
|
47
|
+
</RheoProvider>
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Production:** omit `apiBaseUrl` unless self-hosting. Default API is `https://api.getrheo.io`. Never pair `ob_pk_live_*` with localhost.
|
|
52
|
+
|
|
53
|
+
The snippet uses Vite's `import.meta.env`. Next.js should read `NEXT_PUBLIC_…` (or the project's existing public env) instead.
|
|
54
|
+
|
|
55
|
+
## Payments
|
|
56
|
+
|
|
57
|
+
Stripe is the web paywall. Turn **Stripe** on under **App settings → Integrations**, add a Stripe Integration Node whose Payment Link is on `buy.stripe.com` or another `https://*.stripe.com` host, and paste Rheo's webhook URL and signing secret into Stripe. No Stripe adapter on `RheoProvider`. The return restores the session. The webhook writes the charge. The browser does not send a price.
|
|
58
|
+
|
|
59
|
+
## Engage
|
|
60
|
+
|
|
61
|
+
`identify` and `track` export from `@getrheo/react`. Call `identify` after a real marketing opt-in. Use `track` for automation or segment triggers. An email typed into a flow answer is not consent. See [engage.md](engage.md).
|
|
62
|
+
|
|
63
|
+
`registerPush()` registers Web Push after you save a VAPID key under **App settings → Engage settings**.
|
|
64
|
+
|
|
65
|
+
## Prefetch
|
|
66
|
+
|
|
67
|
+
Pass `prefetch="all"` or `prefetch={['ch_…']}` on `RheoProvider`, or call `prefetch` / `prefetchAll` / `useRheoPrefetch` to warm the resolve cache (`localStorage` + `If-None-Match`).
|
|
68
|
+
|
|
69
|
+
## What the web SDK does not do
|
|
70
|
+
|
|
71
|
+
| Feature | Web behavior |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| RevenueCat / Superwall / headless external surfaces | Surface fails and follows **Fallback** |
|
|
74
|
+
| `request_os_permission` other than notifications | Treated as denied |
|
|
75
|
+
| `request_app_review` | No-op (`not_shown`) |
|
|
76
|
+
| AppsFlyer | Not supported. First-party UTMs are on by default (`attribution.enabled` not `false`) |
|
|
77
|
+
|
|
78
|
+
First-touch UTMs stay in memory while consent is pending or denied. `setAnalyticsConsent('granted')` writes them.
|
|
@@ -1,55 +1,24 @@
|
|
|
1
1
|
# SwiftUI
|
|
2
2
|
|
|
3
|
+
## Status: SDK install coming soon
|
|
4
|
+
|
|
5
|
+
**Do not install** a SwiftUI SDK package for customers today. Public Swift extract / SwiftPM distribution is paused until the native SDK GA checklist is satisfied. Marketing and the Developer Guide treat SwiftUI as **coming soon**.
|
|
6
|
+
|
|
7
|
+
If the user asks to install Rheo in a SwiftUI app:
|
|
8
|
+
|
|
9
|
+
1. Say SwiftUI SDK install is **not customer-available** yet.
|
|
10
|
+
2. Offer supported install stacks instead: Expo, bare React Native, or React web (see those references).
|
|
11
|
+
3. If they have an existing SwiftUI onboarding/paywall to migrate into Convert, route to **rheo-flow-import** (SwiftUI **source → manifest** import is supported; it does not install the SDK).
|
|
12
|
+
|
|
3
13
|
## Detect
|
|
4
14
|
|
|
5
|
-
Look for `Package.swift`, `.xcodeproj`, `.xcworkspace`, SwiftUI `App`, `NavigationStack`, onboarding root views, and coordinators.
|
|
6
|
-
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Optional products:
|
|
16
|
-
|
|
17
|
-
```swift
|
|
18
|
-
.product(name: "RheoSwiftUIRevenueCat", package: "RheoSwiftUI")
|
|
19
|
-
.product(name: "RheoSwiftUISuperwall", package: "RheoSwiftUI")
|
|
20
|
-
.product(name: "RheoSwiftUIAppsFlyer", package: "RheoSwiftUI")
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Minimal Runtime
|
|
24
|
-
|
|
25
|
-
```swift
|
|
26
|
-
import SwiftUI
|
|
27
|
-
import RheoSwiftUI
|
|
28
|
-
|
|
29
|
-
struct OnboardingHost: View {
|
|
30
|
-
var body: some View {
|
|
31
|
-
RheoProvider(
|
|
32
|
-
config: RheoConfig(
|
|
33
|
-
publishableKey: "ob_pk_test_xxx",
|
|
34
|
-
userId: "user_123",
|
|
35
|
-
sessionId: "sess_123"
|
|
36
|
-
)
|
|
37
|
-
) {
|
|
38
|
-
FlowView(channelId: "ch_test_xxx") { snapshot in
|
|
39
|
-
// Continue host navigation.
|
|
40
|
-
} onFlowAbandoned: { snapshot in
|
|
41
|
-
// Continue or restore host navigation.
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Notes
|
|
49
|
-
|
|
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`).
|
|
53
|
-
- Use `RheoSwiftUIAppsFlyer` for AppsFlyer attribution providers.
|
|
54
|
-
- Host apps must include Info.plist usage strings for authored permission prompts.
|
|
55
|
-
- Host apps must register branding fonts if relying on downloaded font families.
|
|
15
|
+
Look for `Package.swift`, `.xcodeproj`, `.xcworkspace`, SwiftUI `App`, `NavigationStack`, onboarding root views, and coordinators — useful for **flow import**, not for SDK install.
|
|
16
|
+
|
|
17
|
+
## Historical snippet (not for install)
|
|
18
|
+
|
|
19
|
+
The file [examples/swiftui-install-snippet.md](../examples/swiftui-install-snippet.md) is retained for internal / future GA reference only. **Do not** add `RheoSwiftUI` SwiftPM products or edit the host app to mount `RheoProvider` / `FlowView` until GA docs flip from coming soon.
|
|
20
|
+
|
|
21
|
+
## Engage notes (when GA lands)
|
|
22
|
+
|
|
23
|
+
- SwiftUI will not export Engage `track` (same as web). Automation triggers must come from React Native or from events the app already sends that Engage can enroll on.
|
|
24
|
+
- Push registration and billing identity helpers are documented in [engage.md](engage.md) / [integrations.md](integrations.md) for when the package is customer-installable.
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Troubleshooting
|
|
2
2
|
|
|
3
|
+
## Analytics shows no product events
|
|
4
|
+
|
|
5
|
+
- Confirm `RheoProvider` is mounted. Sessions start there, not when `Flow` mounts.
|
|
6
|
+
- On web, omitted consent is `pending`. Call `setAnalyticsConsent('granted')` or pass `analytics.consent: 'granted'` when a grant already exists. `analytics.enabled: false` stays off after a grant.
|
|
7
|
+
- `logEvent` before the provider mounts is a no-op. `track` does not write product analytics.
|
|
8
|
+
|
|
9
|
+
## An Engage automation never enrolls
|
|
10
|
+
|
|
11
|
+
- `logEvent` and flow events do not start automations. React Native must call `track`.
|
|
12
|
+
- SwiftUI and web do not export Engage `track`.
|
|
13
|
+
- `identify` with `unknown` or missing email does not make the person sendable. Consent has to be `granted`.
|
|
14
|
+
- Provider credentials, suppressions, and topic grants are dashboard state. The SDK cannot repair them.
|
|
15
|
+
|
|
3
16
|
## Manifest Fails Validation
|
|
4
17
|
|
|
5
18
|
Run:
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rheo-flow-import
|
|
3
|
-
description: Analyze an existing mobile
|
|
3
|
+
description: Analyze an existing mobile Convert flow (onboarding, paywall, post-purchase, setup) in a React Native, Expo, or SwiftUI codebase and export it as a compliant Rheo FlowManifest, then validate it against the dashboard publish gates. Use when a user asks to import, migrate, or convert an existing flow into Rheo, generate or scaffold a Rheo manifest, or validate/repair a Rheo manifest. Part of the `rheo` skill. Does not install the SDK or configure Analytics or Engage. Ships self-contained node scripts — no install step.
|
|
4
4
|
compatibility: Requires Node.js 20+. All scripts are self-contained (zod, @getrheo/contracts, and @getrheo/flow-runtime are bundled into scripts/lib/rheo-cli.mjs). Internet access fetches the latest Manifest Agent Profile; a bundled fallback works offline.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Rheo — Flow Import
|
|
8
8
|
|
|
9
|
-
Convert an existing
|
|
9
|
+
This is the **Convert** path. It turns an existing onboarding, paywall, post-purchase, or setup flow into a Rheo `FlowManifest` that imports and publishes in the dashboard with zero blockers. It does not install the SDK, record product analytics, or configure Engage. When the user also wants the app wired, finish the manifest, then follow [rheo-best-practices](../rheo-best-practices/SKILL.md).
|
|
10
|
+
|
|
11
|
+
Prefer **source code as truth**; use screenshots/recordings only as supporting evidence unless the user says they are newer.
|
|
10
12
|
|
|
11
13
|
The recommended authoring path is **spec → scaffold → enrich → validate**: describe the flow as a compact [flow spec](references/flow-spec.md), run `scaffold-manifest.mjs` to get a schema-valid skeleton with correct ids/structure, then enrich styling and validate. Hand-authoring full manifest JSON is allowed but error-prone — the scaffold removes the mechanical mistakes (ids, `children` arrays, choice bindings, branching).
|
|
12
14
|
|
|
@@ -74,6 +74,7 @@ Valid `action.kind` values on `button` layers:
|
|
|
74
74
|
- `play_media`
|
|
75
75
|
- `request_app_review`
|
|
76
76
|
- `advance_carousel`
|
|
77
|
+
- `dismiss_banner`
|
|
77
78
|
|
|
78
79
|
- `FlowGraphNodeJumpTarget` (`scr_*` | `dec_*` | `surf_*`): `go_to_step.screenId`, choice `branching.conditions[].goTo`, loader/lottie/video `onComplete` when mode is `screen`, and `request_os_permission` outcomes (except `continue`/`end`).
|
|
79
80
|
- `go_back_one_screen` and `back_button` accept optional `fallbackScreenId` (`scr_*` only).
|