The design pack is the source of truth for layout and copy:
the clickable pack. This page is what a developer needs that the
pack cannot show — the token map, the navigation delta against the current
RootNavigator, and the API gaps the design assumes.
conversite-ios → rename
Branch cole/ios-companion-phase1-staging-build-20260721
The shipped app is Conversite-era. Three tabs, one of them a person's name, and a screen no tab can reach:
| Today | File | Becomes |
|---|---|---|
| Trevor tab | HomeScreen.tsx |
Home — Needs You queue + handled-today receipts + today's bookings glance |
| Activity tab | InboxScreen.tsx |
Chats — conversations list, with a live marker |
| Site tab | SettingsScreen.tsx |
Split: Settings (behind the gear) and Your site (a glance, inside Settings) |
| Thread | ThreadScreen.tsx |
Thread — plus Join & take over, the takeover banner, and long-thread collapse |
| Leads (orphaned) | LeadsScreen.tsx |
Delete. Leads were derived from thread profileFacts; the honest
surface is Customers, which is a real list of people, not an inferred score |
| Sign in | SignInScreen.tsx |
Sign in + a new First run (calendar, cutoff, notifications) |
That includes the tab label, the app name, bundle identifier strings shown to users, push copy, and the sign-in screen. The pack's check suite fails if either word appears anywhere in the rendered app.
Current: a 3-tab createBottomTabNavigator with a native stack above it.
Target keeps that shape and changes the contents.
| Level | Screens | Notes |
|---|---|---|
| Auth stack | SignIn → FirstRun | FirstRun is skippable and re-enterable from Settings |
| Tabs (4) | Home · Bookings · Chats · Customers | Bookings and Customers are new. Order is deliberate: it matches how often an owner opens them |
| Pushed (no tab bar) | BookingDetail, Thread, Customer, Notifications, Settings, Calendar, Site, Conflict | tabBarStyle:{display:'none'} on these routes — the pack hides the tab bar
on every pushed screen so the bottom edge belongs to that screen's one action |
| Modal sheets | Ask Kelbin, Business switcher | Presented as native sheets; the ask sheet is reachable from Home, Bookings, Chats, Customers |
Ported from the marketing site's marketing.css. Same values, new names for the
two roles a website never needed.
| Token | Light | Dark | Use |
|---|---|---|---|
--bg | #FBFAF6 | #101725 | Screen ground |
--card | #FFFEFB | #18202F | Cards, tab bar, fields |
--line | #E9E3DA | #283243 | Hairlines, borders |
--ink | #152033 | #F3F1EC | Text only |
--slate | #697386 | #9AA4B8 | Secondary text |
--indigo | #5B5CEB | #8B8CFF | The one accent |
--indigo-soft | #ECEBFF | #242B4A | Kelbin's chat bubbles |
--strong | #152033 | #2B3550 | Inverse surface — ask bar, your bubbles, count pills |
--on-strong | #FFFEFB | #F5F3EE | Text on --strong |
--on-accent | #FFFFFF | #101725 | Text on --indigo |
--green / --terra / --amber |
#5E8C68 #C97855 #D5A249 | same | Fills only, never text. None clears 4.5:1 as type on either ground |
--ink is a text token.
Anything that fills with it needs its own pair. Filling with --ink
made dark mode flip the ask bar to near-white with near-white text — measured at
1.12:1. That is why --strong / --on-strong exist, and why
in dark the strong surface raises to #2B3550 rather than inverting.
Second trap, native and web alike: color inherits a computed value.
The themed container must re-declare color from the token or text that only
inherits from the root never repaints in dark.
| Role | Face | Size / weight | Where |
|---|---|---|---|
| Display | Newsreader 500 | 25–27 / 1.15 | Greeting, screen titles, sheet titles. Never inside a list row |
| Body | Figtree 400–650 | 13.5–15 | Everything else |
| Label | Figtree 800 | 11 / .10em, uppercase | Section labels, bylines |
| Numerals | Figtree, tabular-nums | — | Times, prices, counts — anything that lines up in a column |
Spacing is a 4px grid; radii are 11 (buttons) / 14–15 (cards) / 22 (sheets) / 99 (pills). Minimum tap target is 44px — the first draft shipped 36px and the suite now fails under 40.
Full rationale sits beside each screen in the pack. The decisions a developer needs to preserve:
Written against what conversite-api exposes today. Each of these is a build
dependency, not a design nicety.
| Needs | Status today | Gap |
|---|---|---|
| Needs You queue | Does not exist | New. A typed list of pending owner decisions (reschedule inside cutoff, unanswered question, staged site change, conflict) with a reason string, and approve/decline endpoints. The reason string is required — the UI has nowhere to invent it |
| Handled-today receipts | Does not exist | New. An append-only activity feed of completed agent actions with timestamps, scoped to the business and the day |
| Bookings | Not in the mobile client | List by day, booking detail, reschedule/cancel, and free-gap computation (the agenda renders gaps, so either the API returns them or the client needs bookable hours + buffer) |
| Booking ↔ conversation link | Unknown | Both directions. A booking must carry the thread that produced it |
| Customers | Only derived profileFacts via
agentSetting |
A real customer entity with visit history and next booking, searchable server-side, plus CSV export (emailed, not downloaded — the viewer cannot save files) |
| Multi-business | Single site assumed | List of businesses for the signed-in owner, and every call scoped by business. This is the biggest structural gap |
| Calendar | Not exposed to mobile | Connection status, calendar list, which calendar receives bookings, bookable hours, buffer, and the cutoff value |
| Push | device_tokens + notifyVisitorArrived exist |
Extend to the Needs You classes; the design promises "roughly twice a week", so arrival-of-a-visitor must not be a push by default |
| Site status | Not exposed to mobile | Live URL, last published, and the list of staged changes with a publish action |
| Takeover | Partially exists | Owner join, owner send, and release-back-to-Kelbin, with the socket emitting on owner replies (today it only emits on host replies) |
| Offline | None | A last-sync timestamp and a queue for decisions made offline |
Track B of the 2026-07-07 launch added POST /auth/mobile/signin (bearer in
body) and an AuthGuard bearer fallback, because the web flow is cookie-only. The redesign
changes none of that.
The pack ships with a Playwright suite (acheck.mjs, 39 checks) covering the four
marketing promises, shell-surface parity, tab set, tap targets, sideways scroll on every
screen, dark-mode contrast ratios computed in-page, and distinct Kelbin portraits. Key checks
were mutation-tested — reintroducing the flipping fill, the 36px tap target and a
wrong-but-loadable image path each failed the suite as they should.
Assets: kelbin-avatar.webp and
kelbin-greet.webp are portraits 3 and 1 of the supplied set — deliberately
not any of the four used on the marketing site.