mapples 0.2.0-beta.5 → 0.2.0-beta.7

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.
Files changed (84) hide show
  1. package/README.md +42 -0
  2. package/dist/api/agent.d.ts +84 -0
  3. package/dist/api/agent.js +92 -0
  4. package/dist/api/agent.js.map +1 -0
  5. package/dist/api/client.d.ts +3 -0
  6. package/dist/api/client.js +2 -0
  7. package/dist/api/client.js.map +1 -1
  8. package/dist/api/commit.js +1 -0
  9. package/dist/api/commit.js.map +1 -1
  10. package/dist/api/errors.js +4 -2
  11. package/dist/api/errors.js.map +1 -1
  12. package/dist/api/objects.d.ts +12 -0
  13. package/dist/api/objects.js +2 -0
  14. package/dist/api/objects.js.map +1 -1
  15. package/dist/commands/agent.d.ts +2 -0
  16. package/dist/commands/agent.js +76 -0
  17. package/dist/commands/agent.js.map +1 -0
  18. package/dist/commands/create.js +1 -0
  19. package/dist/commands/create.js.map +1 -1
  20. package/dist/commands/impl/adoptImpl.js +3 -0
  21. package/dist/commands/impl/adoptImpl.js.map +1 -1
  22. package/dist/commands/impl/agentImpl.d.ts +10 -0
  23. package/dist/commands/impl/agentImpl.js +349 -0
  24. package/dist/commands/impl/agentImpl.js.map +1 -0
  25. package/dist/commands/impl/createImpl.js +19 -0
  26. package/dist/commands/impl/createImpl.js.map +1 -1
  27. package/dist/commands/impl/initImpl.js +19 -0
  28. package/dist/commands/impl/initImpl.js.map +1 -1
  29. package/dist/commands/impl/syncImpl.js +9 -3
  30. package/dist/commands/impl/syncImpl.js.map +1 -1
  31. package/dist/commands/init.js +1 -0
  32. package/dist/commands/init.js.map +1 -1
  33. package/dist/index.js +12 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/project/agentState.d.ts +24 -0
  36. package/dist/project/agentState.js +42 -0
  37. package/dist/project/agentState.js.map +1 -0
  38. package/dist/project/secret.d.ts +6 -2
  39. package/dist/project/secret.js +11 -5
  40. package/dist/project/secret.js.map +1 -1
  41. package/dist/services/agentInstall.d.ts +35 -0
  42. package/dist/services/agentInstall.js +180 -0
  43. package/dist/services/agentInstall.js.map +1 -0
  44. package/dist/services/agentLease.d.ts +2 -0
  45. package/dist/services/agentLease.js +32 -0
  46. package/dist/services/agentLease.js.map +1 -0
  47. package/dist/services/clientFactory.d.ts +2 -0
  48. package/dist/services/clientFactory.js +16 -1
  49. package/dist/services/clientFactory.js.map +1 -1
  50. package/dist/services/scaffold.js +4 -0
  51. package/dist/services/scaffold.js.map +1 -1
  52. package/dist/services/syncEngine.js +51 -18
  53. package/dist/services/syncEngine.js.map +1 -1
  54. package/dist/style/theme.js +17 -1
  55. package/dist/style/theme.js.map +1 -1
  56. package/dist/types.d.ts +2 -0
  57. package/dist/types.js.map +1 -1
  58. package/package.json +3 -3
  59. package/templates/app.json +0 -1
  60. package/templates/claude/CLAUDE.md +7 -0
  61. package/templates/claude/mapples.md +118 -0
  62. package/templates/claude/mcp.json +11 -0
  63. package/templates/claude/skills/mapples-conventions/SKILL.md +136 -0
  64. package/templates/claude/skills/mapples-design/SKILL.md +218 -0
  65. package/templates/claude/skills/mapples-design/reference/component-library.md +128 -0
  66. package/templates/claude/skills/mapples-design/reference/design-tokens.md +132 -0
  67. package/templates/claude/skills/mapples-design/reference/layout-contract.md +227 -0
  68. package/templates/claude/skills/mapples-design/reference/lint-checklist.md +51 -0
  69. package/templates/claude/skills/mapples-design/reference/plan.md +95 -0
  70. package/templates/claude/skills/mapples-design/reference/playbooks/empty-states.md +14 -0
  71. package/templates/claude/skills/mapples-design/reference/playbooks/forms-and-auth.md +22 -0
  72. package/templates/claude/skills/mapples-design/reference/playbooks/home-dashboard.md +14 -0
  73. package/templates/claude/skills/mapples-design/reference/playbooks/list-and-detail.md +18 -0
  74. package/templates/claude/skills/mapples-design/reference/playbooks/microcopy.md +20 -0
  75. package/templates/claude/skills/mapples-design/reference/playbooks/navigation-chrome.md +21 -0
  76. package/templates/claude/skills/mapples-design/reference/playbooks/onboarding-flow.md +15 -0
  77. package/templates/claude/skills/mapples-design/reference/playbooks/screen-flow-wiring.md +37 -0
  78. package/templates/claude/skills/mapples-design/reference/playbooks/settings-profile.md +16 -0
  79. package/templates/claude/skills/mapples-design/reference/playbooks/stats-and-progress.md +17 -0
  80. package/templates/claude/skills/mapples-design/reference/playbooks/visual-hierarchy.md +18 -0
  81. package/templates/claude/skills/mapples-design/reference/style-guides.md +92 -0
  82. package/templates/claude/skills/mapples-sync/SKILL.md +93 -0
  83. package/templates/gitignore +2 -0
  84. package/templates/package.json +12 -10
