Mobile capture flow
The Clay mobile app starts with one focused workflow: capture enough signal to draft a useful opportunity fit brief without asking the user to expose raw private reflections. This is the product contract forapps/mobile/app/index.tsx.
On this page
- The mobile scope — platform, framework, native boundaries
- The five captured signals on the first screen
- The four UI states of the capture flow
- The Expo UI boundary inside the first route
- Design implementation notes and component wiring
- The haptic feedback vocabulary
- The next action contract
- The build order for the slice
Scope
Platform
iOS-only Expo app.
apps/mobile/app.json keeps platforms constrained to ["ios"].Framework
Expo SDK 57 with Expo Router through
expo-router/entry; route files live under
apps/mobile/app/.Native controls
@expo/ui owns standard native inputs: text input, picker, slider, switch, and save button.Clay surfaces
React Native owns safe areas, keyboard-aware scrolling, custom cards, selected states, and
Clay-specific layout.
Captured signals
Intention
The user writes one concrete outcome. The current screen caps the text input at 180 characters
to keep the first signal concise.
Opportunity lane
The native picker classifies the next opportunity as
Collaborator, Project, Community, or
Role.Readiness
The native slider captures a 1-5 readiness value and translates it into
Exploring, Open to the right fit, or Ready to act.Personality signal
The custom cards capture the preferred working mode:
Deep work, High context, or Fast feedback.States
| State | Trigger | Required behavior |
|---|---|---|
| Empty | No intention text | Disable save and explain that one concrete outcome is needed. |
| Draftable | Intention text exists | Enable save and tell the user the signal is ready. |
| Saved | Save button pressed | Change the button label to Intention saved and unlock the next-action copy. |
| Edited after save | Text changes after save | Return to draftable so stale fit briefs are not implied. |
Expo UI boundary
Use Expo UI when the control maps cleanly to a native iOS input or action. Keep React Native for
outer layout, navigation, scrolling, keyboard handling, and custom Clay cards.
Host matchContentswraps the native form panel.TextInputcaptures the intention.Pickerselects the opportunity lane.Slidercaptures readiness.Switchcaptures the consent boundary.Buttonsaves the first intention.
Pressable surfaces until a native component clearly improves the interaction.
Design implementation
The mobile capture route uses the ClayDESIGN.md system directly:
apps/mobile/lib/clay-design.tsowns the mobile token layer: cream paper, white panels, almost-black text, acid-lime momentum, electric-purple personality, tomato-orange action, clay-pink support, warm-taupe material cues, dark-plum private panels, 8px product radii, and the 4px spacing scale.apps/mobile/components/native-capture-form.tsxis the Expo UI island. It wraps the native form controls in aHostseeded with acid lime so the first screen keeps one dominant action accent.apps/mobile/components/personality-signal-cards.tsxstays React Native because selected, pressed, and personality-signal feedback are Clay-specific interaction states.apps/mobile/components/next-action-panel.tsxuses dark plum for the private handoff and keeps the consent state explicit with text, not color alone.apps/mobile/components/clay-profile-group.tsxprovides a lightweight handmade profile group for the first capture slice. It is decorative, equal-profile, palette-flexible, and must not encode readiness, privacy, mood, or hierarchy.
Haptic feedback
Clay mobile uses Pulsar haptics for meaningful capture-state changes, not passive page chrome or every text keystroke.| Interaction | Haptic event | Intent |
|---|---|---|
| Save first intention | intentionSaved | Confirm the first concrete signal was submitted. |
| Change opportunity lane | opportunityLaneChanged | Acknowledge the selected opportunity category changed. |
| Move readiness step | readinessChanged | Mark each discrete readiness value change. |
| Toggle consent boundary | playConsentBoundaryHaptic(...) | Distinguish translated-only sharing from a loosened boundary. |
| Select personality signal | personalitySignalSelected | Confirm the custom Clay card selection changed. |
apps/mobile/lib/clay-haptics.ts so route files use product-level
events instead of raw preset names. Underneath, the helper maps those events to Pulsar presets
(Propel, Ping, Snap, Latch, plus the system selection pattern) and preloads them on app
start so the first haptic never warms up cold.
Next action contract
After save, the screen should move from capture to action:Build order
- Keep the first capture flow narrow and reliable.
- Add focused loading and error states before connecting recommendations or mutations.
- Extract reusable card/form components only after a second Clay screen needs the same interaction.
- Verify Pulsar haptics on an iOS simulator or device path after native prebuild.
- Connect backend-generated fit briefs only after the API contract exists in
apps/specs/backend/api.
Related
Companion experience
The proactive voice model that the captured signals feed into.
Curious pet memory
Where captured signals become durable, editable personal knowledges.
User experience flows
Flow 1 — Capture an intention — the broader story this screen implements.
Consent
Why the consent boundary switch defaults to translated fit signals only.

