@getrheo/rheo-skill 1.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 +76 -0
- package/package.json +51 -0
- package/rheo/SKILL.md +32 -0
- package/rheo/rheo-best-practices/SKILL.md +46 -0
- package/rheo/rheo-best-practices/examples/react-native-install-snippet.md +23 -0
- package/rheo/rheo-best-practices/examples/swiftui-install-snippet.md +20 -0
- package/rheo/rheo-best-practices/references/implement-workflow.md +27 -0
- package/rheo/rheo-best-practices/references/integrations.md +51 -0
- package/rheo/rheo-best-practices/references/react-native-bare.md +36 -0
- package/rheo/rheo-best-practices/references/react-native-expo.md +49 -0
- package/rheo/rheo-best-practices/references/swiftui.md +52 -0
- package/rheo/rheo-best-practices/references/troubleshooting.md +57 -0
- package/rheo/rheo-flow-import/SKILL.md +68 -0
- package/rheo/rheo-flow-import/examples/branching-onboarding.manifest.json +155 -0
- package/rheo/rheo-flow-import/examples/flow-spec.example.json +56 -0
- package/rheo/rheo-flow-import/examples/linear-onboarding.manifest.json +104 -0
- package/rheo/rheo-flow-import/examples/revenuecat-paywall.manifest.json +154 -0
- package/rheo/rheo-flow-import/references/animation-import.md +79 -0
- package/rheo/rheo-flow-import/references/capabilities.md +107 -0
- package/rheo/rheo-flow-import/references/carousel-import.md +64 -0
- package/rheo/rheo-flow-import/references/flow-spec.md +214 -0
- package/rheo/rheo-flow-import/references/font-import.md +67 -0
- package/rheo/rheo-flow-import/references/import-workflow.md +240 -0
- package/rheo/rheo-flow-import/references/layer-schema-pitfalls.md +179 -0
- package/rheo/rheo-flow-import/references/localization-import.md +128 -0
- package/rheo/rheo-flow-import/references/manifest-agent-profile-fallback.md +74 -0
- package/rheo/rheo-flow-import/references/manifest-rules.md +197 -0
- package/rheo/rheo-flow-import/references/publish-gates.md +91 -0
- package/rheo/rheo-flow-import/references/react-native-source-patterns.md +99 -0
- package/rheo/rheo-flow-import/references/swiftui-source-patterns.md +99 -0
- package/rheo/rheo-flow-import/scripts/audit-import.mjs +4 -0
- package/rheo/rheo-flow-import/scripts/audit-publish-manifest.mjs +4 -0
- package/rheo/rheo-flow-import/scripts/fetch-profile.mjs +4 -0
- package/rheo/rheo-flow-import/scripts/lib/rheo-cli.mjs +12753 -0
- package/rheo/rheo-flow-import/scripts/normalize-manifest.mjs +4 -0
- package/rheo/rheo-flow-import/scripts/print-manifest-summary.mjs +4 -0
- package/rheo/rheo-flow-import/scripts/scaffold-manifest.mjs +4 -0
- package/rheo/rheo-flow-import/scripts/validate-manifest.mjs +4 -0
- package/src/index.ts +32 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Reading React Native / Expo flows
|
|
2
|
+
|
|
3
|
+
How to trace an existing onboarding/paywall/setup flow in a React Native or Expo
|
|
4
|
+
codebase and map each source construct to a Rheo manifest concept. Run
|
|
5
|
+
`node scripts/audit-import.mjs --entry <entry>` first — this guide explains how
|
|
6
|
+
to interpret and extend its findings.
|
|
7
|
+
|
|
8
|
+
## Find the entry point
|
|
9
|
+
|
|
10
|
+
| Signal | Where |
|
|
11
|
+
|--------|-------|
|
|
12
|
+
| Expo Router | `app/onboarding.tsx`, `app/(onboarding)/_layout.tsx`, `app/(auth)/...` route groups |
|
|
13
|
+
| React Navigation | `createNativeStackNavigator`, `<Stack.Navigator>`, an `OnboardingStack`/`OnboardingNavigator` |
|
|
14
|
+
| Manual gate | A root component branching on `hasOnboarded` / `firstLaunch` from storage |
|
|
15
|
+
| Names | `Onboarding*`, `Welcome*`, `Paywall*`, `Intro*`, `Setup*`, `Step*` screens/components |
|
|
16
|
+
|
|
17
|
+
Ask the user to confirm the entry file if it is not obvious; do not guess.
|
|
18
|
+
|
|
19
|
+
## Map step order and navigation → screens + edges
|
|
20
|
+
|
|
21
|
+
- Each navigator screen or routed page → one Rheo **screen** (`scr_*`).
|
|
22
|
+
- `navigation.navigate('Next')`, `router.push('/next')`, `setStep(step + 1)`,
|
|
23
|
+
index into a `steps[]` array, or a `<Pager>` page change → a `next.default`
|
|
24
|
+
edge to the next screen.
|
|
25
|
+
- A "Continue"/"Next" button that advances → a `button` with `action: "continue"`.
|
|
26
|
+
- "Skip" → `action: "skip"`; finishing/closing the flow → `action: "end_flow"`.
|
|
27
|
+
- Conditional navigation (`if (plan === 'pro') navigate('X')`, A/B flags, platform
|
|
28
|
+
checks, stored answers) → a **decision node**, with the keys added to
|
|
29
|
+
`sdkAttributeKeys` when they are `sdk.*` attributes.
|
|
30
|
+
|
|
31
|
+
## Map UI primitives → layers
|
|
32
|
+
|
|
33
|
+
| React Native source | Rheo layer |
|
|
34
|
+
|---------------------|------------|
|
|
35
|
+
| `<Text>`, `<Heading>`, typography components | `text` (copy in `text.default`, color in `style.color`) |
|
|
36
|
+
| `<Image source={require(...)}>`, `<ImageBackground>`, `expo-image` | `image` with `media.mediaAssetId` (bundle the asset) |
|
|
37
|
+
| `lottie-react-native` `<LottieView>` | `lottie` |
|
|
38
|
+
| `react-native-video` / `expo-video` | `video` |
|
|
39
|
+
| `<Pressable>`/`<TouchableOpacity>` acting as CTA | `button` (label = nested `text` child) |
|
|
40
|
+
| Header back chevron / close (`<HeaderBackButton>`, a back `Pressable` in a top bar) | `back_button` in `regions.header`, `icon.family: "ionicons"`, no `action` |
|
|
41
|
+
| `<View style={{ flexDirection, alignItems, gap }}>` | `stack` (`direction`, `align`, `justify`, `gap`) |
|
|
42
|
+
| Vector icons (`react-native-vector-icons`, `@expo/vector-icons` Ionicons) | `icon` (`family: "ionicons"`) |
|
|
43
|
+
| External `Linking.openURL(...)` / `<A href>` | `hyperlink` |
|
|
44
|
+
| Progress bar / step dots tied to step index | `progress` (header) |
|
|
45
|
+
|
|
46
|
+
Hero images that render through wrapper components (`<Illustration>`, `<Logo>`,
|
|
47
|
+
`<Mascot>`, `<Avatar>`) are easy to miss — follow the component to its `require`.
|
|
48
|
+
|
|
49
|
+
## Inputs and choices
|
|
50
|
+
|
|
51
|
+
- Selectable option grids/lists (mapped `options.map(...)` with a `selected`
|
|
52
|
+
state and a `selected ? styleA : styleB` ternary) → `single_choice` /
|
|
53
|
+
`multiple_choice`. Each option becomes an option `stack`; map the unselected
|
|
54
|
+
branch to `style` and the selected branch to `selectedStyle`.
|
|
55
|
+
- `<TextInput>` collecting a value → `text_input` with a snake_case `fieldKey`;
|
|
56
|
+
mark password/email/PII as `classification: "sensitive"`.
|
|
57
|
+
- Sliders / rating rows → `scale_input`. Consent toggles → `checkbox`.
|
|
58
|
+
- Screens with a manual-submit input need a `continue` button.
|
|
59
|
+
|
|
60
|
+
## Theme, colors, gradients, fonts
|
|
61
|
+
|
|
62
|
+
- Style tokens live in NativeWind/Tailwind config, `theme.ts`, design-token
|
|
63
|
+
files, `StyleSheet.create`, or shared `Button`/`Text`/`Screen` primitives. Map
|
|
64
|
+
primary/background/foreground/accent into `manifest.theme`.
|
|
65
|
+
- `expo-linear-gradient` / `react-native-linear-gradient` →
|
|
66
|
+
`screen.containerStyle.backgroundFill.color` as a `linear-gradient(...)` CSS
|
|
67
|
+
string. NativeWind classes like `bg-red-600 text-white` → solid screen fill +
|
|
68
|
+
`#FFFFFF` text color.
|
|
69
|
+
- `expo-font` `useFonts(...)` / `Font.loadAsync(...)` / Tailwind `fontFamily` →
|
|
70
|
+
custom fonts. Copy the `.ttf`/`.otf` files and emit `rheo-import.fonts.json`;
|
|
71
|
+
set `manifest.theme.fontFamily` ([font-import.md](font-import.md)).
|
|
72
|
+
|
|
73
|
+
## Carousels / pagers
|
|
74
|
+
|
|
75
|
+
`react-native-pager-view`, a `FlatList horizontal pagingEnabled`, a
|
|
76
|
+
`ScrollView horizontal` snap pager, `Animated` `translateX` paging, or an
|
|
77
|
+
`infoSteps`/`currentStep` index → `kind: "carousel"` with one slide per page.
|
|
78
|
+
Carousels are swipe-only; do not turn the pager's own next button into a footer
|
|
79
|
+
button ([carousel-import.md](carousel-import.md)).
|
|
80
|
+
|
|
81
|
+
## Integrations and native steps
|
|
82
|
+
|
|
83
|
+
- `react-native-purchases` / `react-native-purchases-ui` / `Purchases.configure`
|
|
84
|
+
/ a `<Paywall>` → a RevenueCat **external surface** (`provider: "revenuecat"`,
|
|
85
|
+
required `fallback`). See [integrations](../../rheo-best-practices/references/integrations.md).
|
|
86
|
+
- `react-native-appsflyer` → represent stable attribution branches via decision
|
|
87
|
+
nodes; add keys to `sdkAttributeKeys`. Never include AppsFlyer/RevenueCat secrets.
|
|
88
|
+
- OAuth / email-password screens → `oauth_login` / `email_password_auth` (host
|
|
89
|
+
owns the actual auth logic).
|
|
90
|
+
- `react-native-permissions` prompts → a `request_os_permission` button action.
|
|
91
|
+
- Signature pads, camera capture, custom WebViews → confirm with the user whether
|
|
92
|
+
to keep native (host-owned) or approximate; flag unmappable behavior in chat.
|
|
93
|
+
|
|
94
|
+
## i18n
|
|
95
|
+
|
|
96
|
+
`i18next`/`react-i18next` (`t('key')`), `react-intl` (`formatMessage`), Lingui, or
|
|
97
|
+
locale JSON under `locales/` → resolve each key against the **default-locale**
|
|
98
|
+
JSON and put the resolved string in `text.default` (never the raw key). Set
|
|
99
|
+
`manifest.defaultLocale` ([localization-import.md](localization-import.md)).
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Reading SwiftUI flows
|
|
2
|
+
|
|
3
|
+
How to trace an existing onboarding/paywall/setup flow in a SwiftUI codebase and
|
|
4
|
+
map each source construct to a Rheo manifest concept. Run
|
|
5
|
+
`node scripts/audit-import.mjs --entry <entry>` first (point `--entry` at the root
|
|
6
|
+
onboarding view or coordinator) — this guide explains how to interpret findings.
|
|
7
|
+
|
|
8
|
+
## Find the entry point
|
|
9
|
+
|
|
10
|
+
| Signal | Where |
|
|
11
|
+
|--------|-------|
|
|
12
|
+
| App root | `@main struct …App: App`, the root `WindowGroup` view that branches on a stored `hasOnboarded` flag (`@AppStorage`, `UserDefaults`) |
|
|
13
|
+
| Navigation | `NavigationStack { … }` with a `path` binding, `NavigationLink`, or a coordinator pushing views |
|
|
14
|
+
| Step state | A `@State`/`@Published` step index or an `enum OnboardingStep` switched in the body |
|
|
15
|
+
| Names | `Onboarding*View`, `Welcome*View`, `Paywall*View`, `Intro*`, `Setup*`, `*Coordinator` |
|
|
16
|
+
|
|
17
|
+
Ask the user to confirm the entry view/coordinator if it is not obvious.
|
|
18
|
+
|
|
19
|
+
## Map step order and navigation → screens + edges
|
|
20
|
+
|
|
21
|
+
- Each pushed view / `enum` case / `TabView` page → one Rheo **screen** (`scr_*`).
|
|
22
|
+
- `path.append(...)`, `NavigationLink(value:)`, `step += 1`, `withAnimation { step = .next }`,
|
|
23
|
+
or a `selection` change in a paging `TabView` → a `next.default` edge.
|
|
24
|
+
- A primary "Continue"/"Get Started" `Button` that advances → `button` with
|
|
25
|
+
`action: "continue"`; "Skip" → `"skip"`; dismissing/finishing → `"end_flow"`.
|
|
26
|
+
- `if`/`switch` on a stored value, entitlement, A/B flag, or `#if os(...)` that
|
|
27
|
+
changes the next view → a **decision node**; add `sdk.*` keys to `sdkAttributeKeys`.
|
|
28
|
+
|
|
29
|
+
## Map SwiftUI views → layers
|
|
30
|
+
|
|
31
|
+
| SwiftUI source | Rheo layer |
|
|
32
|
+
|----------------|------------|
|
|
33
|
+
| `Text(...)`, `Label` text | `text` (copy in `text.default`, color in `style.color`) |
|
|
34
|
+
| `Image("asset")`, `AsyncImage`, `Image(uiImage:)` from the asset catalog | `image` with `media.mediaAssetId` (bundle the asset) |
|
|
35
|
+
| Lottie via `lottie-ios` (`LottieView`/`AnimationView`) | `lottie` |
|
|
36
|
+
| `VideoPlayer` / `AVPlayer` | `video` |
|
|
37
|
+
| `Button { … } label: { … }` acting as CTA | `button` (label = nested `text` child) |
|
|
38
|
+
| Toolbar back/close (`.toolbar { ToolbarItem(placement: .navigationBarLeading) }`, a chevron `Button`) | `back_button` in `regions.header`, `icon.family: "ionicons"`, no `action` |
|
|
39
|
+
| `VStack`/`HStack`/`ZStack` with `spacing`, `alignment` | `stack` (`direction`, `align`, `justify`, `gap`) |
|
|
40
|
+
| SF Symbol `Image(systemName:)` | `icon` — **remap to a valid `ionicons` name** (SF Symbols are not allowed on `icon`) |
|
|
41
|
+
| `Link(destination:)` / `openURL` | `hyperlink` |
|
|
42
|
+
| `ProgressView(value:)` / step dots | `progress` (header) |
|
|
43
|
+
|
|
44
|
+
Custom view structs (`HeroIllustration`, `LogoView`, `MascotView`) often wrap the
|
|
45
|
+
real asset — follow the struct to its `Image("…")` to find the asset name.
|
|
46
|
+
|
|
47
|
+
## Inputs and choices
|
|
48
|
+
|
|
49
|
+
- A list/grid of selectable option views with `@State var selected` and a
|
|
50
|
+
`selected == option ? colorA : colorB` modifier → `single_choice` /
|
|
51
|
+
`multiple_choice`. Each option becomes an option `stack`; map the unselected
|
|
52
|
+
modifiers to `style` and the selected modifiers to `selectedStyle`.
|
|
53
|
+
- `TextField`/`SecureField` → `text_input` with a snake_case `fieldKey`
|
|
54
|
+
(`SecureField` / email / PII → `classification: "sensitive"`).
|
|
55
|
+
- `Slider` / star rating → `scale_input`. `Toggle` consent → `checkbox`.
|
|
56
|
+
- Manual-submit input screens need a `continue` button.
|
|
57
|
+
|
|
58
|
+
## Theme, colors, gradients, fonts
|
|
59
|
+
|
|
60
|
+
- Style tokens live in `Color` extensions / an asset-catalog color set, `Font`
|
|
61
|
+
extensions, and reusable `ButtonStyle`/`ViewModifier` types. Map primary/
|
|
62
|
+
background/foreground/accent into `manifest.theme`.
|
|
63
|
+
- `LinearGradient(gradient:startPoint:endPoint:)` used as a background →
|
|
64
|
+
`screen.containerStyle.backgroundFill.color` as a `linear-gradient(...)` CSS
|
|
65
|
+
string. A solid `.background(Color("Brand"))` → solid screen fill + matching
|
|
66
|
+
text color.
|
|
67
|
+
- Custom fonts registered in `Info.plist` (`UIAppFonts`) and used via
|
|
68
|
+
`.font(.custom("Name", size:))` → copy the font files, emit
|
|
69
|
+
`rheo-import.fonts.json`, and set `manifest.theme.fontFamily`
|
|
70
|
+
([font-import.md](font-import.md)).
|
|
71
|
+
|
|
72
|
+
## Carousels / pagers
|
|
73
|
+
|
|
74
|
+
A paging `TabView { … }.tabViewStyle(.page)`, a horizontal `ScrollView` with snap
|
|
75
|
+
paging, or an `infoSteps`/`currentStep` index → `kind: "carousel"`, one slide per
|
|
76
|
+
page, swipe-only (no in-pager button) ([carousel-import.md](carousel-import.md)).
|
|
77
|
+
|
|
78
|
+
## Integrations and native steps
|
|
79
|
+
|
|
80
|
+
- RevenueCat (`Purchases.configure`, `RevenueCatUI` `PaywallView`, `.presentPaywall`)
|
|
81
|
+
→ a RevenueCat **external surface** (`provider: "revenuecat"`, required
|
|
82
|
+
`fallback`). See [integrations](../../rheo-best-practices/references/integrations.md).
|
|
83
|
+
- AppsFlyer (`AppsFlyerLib`) → represent stable attribution branches via decision
|
|
84
|
+
nodes; add keys to `sdkAttributeKeys`. Never include secrets.
|
|
85
|
+
- "Sign in with Apple" (`SignInWithAppleButton`) / OAuth / email-password →
|
|
86
|
+
`oauth_login` / `email_password_auth` (host owns the auth logic).
|
|
87
|
+
- Permission prompts (`AVCaptureDevice.requestAccess`, `CLLocationManager`,
|
|
88
|
+
`UNUserNotificationCenter`) → a `request_os_permission` button action; the host
|
|
89
|
+
must declare the matching `Info.plist` usage strings.
|
|
90
|
+
- `PencilKit` signature, camera capture, custom `WKWebView` → confirm whether to
|
|
91
|
+
keep native (host-owned) or approximate; flag unmappable behavior in chat.
|
|
92
|
+
|
|
93
|
+
## Localization
|
|
94
|
+
|
|
95
|
+
`String(localized:)`, `Text("key")` resolved from `Localizable.strings`/
|
|
96
|
+
`.xcstrings`, or `NSLocalizedString` → resolve each key against the
|
|
97
|
+
**default-locale** strings file and put the resolved string in `text.default`
|
|
98
|
+
(never the raw key). Set `manifest.defaultLocale`
|
|
99
|
+
([localization-import.md](localization-import.md)).
|