@@ -0,0 +1,227 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Layout contract — every screen
3
+
4
+ Ported from the Creator agent's system prompt (`agent/prompt.ts`: `LAYOUT_CONTRACT`,
5
+ `STYLE_MERGE_RULE`, the archetypes, the fonts rule). Vocabulary here is the file's: an element
6
+ is a JSX tag, `style` is `styled.style`, style slots are the other `styled` keys, and design
7
+ tokens are strings.
8
+
9
+ ## Fonts
10
+
11
+ Typography `fontFamily` values must be bundled family names — `"<Family>-<Weight>"` with
12
+ Family in {Inter, Manrope, DMSans, PlusJakartaSans, Poppins, Nunito, SpaceGrotesk, Sora,
13
+ Outfit, PlayfairDisplay, Fraunces, IBMPlexMono} and Weight in {Regular, Medium, SemiBold, Bold}
14
+ (serifs: Regular/SemiBold/Bold; IBMPlexMono: Regular/Medium) — e.g. `"Manrope-SemiBold"`.
15
+ Never "system", "Helvetica" or any other name: it will not render. Set `fontWeight` to match
16
+ the weight. On screens, fonts apply only through `Typography` variants — never set
17
+ `fontFamily` on an element.
18
+
19
+ ## The contract
20
+
21
+ - Design for the page's device (default 360×640 "phone"). Everything must fit that width;
22
+ vertical overflow goes inside a `ScrollView`.
23
+ - The root is a full-size column. Build with `Container` (flex: 1) and `View` (width 100%)
24
+ columns/rows — never give a layout container a fixed pixel width unless it is a card in a
25
+ horizontal row. Text elements carry no width; they stretch.
26
+ - Spacing comes from the sizing scale (4/8/12/16/24/32): screen padding 20–24, gap 12–16
27
+ between controls, 24–32 between groups. Use `gap`, not margins, between siblings. Prefer the
28
+ token strings (`'sizing.screenPadding'`, `'sizing.gap'`, `'sizing.lg'`).
29
+ - Scroll containers (`ScrollView`, `HorizontalScrollView`, `FlatList`, grids): gap/padding that
30
+ space the SCROLLING CHILDREN go in the `styled.contentContainerStyle` slot — on `style` they
31
+ are silently ignored. A horizontal card row is full-bleed with
32
+ `styled={{ contentContainerStyle: { gap: 12, paddingHorizontal: 20 } }}` so the first card
33
+ aligns with the screen padding and cards still scroll edge to edge.
34
+ - Hierarchy: one Headline, one supporting Body paragraph (≤ 2 lines of copy on phone),
35
+ secondary text in `theme.text.secondary`.
36
+ - EVERY piece of text is a `Typography` element with a `variant` (Headline, Subtitle, Body,
37
+ Caption, Overline, Button, Link, Label, Code) — the project type scale and fonts apply only
38
+ through variants. NEVER use the raw `Text` type on a screen: it ignores the design tokens and
39
+ breaks the design system. Colors likewise come from theme tokens, never hardcoded hex.
40
+ - Primary action: exactly one `Button` `{variant: "filled", size: "lg", fullWidth: true}` pinned
41
+ to the bottom with a parent column using `justifyContent: 'space-between'` and 24–32 of bottom
42
+ padding — on detail/checkout screens a `BottomActionBar` `{sticky: true}` holds it. Secondary
43
+ actions are `TextLink` or `Button` `{variant: "text"}` / `{variant: "outlined"}`. Touch
44
+ targets ≥ 44 high.
45
+ - Hero content (icon/illustration + title + body) is centered with `alignItems: 'center'` and
46
+ `textAlign: 'center'`; list/detail content is left-aligned.
47
+ - Safe areas: top padding ≥ 48 on the root (or a `SafeAreaView`), bottom ≥ 24.
48
+ - Cards: a `Card` element (variant elevated|filled|outlined; children are the body) or a
49
+ `MediaCard` for a photo-topped tile — never a hand-styled `View` pretending to be a card.
50
+ Images: width 100% with an explicit height (160–240) and `borderRadius`.
51
+ - Chrome (chips, pills, badges, breadcrumbs, in-content header rows) is CONTENT-SIZED — never
52
+ width 100% inside a row or a horizontal scroll. Use the library: `Chip` and `ChipGroup`
53
+ `{options, value}` for filters and tags, `Badge` for counts and status pills, `Breadcrumbs`
54
+ `{items}`, `TopAppBar` `{title, showBack, actions}` for an in-content header (only when the
55
+ stack header is hidden). Stack headers and tab bars are NAVIGATOR options set in Creator
56
+ (see `playbooks/navigation-chrome.md`), never hand-built elements — `BottomNavigationBar` and
57
+ `Tabs` are in-content widgets, not a substitute.
58
+ - Depth: the elevation language is a DESIGN-SYSTEM decision — the design instructions state it;
59
+ follow them exactly, and when they are silent default to RESTRAINT. Shadows are not what makes
60
+ a design modern: a flat design separated by 1px `theme.neutral.n200` borders or contrasting
61
+ surface colors is just as shippable. A shadow is only for a surface that genuinely floats or
62
+ overlaps (a feature card on a contrasting background, a sticky bottom bar, a sheet, a FAB) —
63
+ and then barely-there: `boxShadow` is an OBJECT `{ x: 0, y: 6, radius: 20, color:
64
+ 'rgba(16,24,40,0.08)' }` (alpha ≤ 0.12, blur ≥ 3× offset, NEVER a CSS string), paired with the
65
+ surface's `borderRadius`. NEVER shadow TextInputs, chips/pills, or rows inside a card — inputs
66
+ separate with a border or a tinted fill. At most one elevation level per screen; if everything
67
+ is elevated, nothing is.
68
+ - Corners may differ per edge (`borderTopLeftRadius`, `borderTopRightRadius`,
69
+ `borderBottomLeftRadius`, `borderBottomRightRadius`): bottom sheets round only their top
70
+ corners, edge-to-edge heroes only their bottom corners (20–28). Use `opacity` (0.4–0.6) for
71
+ disabled/pressed looks.
72
+ - Gradient accent: at most ONE gradient surface per screen (hero band, promo card, or the
73
+ primary CTA) — a `GradientBackground` container with
74
+ `gradient={{ type: 'linear', stops: [{ color: '#7C6AE6', position: 0 }, { color: '#4C3BB8', position: 1 }], start: { x: 0, y: 0 }, end: { x: 1, y: 1 } }}`.
75
+ Stop colors MUST be literal hex/rgba — theme tokens do NOT resolve inside gradients (the
76
+ gradient silently disappears); pick hexes from the theme's own hues, and make sure text on the
77
+ gradient still contrasts if the gradient failed to render (`backgroundColor` fallback on the
78
+ same node). An accent, never wallpaper.
79
+ - Contrast: text on primary uses `theme.primary.contrast`; never grey-on-grey below
80
+ `text.secondary`.
81
+ - Imagery is REQUIRED for hero, featured-card, detail and list-thumb slots — a tinted box there
82
+ is a wireframe, not a design. Use a topic-matched placeholder photo:
83
+ `source="https://picsum.photos/seed/<topic-word>/<width>/<height>"` on `Image`,
84
+ `ImageBackgroundView` and `MediaCard` (same seed = same photo, so reuse one seed per subject).
85
+ Never invent Creator asset refs. Icon-scale spots (avatars, list icons) stay tinted
86
+ circles/squares holding an `Icon` element — never a tiny photo, never a sourceless `Image`.
87
+ - NEVER use emoji — not in copy, not in headlines, not as icons or illustrations. Every
88
+ pictorial need is an `Icon` element or a photo. Icons color via `styled.styleSvg`
89
+ `{ color, width, height }`.
90
+ - Icons: `iconName` must be a glyph of the project's icon family (Creator → Project → Settings;
91
+ ionicons by default: `home-outline`, `search`, `heart`, `chevron-forward`, `add`, `settings-outline`,
92
+ `person-circle-outline`, `checkmark-circle`, `cart-outline`, `notifications-outline`,
93
+ `chatbubble-outline`, `close`). An unknown name renders as a broken glyph — when the concept
94
+ you want is not a name you know, pick the closest common one rather than guessing.
95
+ - Photo card with text (the premium pattern): `ImageBackgroundView` `source=<picsum>` with
96
+ explicit height 180–260, `borderRadius: 20`, `overflow: 'hidden'` → child `GradientBackground`
97
+ (flex 1, `justifyContent: 'flex-end'`, padding 16, gradient stops `#00000000` → `#00000099`,
98
+ top→bottom) → white `Typography` over the scrim.
99
+
100
+ ## Style merge
101
+
102
+ Each type's defaults come from the component itself — your style MERGES into them. Elements
103
+ you write start from a NEUTRAL base: every element is TRANSPARENT unless you set a
104
+ `backgroundColor` (surfaces — cards, pills, bars — need an explicit theme token; plain text and
105
+ layout containers need none), sized by its content or by flex, and text takes the typography
106
+ document's color unless you set one. Columns still stretch children to full width (React
107
+ Native's `alignItems: 'stretch'`); in rows and horizontal scrolls items size to their content —
108
+ give a container `flex: 1` or an explicit height when it must fill.
109
+
110
+ ## Component library
111
+
112
+ The themed library (`@mapples/components`) paints itself from the theme — use it FIRST and
113
+ compose primitives (`View`, `Typography`, `Pressable`) only for layouts the library lacks.
114
+ Archetype map: surfaces → `Card` (children are the body) or `MediaCard` (photo tile: source,
115
+ title, subtitle, meta); rows → `List` holding `ListItem` children (leading icon/avatar/photo,
116
+ trailing chevron|text|switch|checkbox); filters and tags → `ChipGroup` / `Chip`; counts and
117
+ status pills → `Badge`; form fields → `InputField`, `SelectField`, `Checkbox`, `RadioGroup`,
118
+ `Switch`, `Slider`, `NumberStepper`, `PinInput` (never a raw `TextInput` in a form); search →
119
+ `SearchBar`; progress and KPIs → `ProgressBar`, `ProgressCircle`, `StatTile`; page dots →
120
+ `PageControl`; multi-step → `Steps`; nothing to show → `EmptyState`; confirmations → `Dialog`;
121
+ pickers and quick details → `BottomSheet` / `ActionSheet`; toasts → `Snackbar`; inline notices →
122
+ `Banner`; section titles → `SectionHeader`; chat → `MessageBubble` + `ChatComposer`; in-content
123
+ header → `TopAppBar` ONLY when the stack header is hidden. `BottomNavigationBar` and `Tabs`
124
+ never stand in for a tabs NAVIGATOR — `Tabs` switches views inside one screen.
125
+ Library defaults live inside the component: change the look through `variant`/`size`/`tone`
126
+ props and the style slots, never by rebuilding a component from Views. Array props (`options`,
127
+ `items`, `columns`) are literal arrays. Overlays (`Dialog`, `BottomSheet`, `ActionSheet`,
128
+ `Snackbar`) go LAST in the page root with `visible={false}` unless the project has a boolean
129
+ variable to bind (`$data={{ visible: { key: 'vars.<name>', active: true } }}`) — an overlay
130
+ left visible with no binding covers the screen forever.
131
+
132
+ ## Screen archetypes (adapt, don't copy)
133
+
134
+ - Onboarding: 3 screens — hero (gradient circle or edge-to-edge illustration band with
135
+ bottom-only corner radius 24) + Headline + Body, `PageControl` `{count, value}`, `Button`
136
+ `{variant "filled", size "lg", fullWidth}`; the last screen has Get started + a `TextLink`
137
+ "Sign in". One supporting `Card` `{variant "elevated"}` grounds the hero.
138
+ - Auth: logo mark, Headline + one Caption line of warmth, `InputField` email
139
+ (`keyboardType "email-address"`, `leadingIconName`) and `InputField` password
140
+ (`secureTextEntry`, `showPasswordToggle`), a right-aligned `TextLink` "Forgot password?",
141
+ `Button` filled lg fullWidth, a Caption + `TextLink` switch row. Inputs sit in a single `Card`
142
+ on colored backgrounds.
143
+ - Home (tabs shell): header row (greeting Headline + `Avatar` `{name or source}`), `SearchBar`
144
+ `{placeholder}`, one featured PHOTO-SCRIM card (pattern above, radius 20) before the content,
145
+ `SectionHeader` `{title, actionLabel "See all"}` + horizontal rail of `MediaCard`
146
+ `{source, title, subtitle, meta}` (width 150, gap 12 in contentContainerStyle), then a `List`
147
+ of `ListItem` rows or a column of MediaCards in a ScrollView.
148
+ - List: a `List` `{variant "plain"|"inset"|"card"}` of `ListItem` rows — leading "image" +
149
+ `source` (topic-matched placeholder) or leading "icon" + `leadingIconName`, title + subtitle,
150
+ trailing "chevron" or "text" (price/time). One leading mode per list; the List draws the
151
+ dividers.
152
+ - Detail: hero PHOTO (`Image` or `ImageBackgroundView`) height 240–280 with bottom-only corner
153
+ radius — Headline + a meta row of `Chip` `{variant "assist"}` tags and a `Rating`
154
+ `{readOnly}`, Body, option selectors as `ChipGroup` `{options, value}` rows, a `NumberStepper`
155
+ for quantity, and a `BottomActionBar` `{sticky}` holding the price (Subtitle) + Button filled lg.
156
+ - Settings: `Avatar` `{size "xl"}` header, then `List` `{variant "inset", header "PREFERENCES"}`
157
+ groups of `ListItem` rows `{leadingIconName, title, trailing "switch"|"chevron"|"text"}`; the
158
+ destructive row is a `ListItem` `{tone "error"}` in its own List.
159
+ - Stats: a row of 2–3 `StatTile` `{label, value, unit, trend, trendValue}` (flex 1 each),
160
+ `ProgressBar` `{value, showLabel}` or `ProgressCircle` `{value, size 72, showLabel}` for goals —
161
+ never charts faked from Views.
162
+ - Empty state: `EmptyState` `{iconName, title, message, actionLabel}` centred with generous
163
+ vertical whitespace (top ⅓ empty).
164
+ - Chat: a ScrollView of `MessageBubble` `{text, direction, time, status}` and a `ChatComposer`
165
+ `{placeholder, leadingIconName "attach-outline"}` pinned to the bottom.
166
+ - Modal sheet: a whole flow presents as a modal ROUTE (set in Creator; note it in `design.md`);
167
+ a picker or quick detail inside a screen is a `BottomSheet` `{title}` with children; a
168
+ confirmation is a `Dialog` `{title, message, primaryActionLabel, secondaryActionLabel, tone
169
+ "error" when destructive}`; a list of actions is an `ActionSheet` `{options}`.
170
+ - Chips, badges, breadcrumbs: `Chip`/`ChipGroup`, `Badge`, `Breadcrumbs` — content-sized library
171
+ elements; stack headers and tab bars come from navigator options.
172
+
173
+ ## Example — one onboarding screen as a route file
174
+
175
+ ```tsx
176
+ // (the CLI's `// mapples-route:` marker stays on line 1 once the file is synced)
177
+ import { router } from 'expo-router';
178
+ import { Container, GradientBackground, Icon, Typography, View } from '@mapples/ui';
179
+ import { Button, Card, PageControl, TextLink } from '@mapples/components';
180
+ import { Styler } from '@mapples/style';
181
+
182
+ export default function Welcome() {
183
+ return (
184
+ <Container styled={{ style: styles.root }}>
185
+ <View styled={{ style: styles.topBar }}>
186
+ <TextLink label="Skip" tone="neutral" underline={false} onPress={() => router.push('/(main)')} />
187
+ </View>
188
+ <View styled={{ style: styles.hero }}>
189
+ <GradientBackground
190
+ gradient={{ type: 'linear', stops: [{ color: '#7C6AE6', position: 0 }, { color: '#4C3BB8', position: 1 }], start: { x: 0, y: 0 }, end: { x: 1, y: 1 } }}
191
+ styled={{ style: styles.heroMark }}
192
+ >
193
+ <Icon iconName="chatbubble" styled={{ styleSvg: styles.heroGlyph }} />
194
+ </GradientBackground>
195
+ <Typography text="Chat like Viver" variant="Headline" styled={{ style: styles.heroTitle }} />
196
+ <Typography text="Voice, video and messaging in one fast, friendly space." variant="Body" styled={{ style: styles.heroBody }} />
197
+ <Card variant="elevated" styled={{ style: styles.proofCard }}>
198
+ <Typography text="End-to-end encrypted" variant="Label" styled={{ style: styles.proofTitle }} />
199
+ <Typography text="Your calls and chats stay between you." variant="Caption" styled={{ style: styles.proofBody }} />
200
+ </Card>
201
+ </View>
202
+ <View styled={{ style: styles.bottom }}>
203
+ <PageControl count={3} value={0} variant="bars" />
204
+ <Button label="Continue" variant="filled" size="lg" fullWidth onPress={() => router.push('/(onboarding)/features')} />
205
+ </View>
206
+ </Container>
207
+ );
208
+ }
209
+
210
+ const styles = Styler.create({
211
+ root: { padding: 24, paddingTop: 64, paddingBottom: 32, justifyContent: 'space-between', backgroundColor: 'theme.background.primary' },
212
+ topBar: { alignItems: 'flex-end' },
213
+ hero: { alignItems: 'center', gap: 16 },
214
+ heroMark: { width: 96, height: 96, borderRadius: 48, alignItems: 'center', justifyContent: 'center' },
215
+ heroGlyph: { width: 44, height: 44, color: '#FFFFFF' },
216
+ heroTitle: { textAlign: 'center', color: 'theme.text.primary' },
217
+ heroBody: { textAlign: 'center', color: 'theme.text.secondary', paddingHorizontal: 12 },
218
+ proofCard: { gap: 4 },
219
+ proofTitle: { color: 'theme.text.primary' },
220
+ proofBody: { color: 'theme.text.secondary' },
221
+ bottom: { gap: 16, alignItems: 'center' },
222
+ });
223
+ ```
224
+
225
+ > Not ported (Creator-only): element ids and `set_element_style`, `capture_page` screenshots
226
+ > (re-read the file against `lint-checklist.md` instead), the storyboard layout, selection
227
+ > chips, `add_placeholder_image` refs (picsum URLs here), `$data` variable creation.
@@ -0,0 +1,51 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Review checklist — the layout lint, by hand
3
+
4
+ Ported from the Creator's `designLint.ts`, which runs on every AI-authored tree before it is
5
+ written. Here you are the lint: after each screen (and in the review pass) re-read the file
6
+ and walk every element against this list. **Error** items must be fixed; **warn** items are
7
+ fixed unless the design instructions justify them.
8
+
9
+ | # | Rule | Severity | Check | Fix |
10
+ | --- | --- | --- | --- | --- |
11
+ | 1 | full-width-in-row | error | `width: '100%'` on an element inside a row (`flexDirection: 'row'`) or a `HorizontalScrollView` | drop the width (chips, pills, badges size to their content; `alignSelf: 'flex-start'`) or give a fixed width |
12
+ | 2 | unknown-token | error | a `'theme.…'` / `'sizing.…'` string that is not a key of `mapples/theme.ts` | use a real path (`theme.primary.main`, `theme.text.secondary`, `sizing.md`) |
13
+ | 3 | unknown-prop | warn | a prop the type does not have | remove it or use the prop from `component-library.md` |
14
+ | 4 | missing-content-prop | error | a library element without its content prop (`Typography` without `text`, `Button` without `label`, `ListItem` without `title`, `InputField` without `label`/`placeholder`, `EmptyState` without `title`) | set it — otherwise the palette placeholder content ships as the design |
15
+ | 5 | control-without-label-color | warn | `Button`/`SubmitButton` with no `variant` and no `styled.styleTypography.color` | set a `variant` (filled/outlined/text) |
16
+ | 6 | icon-without-color | warn | `Icon` with no `styled.styleSvg.color` | set a theme token |
17
+ | 7 | icon-button-without-label | warn | `IconButton`/`Fab` without `accessibilityLabel` | name the action ("Add to favourites") |
18
+ | 8 | percent-height-in-flow | error | `height: '100%'` on an element sharing a column with siblings | `flex: 1` or a fixed height |
19
+ | 9 | absolute-without-offsets | warn | `position: 'absolute'` without top/left/right/bottom | add offsets or drop the position |
20
+ | 10 | empty-container | warn | a container with no children and no height/minHeight/flex | give it content or a size |
21
+ | 11 | small-touch-target | warn | a control with `height`/`minHeight` < 44 | ≥ 44 |
22
+ | 12 | narrow-text | warn | a `Typography` with a numeric `width` < 120 | drop the width so it stretches |
23
+ | 13 | unknown-icon-glyph | warn | an `iconName` that is not a glyph of the project icon family | pick a common name (`home-outline`, `search`, `chevron-forward`, `add`, …) |
24
+ | 14 | gradient-token-color | warn | a gradient stop using a `theme.`/`sizing.` string | literal hex/rgba stops |
25
+ | 15 | image-without-source | warn | `Image`/`ImageBackgroundView`/`MediaCard` without a `source` | a picsum URL (`https://picsum.photos/seed/<topic>/<w>/<h>`) |
26
+ | 16 | chip-outside-group | warn | a `Chip` directly in a column | put it in a `ChipGroup`, a row or a `HorizontalScrollView` |
27
+ | 17 | overlay-always-visible | warn | `Dialog`/`BottomSheet`/`ActionSheet`/`Snackbar` not `visible={false}` and not bound | `visible={false}` or a `$data` binding to a boolean variable |
28
+ | 18 | raw-text | warn | a `Text` element | `Typography` with a variant |
29
+ | 19 | typography-without-variant | warn | `Typography` with no `variant` | set one (Headline, Body, Caption, …) |
30
+ | 20 | invisible-surface | warn | a container whose `backgroundColor` equals its parent's, with no border or shadow | a contrasting surface color, a 1px `theme.neutral.n200` border, or (only if the elevation language uses them) a soft shadow |
31
+ | 21 | shadow-on-control | warn | `boxShadow` on a flat control (`InputField`, `TextInput`, `Chip`, `Badge`, a `ListItem` inside a card) | remove it; separate with a border or a tinted fill |
32
+ | 22 | scroll-spacing-in-style | warn | `gap`/`padding*` on a scroll container's `style` | move them into `styled.contentContainerStyle` |
33
+ | 23 | unspaced-container | warn | a container with ≥ 2 children and no `gap`/`padding` (and none in `contentContainerStyle`) | `gap` from the sizing scale (12–16) |
34
+ | 24 | literal-color | warn | a hex `backgroundColor`/`color`/`borderColor` outside a gradient or a scrim | a theme token so dark mode and restyles follow |
35
+
36
+ Then the human pass the Creator does with a screenshot (`capture_page`): read the file top to
37
+ bottom as the phone would draw it — clipping (fixed widths > 360), overflow (tall content not in
38
+ a ScrollView), misalignment (mixed `alignItems`), cramped spacing (gaps < 8 between groups),
39
+ weak hierarchy (two Headlines; no focal point), wrong contrast (grey on grey, white on light),
40
+ grey image boxes (every photo slot has a source), off-topic photo seeds, unreadable text over
41
+ photos (the scrim gradient is there), an emoji anywhere, placeholder copy ("Item 1", "Text").
42
+
43
+ The squint test: if you blur the screen you should still see WHERE to look first and WHAT is
44
+ tappable. If everything is even grey noise, raise the focal point and quiet the rest.
45
+
46
+ Finally, `npx -y mapples@__CLI_VERSION__ doctor --json` must show no `duplicate` or `missing` issues, and the last
47
+ `npx -y mapples@__CLI_VERSION__ sync --yes --json` must exit 0 with no `warnings` of kind `UNKNOWN_ELEMENT_WITH_SID`.
48
+
49
+ > Not ported (Creator-only): `strictProps` per-schematic hint lists, the icon-glyph set and
50
+ > token set validation (both live in the Creator's registry), `aiLint` hints (`selfSpaced`,
51
+ > `selfSurfaced`, `touchTarget`, `overlay`, `flatControl`) — the type lists above stand in.
@@ -0,0 +1,95 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Implementation plan (phase 3)
3
+
4
+ Ported from `generate.ts` `generatePlan` and `schemas.ts` `implementationPlanSchema`. Act as a
5
+ senior product engineer planning the MVP build of this mobile app. Inputs: the brief, the
6
+ design instructions (from phase 2) and the scope.
7
+
8
+ ## Scopes
9
+
10
+ | Scope | Meaning |
11
+ | --- | --- |
12
+ | single | SINGLE SCREEN — a design-quality test bed: exactly ONE section (a stack) holding exactly ONE screen, the app's Home, designed to the highest visual standard — hero/featured content, real copy, depth, imagery placeholders. No auth, no onboarding, no detail screens; decisions record only what was cut. Steps: build the Home screen, then a visual-polish pass, then the review pass. |
13
+ | minimal | MINIMAL — the leanest shippable start: only the screens delivering the core value, plus auth ONLY if the product cannot work without accounts. 3–5 screens. |
14
+ | basic | BASIC — the core value with its supporting screens: main content, detail, settings/profile where they earn their place, auth if needed. 6–9 screens. |
15
+ | advanced | ADVANCED — a near-complete app: every main section, detail screens, profile/settings, onboarding and empty states where they earn their place. 10–14 screens. |
16
+
17
+ ## Decide first
18
+
19
+ First DECIDE what THIS product actually needs — no habit choices, and record every material
20
+ decision with its product reason:
21
+
22
+ - Authentication: does it need accounts at all? No accounts → no auth screens.
23
+ - Navigation pattern: plain stack, tabs, or drawer — chosen for the content, not by default.
24
+ - Onboarding: only if it teaches something the first screen cannot.
25
+ - What was deliberately cut at this scope and why.
26
+
27
+ ## Screen set
28
+
29
+ The GOLDEN PATH comes first — the one flow that proves the product's value end to end (open →
30
+ core content → primary action → payoff); every screen on it exists before any supporting screen
31
+ does. Supporting screens must earn their place: a detail screen only when lists point at it,
32
+ settings only when there is something real to set, profile only when identity matters to this
33
+ product, onboarding only when it teaches what the first screen cannot. At every scope prefer
34
+ fewer screens fully designed over more screens sketched.
35
+
36
+ Flow integrity — the plan must be walkable on paper: every screen's key elements name where its
37
+ PRIMARY action leads ("Add to order button → Cart"), every screen is reachable from another
38
+ screen or a tab, every flow exits somewhere meaningful (a completed form lands on a success
39
+ state or the content it created, never back on the empty form), and no screen exists that
40
+ nothing links to. The entry screen is the value proof — never settings or profile.
41
+
42
+ Navigation rules: one root stack; sections are its children (Auth stack, Main tabs…), at most
43
+ two levels. No section for a single screen, no wrapper stacks. Screen names say what the screen
44
+ IS ("Welcome", "Sign in", "Chats"), never numbered. Every screen name is unique across sections;
45
+ exactly one section is `initial`.
46
+
47
+ ## Build steps
48
+
49
+ Then the ordered build steps. Phase 4 creates the navigation and every screen automatically
50
+ BEFORE step one, so steps never create screens or sections — they design existing empty screens.
51
+ Every step carries `kind` and `screens`: kind **screen** designs one or two screens (their EXACT
52
+ names from the navigation) with concrete content directions (real copy, from the brief) honoring
53
+ the design instructions; kind **wiring** connects the existing screens (list every screen it
54
+ touches) and comes after all screen steps; kind **review** is always the final step, a
55
+ consistency pass across all screens for spacing and contrast (list them all). The first step
56
+ designs the entry screen, and every screen is designed by a screen step. Each step must be
57
+ completable in ONE sitting (one screen file, one sync). 3–12 steps.
58
+
59
+ ## Write it into `design.md`
60
+
61
+ ```md
62
+ ## Plan — <name> (<scope>)
63
+ <rationale, one sentence>
64
+
65
+ ### Decisions
66
+ - Authentication: <decision> — <why>
67
+ - Navigation pattern: <decision> — <why>
68
+ - Onboarding: <decision> — <why>
69
+ - Cut at this scope: <what> — <why>
70
+
71
+ ### Navigation
72
+ - (main) tabs — initial
73
+ - Home — <purpose>. Key elements: <…; "Start button → Session">
74
+ - Progress — <purpose>. Key elements: <…>
75
+ - (auth) stack
76
+ - Sign in — <purpose>. Key elements: <…>
77
+ Entry screen: Home
78
+
79
+ ### Steps
80
+ 5. Build the Home screen — screen: Home — <detail: exactly what to design and how, real copy directions>
81
+ 6. Build Progress and Settings — screen: Progress, Settings — <detail>
82
+ 7. Wire the flow — wiring: Home, Progress, Settings, Sign in — <detail>
83
+ 8. Review pass — review: all — spacing, contrast, hierarchy
84
+ ```
85
+
86
+ Step numbers continue the fixed index convention (0 Brief · 1 Style guides · 2 Design tokens ·
87
+ 3 Plan · 4 Scaffold), so the first plan step is index 5; wiring is N-1 and review is N.
88
+
89
+ Section slugs become route groups: `(main)`, `(auth)`. Screen slugs become route files:
90
+ `index.tsx` for a section's first screen, kebab-case otherwise (`sign-in.tsx`).
91
+
92
+ > Not ported (Creator-only): the zod cross-field validation (apply the same checks yourself:
93
+ > unique names, one initial section, entry screen known, first step designs the entry screen,
94
+ > last step is review, every screen designed once), and `set_route_presentation` /
95
+ > `set_navigator_options` (describe modal routes and chrome in `## Navigation chrome`).
@@ -0,0 +1,14 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Empty states
3
+
4
+ First-run and no-content screens: icon, copy formula, one clear action.
5
+
6
+ An empty state is an onboarding moment, not an apology. Formula: two parts instruction, one part delight. Build it as ONE `EmptyState` {iconName, title, message, actionLabel, secondaryActionLabel} (or `imageSource` instead of the glyph) placed with generous whitespace — the block sits at about 1/3 from the top. What it renders:
7
+ 1. Mark: a 96–120 circle — tinted `theme.primary.background`, or a subtle two-hex gradient — holding an `Icon` glyph 40–48 relevant to the missing content (an "image" glyph for no photos, a "cart" glyph for an empty cart). NEVER an emoji.
8
+ 2. Headline, ≤ 4 words, stating the situation positively: "No orders yet", "Your cart is empty".
9
+ 3. Body, ≤ 2 lines, `theme.text.secondary`, telling the user what this screen WILL show and how to get there: instruction, not decoration.
10
+ 4. ONE primary `Button` naming the action ("Browse the menu", "Add your first habit") — only when the user can actually resolve the emptiness here; if the content arrives on its own (e.g. notifications), end at the Body line.
11
+
12
+ Variants: search-no-results uses iconName "search" and a secondaryActionLabel "Clear search"; error states use tone "error" and an actionLabel "Try again".
13
+
14
+ Pitfalls: no dead-end screens — something actionable or an explanation, always; do not stack two buttons; the copy speaks the product's voice from the brief, not generic "No data".
@@ -0,0 +1,22 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Forms and auth
3
+
4
+ Sign in/up and any input form: field anatomy, grouping, validation, CTA.
5
+
6
+ Field anatomy (every input): an `InputField` {label, placeholder, helperText, errorText, leadingIconName, keyboardType, autoCapitalize, variant "outlined" | "filled"} — never a raw `TextInput` in a form. Dropdowns are `SelectField` {options, placeholder}; yes/no is `Checkbox` or `Switch`; an exclusive choice is `RadioGroup` {options}; one-time codes are `PinInput` {length}. Match the app's elevation language through `variant` (outlined vs filled); NEVER a `boxShadow` on an input. Placeholder is an example value ("you@example.com"), never a label substitute. Gap 16 between fields, 24–32 between groups.
7
+
8
+ Auth screen structure (root column, screen padding 20–24, `justifyContent: 'space-between'`):
9
+ 1. Top: logo mark or app-name Headline, plus ONE warm Caption line ("Good to see you again").
10
+ 2. Middle (gap 16): the fields — `InputField` email/phone (keyboardType "email-address" | "phone-pad", autoCapitalize "none"), `InputField` password (secureTextEntry, showPasswordToggle). On colored or photo backgrounds, group all fields inside one `Card` {variant "elevated"}.
11
+ 3. A right-aligned `TextLink` "Forgot password?" directly under the password field.
12
+ 4. Bottom: `Button` {variant "filled", size "lg", fullWidth true}, then a centered switch row ("New here?" Caption + `TextLink` "Create account").
13
+
14
+ Forms in general:
15
+ - One column, never side-by-side fields on phone (except tiny pairs like MM/YY + CVC).
16
+ - Group related fields under an Overline section label; 3–6 fields per screen, split longer flows into steps with a progress indicator (`Steps`).
17
+ - Validation is inline: the field's `errorText` paints the error border and the message — never only a toast, never clearing the user's input. In code, keep the literal you design with (`errorText` omitted or a literal example); state comes later.
18
+ - Keyboard reality: keep the primary `Button` visible — bottom padding 24–32 and the fields in the upper half of the screen.
19
+
20
+ Pitfalls: disabled-looking CTAs (use full primary color; validate on submit); asking for data the flow does not need; phone inputs without keyboardType "phone-pad"; password fields without showPasswordToggle.
21
+
22
+ > Not ported (Creator-only): the `create_page {template: "login"}` shortcut — write the screen.
@@ -0,0 +1,14 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Home / dashboard
3
+
4
+ Home screens: greeting header, search, featured card, rails and lists.
5
+
6
+ The scan order sells the app in 3 seconds: who am I → what is featured → what can I browse. Root is a vertical `ScrollView` (spacing in `styled.contentContainerStyle`: {gap: 24, paddingBottom: 32}); the screen padding lives there too.
7
+
8
+ 1. Header row (`flexDirection: 'row'`, `justifyContent: 'space-between'`, `alignItems: 'center'`): greeting Headline ("Good morning, Alex" — real name from the brief, no emoji) with an optional Caption line under it; trailing `Avatar` {name or source, size "md"}.
9
+ 2. Search (when the product searches): a `SearchBar` {placeholder} — filled pill by default; never a bare 1px outline on white.
10
+ 3. ONE featured/promo card: the photo-scrim pattern — `ImageBackgroundView` (picsum `source`, height 180–220, borderRadius 20, overflow "hidden") → `GradientBackground` child (flex 1, `justifyContent: 'flex-end'`, padding 16, stops "#00000000" → "#00000099", top→bottom) → white `Typography` (Subtitle + Caption). Elevation only if the app's elevation language says so.
11
+ 4. Horizontal rail: `SectionHeader` {title, actionLabel "See all"}, then `HorizontalScrollView` with `styled.contentContainerStyle` {gap: 12, paddingHorizontal: 20} (full-bleed scroll, aligned first card). Cards are `MediaCard` {source (picsum), title, subtitle, meta} at a fixed width 150.
12
+ 5. Vertical list: a `List` of 3–5 `ListItem` rows, or a column of MediaCards (see the list-and-detail playbook).
13
+
14
+ Pitfalls: never two featured cards; never a gradient AND a photo hero competing; one accent surface per screen; rails scroll behind the screen padding (`paddingHorizontal` in `contentContainerStyle`, NOT on the rail's style).
@@ -0,0 +1,18 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Lists and detail screens
3
+
4
+ List rows, cards, detail screens with hero, meta pills and sticky CTA.
5
+
6
+ List rows: a `List` {variant "plain" | "inset" | "card"} holding `ListItem` rows — never hand-built Pressable rows:
7
+ - Leading: leading "image" + `source` (a picsum URL seeded with the row's own topic) when rows have natural imagery; otherwise leading "icon" + `leadingIconName` (the row tints a rounded square itself). One mode per list — never mix thumbs and icon squares.
8
+ - Middle: title + subtitle (one Caption meta line).
9
+ - Trailing: trailing "chevron", or trailing "text" + `trailingText` (a price or a time) — one, not several.
10
+ - Separation follows the app's elevation language: `List` {variant "plain"} draws hairline dividers on the page background; a card list is `List` {variant "card"} or one `MediaCard` per item with gap 12.
11
+
12
+ Detail screen:
13
+ 1. Hero photo: `Image` or `ImageBackgroundView` height 240–280, width 100%, bottom-only corner radius 20–28 (or a content sheet overlapping it with `marginTop: -24` and top-only radius 24).
14
+ 2. Title block: Headline + a meta row of `Chip` {variant "assist", label} tags (≤ 2) and a `Rating` {value, readOnly} — content-sized, in a row with gap 8.
15
+ 3. Body copy, then option selectors as `ChipGroup` {options, value, scrollable} rows and a `NumberStepper` {min 1} for quantity.
16
+ 4. Sticky bottom bar: a `BottomActionBar` {sticky true} holding the price (Subtitle) + `Button` {variant "filled", size "lg"} (flex 1).
17
+
18
+ Pitfalls: content between hero and CTA scrolls (`ScrollView` with `contentContainerStyle` padding), the bottom bar does not; never let meta chips wrap to three lines — cap at two tags plus a rating.
@@ -0,0 +1,20 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Microcopy
3
+
4
+ Copy that sells: verbs on buttons, benefit headlines, product voice, error tone.
5
+
6
+ Copy is half of looking real. Generic words are the fastest tell of a template; specific words are the cheapest wow.
7
+
8
+ Voice: derive it from the brief — a specialty coffee app sounds warm and craft-y, a finance app calm and precise, a fitness app energetic. Pick the voice once and keep it on every screen, in the design instructions' terms.
9
+
10
+ Buttons are VERBS that name the outcome: "Start brewing", "Book the 9:00 class", "Add to order" — never "Submit", "OK", "Click here", "Continue" where something specific fits (Continue is fine mid-onboarding). One primary verb per screen.
11
+
12
+ Headlines state the benefit, not the feature: "Your next free coffee is close" beats "Loyalty points"; "Chat like Viver" beats "Messaging features". Keep hero headlines ≤ 5 words; sentence case everywhere except Overline labels (uppercase) — never Title Case Every Word.
13
+
14
+ Body and meta text carry REAL data shaped like the product: prices with currency, times as a person says them ("Scanned 2 hours ago"), quantities with units ("250g bag"). Lists carry 3–5 believable, varied entries from the brief's world — never Item 1 / Item 2, never lorem ipsum, never the same entry repeated.
15
+
16
+ Empty and error states: state the situation positively, then the way forward ("No orders yet — your first one lands here"; "That code did not match — try again or resend"). Errors never blame the user and never say "Error:" — they say what to do next.
17
+
18
+ Numbers and dates: shorten like products do (1.2k, 4.8 stars, "Tue 8:15 AM"); progress copy counts DOWN to the goal ("30 to go for a free coffee") because momentum sells.
19
+
20
+ Pitfalls: emoji anywhere (hard ban); exclamation marks more than once per screen; "Welcome to [App]" as a headline (say what the user GETS instead); placeholder text that repeats the label; the assistant's own meta-language ("This screen shows…") leaking into the UI.
@@ -0,0 +1,21 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Navigation chrome
3
+
4
+ Headers, tab bars, chips, badges and breadcrumbs: navigator options vs content-sized elements.
5
+
6
+ Two kinds of chrome, two mechanisms — never mix them up:
7
+ - Stack headers and tab bars belong to the NAVIGATOR. In this version they are set in Creator (navigator options: header visible/title/colors/back, tab bar colors/labels; route options: title, tab label, tab icon asset) and land in the CLI-owned `_layout.tsx` on the next sync — you cannot set them from code, and you must not edit the layouts. Describe the intended chrome per section in `design.md` under `## Navigation chrome` (which sections hide the header, tab labels and icon concepts, modal routes) so the user applies it. A hand-built header row on a screen whose stack also shows a header gives two headers: design for one — the default root layout hides headers (`headerShown: false`), so in-content `TopAppBar` is the norm for apps born from `npx -y mapples@__CLI_VERSION__ create`.
8
+ - Tab icons require an icon ASSET in Creator; an `Icon` element or a glyph name does nothing there. Note the icon concept per tab in `design.md`; keep tab labels short and distinct — never fake a tab bar from a row of buttons on the page.
9
+ - Everything inside the content area (chips, pills, badges, breadcrumbs, in-content title rows) is a CONTENT-SIZED library element: never width 100% inside a row or a horizontal scroll; never a `Button` where a `Chip` is meant.
10
+
11
+ Recipes:
12
+ - Chip row: `ChipGroup` {options: [{label, value, iconName?}], value, variant "filter", scrollable true} — it scrolls full-bleed itself; single chips are `Chip` {label, variant "assist" | "suggestion"}.
13
+ - Count badge: `IconButton` {iconName, badgeCount, accessibilityLabel} or `Avatar` {badgeCount}; a standalone `Badge` {count} elsewhere. Digits only ("99+" past the max); no badge at zero.
14
+ - Status pill (tags, "New", "Ready"): `Badge` {label, variant "text", tone} or `Chip` {variant "suggestion"}; at most two pills per row — never three lines of pills.
15
+ - Breadcrumbs: `Breadcrumbs` {items: [{label, value}], separator "chevron", maxItems 4}; the last item is the current page. Never as the screen's only title.
16
+ - In-content title row (only when the stack header is hidden): `TopAppBar` {title, showBack true, actions: [{iconName, value}], variant "small"}; the root keeps its safe-area `paddingTop` (≥ 48).
17
+ - In-content tabs inside ONE screen: `Tabs` {items: [{label, value}], value} with each panel shown for one value (bind `$data={{ _visible: … }}` only when the project has the variable; otherwise design the first panel); a `BottomNavigationBar` is only for a single-page demo of a tab shell — real tabs are a tabs navigator (a `(group)/` with a `<Tabs />` layout).
18
+
19
+ Pitfalls: chips built from Pressables; a badge drawn from Views; breadcrumbs typeset as a Headline; a header built twice (TopAppBar + stack header); `Tabs` or `BottomNavigationBar` used instead of a navigator.
20
+
21
+ > Not ported (Creator-only): `set_navigator_options` / `set_route_options` and the `ref(theme:…)` / `ref(icon:…)` value syntax.
@@ -0,0 +1,15 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Onboarding flow
3
+
4
+ Welcome/intro flows: 2–3 value-prop screens with hero, dots and CTA arc.
5
+
6
+ Value first: each screen sells ONE benefit from the brief — never a feature tour of the whole app. 2–3 screens maximum; every extra screen loses users.
7
+
8
+ Structure per screen (root column, `justifyContent: 'space-between'`, screen padding 20–24, `paddingTop` ≥ 64, `paddingBottom` 32):
9
+ 1. Top bar: a right-aligned `TextLink` {label "Skip", tone "neutral", underline false} on every screen except the last.
10
+ 2. Hero block (`alignItems: 'center'`, gap 16): ONE hero — either a `GradientBackground` circle 96–120 holding an `Icon` glyph 44–56 (`styleSvg.color` a light hex), or an edge-to-edge photo band (`Image` with a picsum `source`, height 260–320, bottom-only corner radius 24). Then a centered Headline (≤ 5 words, the benefit, not the feature) and one Body line (≤ 2 lines, `theme.text.secondary`).
11
+ 3. Bottom block (gap 16, `alignItems: 'center'`): a `PageControl` {count, value, variant "bars"} — then the primary `Button` {variant "filled", size "lg", fullWidth true}.
12
+
13
+ CTA copy arc: "Continue" on middle screens; the LAST screen carries the real ask — "Get started" primary plus a `TextLink` "Sign in" row underneath for returning users.
14
+
15
+ Pitfalls: no emoji heroes; one hero per screen, never hero + photo; dots and button positions must not shift between screens (same bottom block on all three); wire screen→screen and last screen→auth or home in the wiring phase (`$actions` navigate + `router.push`).
@@ -0,0 +1,37 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Screen flow wiring
3
+
4
+ Wiring flows: every CTA connected, entries set, a walkable prototype.
5
+
6
+ A project becomes a product when every path is walkable. After the screens exist, wire them — this is as much the design as the pixels.
7
+
8
+ How a connection is written (both halves, on the element's primary event):
9
+
10
+ ```tsx
11
+ import { router } from 'expo-router';
12
+ // …
13
+ <Button
14
+ label="Add to order"
15
+ variant="filled"
16
+ size="lg"
17
+ fullWidth
18
+ onPress={() => router.push('/(main)/cart')}
19
+ $actions={{ onPress: { type: 'mapples:navigate', staticData: { pageUuid: '<uuid>' } } }}
20
+ />
21
+ ```
22
+
23
+ `$actions` is the Creator connection (the storyboard arrow); `onPress` is the runtime handler. The `pageUuid` is the `uuid` field of `.mapples/base/pages/<pageId>.json`, where `<pageId>` is the key in `.mapples/pages.json` whose `file` is the target route file. Rows use `ListItem`'s `onPress`, cards `MediaCard`'s / `Card`'s `onPress`.
24
+
25
+ The contract:
26
+ - Every PRIMARY `Button` navigates to a real page: onboarding Continue → next screen, Get started → auth or home, list row / card → its detail, detail CTA → the flow it starts (cart, booking, player). No dead primary buttons, ever.
27
+ - Secondary paths too: Skip → where Continue ultimately lands; Sign in ↔ Create account cross-links; back is implied by the stack — never draw a back button into the tree (the shell provides it).
28
+ - Every screen is REACHABLE: if nothing navigates to a screen in the plan, either wire the entry that was missed or question why the screen exists.
29
+ - Every flow has an EXIT: the last onboarding screen leaves onboarding; a completed form lands somewhere meaningful (a success state or the content it created), not back at the empty form.
30
+ - Entries: the app must open on the value, not on a settings screen. The initial section/route is a navigator option set in Creator — state the intended entry in `design.md` under `## Navigation chrome` (the scaffold's `index.tsx` of the initial section is the natural default).
31
+ - Presentation: multi-screen interruptions and create-flows present as modal ROUTES (a navigator option — describe them in `design.md`); browsing pushes. Confirmations, pickers and quick details stay on the screen as `Dialog` / `BottomSheet` / `ActionSheet` with `visible={false}`, or bound through `$data={{ visible: { key: 'vars.<name>', active: true } }}` when the project has the variable — an overlay nobody can open or close is a dead end.
32
+
33
+ Verify like a user: after wiring, walk the golden path mentally from the entry screen — first open → core value → primary action → done. Name the connection chain; every hop must exist. Then `npx -y mapples@__CLI_VERSION__ sync --yes --json` and check that `pushedOps` covers every `$actions` you added (an action on an element without a `$sid` yet lands on the sync after the element is tagged).
34
+
35
+ Pitfalls: wiring only the happy screen and leaving detail pages orphaned; two buttons navigating to the same place with different labels; a tab bar plus in-content navigation to the same sections.
36
+
37
+ > Not ported (Creator-only): `set_initial_route`, `set_entry_page`, `set_route_presentation`, `layout_storyboard`, `add_connection {action: {kind: "setState"}}` variable creation.
@@ -0,0 +1,16 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Settings and profile
3
+
4
+ Settings and profile screens: grouped cards, icon rows, switches, sign out.
5
+
6
+ Root: vertical `ScrollView`, `contentContainerStyle` {gap: 24, padding: 20, paddingBottom: 40}.
7
+
8
+ Profile header (when the app has accounts): centered column gap 8 — `Avatar` {size "xl", source a picsum "portrait" seed, or name for initials}, name Subtitle, email/handle Caption in `theme.text.secondary`. A `TextLink` "Edit profile" or `Button` {variant "outlined", size "sm"} under it.
9
+
10
+ Groups: one `List` {variant "inset", header "PREFERENCES" | "ACCOUNT" | "ABOUT"} per group — the List draws the surface and the dividers (no gaps between rows — the list is the unit).
11
+
12
+ Row anatomy: `ListItem` {leadingIconName, title, subtitle only for rows that need explanation, trailing "switch" for toggles, trailing "chevron" for navigation rows, trailing "text" + trailingText ("English") for pickers}. Keep one icon tint system across the groups.
13
+
14
+ The destructive row: "Sign out" / "Delete account" as a `ListItem` {tone "error"} in its own last `List` — never mixed into a normal group.
15
+
16
+ Pitfalls: no more than 5–6 rows per list; switches bind to real variables only when the project has them (`$data`), otherwise leave them unwired rather than faking state; app version as a final centered Caption is a nice close.
@@ -0,0 +1,17 @@
1
+ <!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
2
+ # Stats and progress
3
+
4
+ Numbers, balances, goals: stat cards, progress bars, streaks — no fake charts.
5
+
6
+ Numbers are the hero — let one big value carry each block.
7
+
8
+ The hero number: a `StatTile` {label "BONUS BALANCE", value "1,240", unit "pts", caption, trend, trendValue, iconName, variant "elevated"} — or, for a brand-coloured hero, a `Card` with a deep brand-hex fill holding an Overline label and a Headline-sized value (fontSize 40–56 via a `styleTypography` override) with its unit in a Subtitle beside it (`flexDirection: 'row'`, `alignItems: 'flex-end'`, gap 8).
9
+ - CONTRAST RULE: on a dark/brand fill, text is white/near-white hexes; on a light card, `theme.text` tokens. Never white text on a light background — if a gradient supplies the dark fill, the SAME node needs a solid dark `backgroundColor` fallback.
10
+
11
+ Progress: `ProgressBar` {value, max, showLabel} for goals and uploads, `ProgressCircle` {value, size 72, showLabel} for rings. Under it one Caption: how far to the goal ("30 to go for a free coffee").
12
+
13
+ Stat rows/grid: 2–3 `StatTile` in a row (`flexDirection: 'row'`, gap 12, each flex 1). Streaks: a row of 7 day-dots (24 circles — filled `theme.primary.main` for done, tinted for not, an `Icon` "checkmark" glyph 12 inside filled ones).
14
+
15
+ Simple comparisons only: horizontal bar rows (Label + track/fill pair per row). Do NOT fake line/pie charts out of Views — if the product truly needs charts, say so instead of drawing a lie.
16
+
17
+ Pitfalls: multiple hero numbers competing on one screen (pick one, demote the rest to the row/grid); percent fills must come from the actual data in the copy; progress color and CTA color should match so the goal reads as reachable.