TenantMate — Stitch v2.1 vs Built Screen Audit

Run: 2026-05-17. 19 screens audited (18 Stitch sources + 1 built-only). Comparison axes: purpose match, structure, styling, copy. Each screen marked match / partial / divergent / n/a. Stitch project: 11626845676710860760 ("TenantMate All Screens v2.1"). Built state: master 9e055ad; KEEP list at docs/05-design/screen-architecture.md §119 (added 2026-05-16, #606).

Re-run of the 2026-05-16 audit after the #605 convergence umbrella closed. Track what shipped: 13 sub-issues across Tranches I–III merged on 2026-05-17. KEEP list landed in docs/05-design/screen-architecture.md via #606 ahead of this work, codifying the divergences that should not be scored against Stitch (Auth two-page split, Profile/popover, Communications hub→detail, Occupy data cards, Dashboard summary cards, Search Insights Soon badges, Move In/Out copy).

TL;DR

The #605 convergence umbrella moved eight screens up the severity ladder. The three previously-divergent screens (3b Property Report, 9 Documents) and most of the previously-partial schema-blocked screens (8 References, 11 Communications, 12 Key Contacts, 13 Advice, 14 App Feedback, 15 Profile) now reflect Stitch's intent. The remaining gaps are all product-decision deferrals tracked under Tranches IV (long pole) and V (parked) of #605, plus the standing KEEP-list divergences from #606. Occupy is the sole remaining divergent screen — and it's a deliberate KEEP item, not an audit gap.

13
match
4
partial
1
divergent (KEEP)
1
n/a (no Stitch source)
19
total

Summary

match built reflects Stitch's intent with mechanical adaptation  ·  partial covers primary use; omits secondary affordances or has materially-different layout  ·  divergent same problem, structurally different layout  ·  n/a no Stitch source
#ScreenSeverityBuilt pathOne-liner
0Splash Screenmatchsrc/components/Splash.tsxTransient render-state; tagline dropped (#610), swipe-up affordance added on coarse-pointer devices (#587 / #591). KEEP-listed.
1Authenticationpartialsrc/pages/SignInPage.tsx + RegisterPage.tsxTwo-page split is KEEP-listed; minor “Contact Support” footer link still absent.
2Dashboard Updatedmatchsrc/pages/DashboardPage.tsxDeposit tile restored in bento (#596) with real protected-status caption; Repairs moved to a summary card below.
3aSearch Insights Updatedmatchsrc/pages/SearchInsightsPage.tsxStitch's 6-tile preview kept, plus the legacy HomePage substance (recent reports, aggregate-action vote).
3bProperty Reportmatchsrc/pages/ReportPage.tsxCosmetic re-port to v2.1 tokens (#597) + 6-tile signals grid with verdict badges (#599). Narrative + paywall remain post-MVP.
4Tenancy hubn/asrc/pages/TenancyHubPage.tsxNo Stitch source. Built as a row-list directory mirroring Profile's hub pattern (per #558).
4aStart Tenancypartialsrc/pages/StartTenancyPage.tsxManual form replaces Stitch's upload-the-agreement / AI-extracts flow. Tranche IV of #605.
4bMove In Review Updatedpartialsrc/pages/MoveInPage.tsxKeys + Issues-Log tiles swapped for Tenancy Agreement + Compliance Documents; exit_captures-class items deferred to Tranche IV.
5Occupancydivergentsrc/pages/OccupyPage.tsxKEEP-listed: 7 data-bearing summary cards in place of Stitch's 6-tile nav pad. Revisit when per-pack screens land.
6Move Out Review Updatedpartialsrc/pages/MoveOutPage.tsxKeys/Meters/Issues/Comparison live in exit_captures JSON; flagged via HelpInfoCard until the capture flow lands (Tranche IV).
7Deposit Management Updatedpartialsrc/pages/DepositManagementPage.tsxGenerate-PDF preserved as disabled “Soon” — export pipeline parked (Tranche V).
8Referencesmatchsrc/pages/ReferencesPage.tsxStructured Reference Profile stats panel landed (#598) with sample-size-aware empty states.
9Documentsmatchsrc/pages/DocumentsPage.tsxACTIVE / PRE-TENANCY / ARCHIVED filter pills shipped (#593); URL-roundtripped ?stage= filter.
10Tenancy Timeline Updatedmatchsrc/pages/TimelinePage.tsxVertical-rail timeline matches. Stitch's “Rent Due in 3 days” upcoming card not surfaced (feed is historical).
11Communications & Maintenancematchsrc/pages/MessagesPage.tsxMultipart attachments shipped (#604); hub→detail layout is KEEP-listed.
12Key Contactsmatchsrc/pages/KeyContactsPage.tsxPhone/email rows + freeholder + management_company party types (#592). “Draft a Letter” CTA wired to letter templates (#602).
13Guidance Library / Advicematchsrc/pages/AdvicePage.tsx + ArticlePage.tsxPer-stage ContextBanner (#601), Letter Templates rail (#602), External Support rail (#603).
14App Feedbackmatchsrc/pages/FeedbackPage.tsxScreenshot upload zone + thumbnail preview shipped (#595) with multipart submission path.
15Profilematchsrc/pages/ProfilePage.tsxAvatar + member-since (#594), Notifications + Biometric Login toggles (#600). Tenancy switcher stays in toolbar popover (KEEP-listed).

Findings by screen

0 Splash Screen

match
Stitch 07f66b97fa1641028bcc02f47ca0b073  ·  Built tenantmate-app/src/components/Splash.tsx
Purpose match: yes — branded boot/loading state. Splash now ships in two modes: presentational (renders while useCurrentPrincipal() is in flight) and dismissible (lingers on coarse-pointer devices until the user swipes up). Desktop / fine-pointer never sees the splash at all (#609).

Structure

Both: centered brand glyph + “TenantMate” wordmark. Built drops the tagline and the spinner (#610). In dismissible mode (#587 / #591) a swipe-up chevron + “SWIPE UP TO CONTINUE” affordance pins to the bottom; a focus-visible “Continue to sign in” button gives keyboard / AT users the same exit. Stitch's “Get started” CTA and “VERSION 2.4.0” footer remain intentionally omitted.

Styling

Built leans atmospheric: full-bleed bg-primary canvas, text-on-primary, two blurred glow blobs, 80px home-outline icon in a glowing 128px disc with shadow ring. Swipe-up affordance uses animate-bounce chevron + font-label-caps tracking-wider strapline.

Copy

Wordmark “TenantMate” identical. Stitch tagline “Transparent insights for the modern tenant” dropped in #610. “SWIPE UP TO CONTINUE” / “Continue to sign in” (keyboard fallback) are built additions for dismissible mode. aria-label “Loading TenantMate” preserved for AT in presentational mode.

Key divergences

  • No “Get started” CTA — deliberate (transient render-state, not a marketing destination); KEEP-listed
  • No version footer
  • No tagline (changed in #610 — product preference)
  • Coarse-pointer-only display (#609) — desktop skips the splash entirely
Carry-forward: Native Capacitor splash artwork (per #583) still left untouched until final art lands. Comment in Splash.tsx documents both the CTA omission and the dismissible-mode rationale.

1 Authentication

partial
Stitch 1285890783c3405c805e1570fd2c58ee  ·  Built tenantmate-app/src/pages/SignInPage.tsx + RegisterPage.tsx
Purpose match: yes — sign-in + create-account for email/password auth. Stitch presents a single screen with a tab toggle plus a marketing-side “Account preview”; built splits into two routes that the app-level state machine toggles via onWantRegister / onWantSignIn callbacks. The two-page split is KEEP-listed.

Structure

Stitch: one screen, tab-toggle between modes, email + password, “Forgot password?”, terms checkbox, password-strength affordance, “Contact Support” footer. Built: two separate AuthShell+AuthCard pages. SignInPage has Forgot link, resend-verify-email, error switching across rate-limit / lockout / account-state. RegisterPage has terms checkbox + post-submit “Check your email” success state.

Styling

Stitch Material card, deep-teal primary, Manrope/Inter, uppercase labels. Built matches well: bg-primary, Material symbols (mail/lock/visibility/arrow_forward), font-label-caps via tokens, surface-container-low inputs, primary CTA with shadow and scale-on-press. Density + hierarchy close.

Copy

Stitch labels “EMAIL ADDRESS”, “PASSWORD”, “Forgot password?”, “I agree to the Terms of Service and Privacy Policy.” — preserved verbatim. Built adds “Welcome back” / “Create your account”, inline hint “Minimum 8 characters. We block passwords from known-breach lists.”, resend-link copy.

Key divergences

  • Tabbed single-screen → two-page split (state-machine toggle) — KEEP-listed
  • No password-strength meter — strength enforced server-side via breach-list rejection (#480)
  • No “Contact Support” footer link — minor unresolved gap
  • Adds verify-resend + “Check your email” success state not in Stitch (Rodauth flow)
Carry-forward: Resend copy intentionally neutral pending #528 (verify-account-resend enumeration leak). The only closeable gap here is the Contact Support footer link; not in scope of #605.

2 Dashboard Updated

match
Stitch 04f38c5267e646c6b8d1e3f22ff2c8ad  ·  Built tenantmate-app/src/pages/DashboardPage.tsx
Purpose match: yes — at-a-glance overview after sign-in. Stitch lays it out as a hero CTA + bento grid; built keeps the hero + bento and adds real per-domain summary cards so the screen answers “what needs attention?” without N round-trips. The summary cards are KEEP-listed as additive.

Structure

Stitch: “Start new tenancy” hero + “Overview / LIVE TRACKING” header + bento grid of 4 tiles (Search / Tenancy / Deposit / Advice) + 4-item bottom nav. Built mirrors with Search / Tenancy / Deposit / Advice (Deposit tile back in after #596 wired deposit_summary), then 5 summary cards (Tenancy / Deposit / Repairs / Notices / Recent Activity). Real badge counts from /api/v1/dashboard. Repairs is no longer in the bento — it surfaces as a card below per the Stitch shape.

Styling

Stitch Material bento with rounded-2xl tiles, primary teal accents. Built mirrors: aspect-square bento tiles with primary-container/20 bg, label-caps, error-red badge bubble for counts, primary CTA hero with shadow-lg. Deposit tile icon switches to shield-checkmark when protected, otherwise wallet. Card pattern (rounded-xl + outline-variant + shadow-sm) consistent throughout.

Copy

Stitch verbatim: “Start new tenancy”, “Overview”, “LIVE TRACKING”, tile labels “SEARCH/TENANCY/DEPOSIT/ADVICE”. Deposit tile caption is real-data-driven: “Protected” / “Returned” / “Disputed” / “Deducted” / “Not protected” / “Not recorded”. DepositSummaryCard renders amount + scheme + reference + protected-on.

Key divergences

  • Built adds 5 data-bearing summary cards below the bento not present in Stitch — KEEP-listed as additive
Carry-forward: Closed by #596 / PR #612 — the Deposit tile is honest (renders “Not recorded” when no deposit_summary). No remaining gap.

3a Search Insights Updated

match
Stitch d9be8aef1e654df1a53afe9bd30e1346  ·  Built tenantmate-app/src/pages/SearchInsightsPage.tsx
Purpose match: yes — entry point for running a property report. Stitch is mostly an aspirational marketing surface (search field + 6-tile signal preview); built keeps that surface and additionally carries the substance from the legacy HomePage (tenancy banner, aggregate-action voting, real create-report form, recent reports).

Structure

Stitch: header + Search input + 6-tile signals bento (EPC / Broadband / Council Tax / Crime / Schools / Flood Risk) + bottom nav. Built: account/tenancy banner → “Search a property” → SignalsBento (same 6 tiles, with Live/Soon badges) → PendingAggregateActions → form (postcode + optional line-1) → “Recent reports” list with cache fallback. Order + tile set match Stitch; built adds the actual report-creation interaction.

Styling

Stitch card grid, teal icons in circular wells. Built mirrors: 2-col grid, 40px primary-container/30 icon discs, label-caps tile titles, body-sm captions, “Soon” chip on Broadband + Schools. Recent-reports list uses surface-container-lowest divided list with chevron-forward.

Copy

Stitch “Enter a postcode or street name to reveal property data.” → built “Enter a postcode (and optional flat / house number) to reveal property data from official sources.”. Tile labels match. Built adds Live/Soon badges, captions like “Energy rating + cost band” and the honest “Soon” on Broadband (Ofcom #264) and Schools. Form CTA “Generate report”.

Key divergences

  • Soon badges on Broadband + Schools tiles — KEEP-listed per feedback_dont_overstate_progress + Ofcom #264
  • Built keeps the aggregate-action voting and recent-reports list from legacy HomePage (Stitch only previews the marketing surface)
  • Search field uses postcode + optional line-1 (matches actual address-resolution stack), not Stitch's freeform “postcode or street name”

3b Property Report

match
Stitch 19ee49bf48b044b1928d33439f262ea2  ·  Built tenantmate-app/src/pages/ReportPage.tsx
Purpose match: yes — surfaces per-source property data for a saved report. Cosmetic re-port to v2.1 tokens (#597) plus the per-source verdict rule engine (#599) reshapes the screen into Stitch's 6-tile signals bento with rounded verdict pills and a legend; the underlying per-source data still drives every tile.

Structure

Stitch: hero with address + narrative summary (“A well-maintained urban flat with excellent connectivity…”) + 6 metric cards (EPC C, Flood Risk Medium, Crime Mixed, Broadband 900 Mbps, Council Tax Band B, Deposit £1,440) with verdict badges (“GOOD/WATCH/NEUTRAL”), plus “Want the full picture?” paywall CTA. Built: pending/failed/cached banners → resolved address heading + timestamp → 6-tile SignalsGrid (EPC / Flood / Crime / Broadband / Council Tax / Deposit) with VerdictBadge + VerdictLegend → flat per-source detail sections beneath. Broadband renders “Coming soon” with missing verdict (Ofcom #264); Deposit renders “Not configured” (no deposit_summary on a property report yet).

Styling

Stitch M3-style cards with bold accent badges. Built now mirrors: rounded-2xl tile containers per-verdict-toned (good/neutral/watch/missing map to surface/icon/text colour-tokens), 40px verdict-toned icon discs, font-status-badge pills, font-label-caps tile labels, font-h3 value text. VerdictLegend documents the four verdict values inline below the grid. Per-source detail sections below the grid remain plain IonList stacks for now.

Copy

Verdict labels are server-derived (verdict_label on each source payload, computed by PropertyDueDiligence::Verdict.derive): EPC “Good” for A–C, “Watch” for D, “Bad” for E–G; Flood inversion of the Environment Agency severity; Crime against a lazy-cached 90-day national baseline. Built drops Stitch's narrative summary and the paywall CTA — both remain post-MVP.

Key divergences

  • No narrative summary (“A well-maintained urban flat with excellent connectivity…”) — copy generation isn't wired
  • No “Want the full picture?” paywall CTA — monetisation tier surfacing parked
  • Broadband + Deposit tiles render as honest “Coming soon” / “Not configured” (per feedback_dont_overstate_progress)
Carry-forward: Closed by #597 / PR #611 (cosmetic re-port to v2.1 tokens) + #599 / PR #619 (per-source verdict rule engine). Narrative summary + paywall are out-of-scope marketing/monetisation surfaces; track under product roadmap, not the screen audit.

4 Tenancy hub

n/a
No Stitch source  ·  Built tenantmate-app/src/pages/TenancyHubPage.tsx
Purpose match: yes — landing page for the tenancy lifecycle. No Stitch frame ships under this name; per #558 the closest reference was “Tenancy Timeline Updated”, used purely for visual tokens not layout.

Structure

Tenancy summary card at top (address / postcode / role / status / type / start / end / rent) for the active membership, with a “Tenancy withdrawn” banner when applicable. Below: “Tenancy Lifecycle” row-list of 8 entries — Start Tenancy, Key Contacts, Documents, Move In, Occupy, Move Out, Deposit Management, References — each with icon + label + description + chevron-forward when routed, “Soon” chip when not. All 8 rows live as of #576.

Styling

Uses bg-white rounded-xl cards, outline-variant borders, primary teal icons, font-label-caps uppercase section labels — fully on the v2.1 design tokens. Hover/disabled states styled. Withdrawn banner uses error-container token. Consistent with the rest of the design system.

Copy

Section headers “Tenancy Lifecycle”. Empty state: “No active tenancy” with “Once you start a tenancy, the address, key dates, and lifecycle steps will live here. Start by running a property report and promoting it into a tenancy.”. Withdrawn copy: “Tenancy withdrawn” / “You no longer have an active role on this tenancy. Records remain visible for audit.”.

Key divergences

  • No Stitch source — design call was to mirror Profile's row-list hub pattern (#558); KEEP-listed
  • TODO in source: co-tenant surfacing deferred until household-members shape lands on Tenancy serializer
Carry-forward: Per #558 / KEEP list: intentionally no Stitch source; revisit if a tenancy-hub Stitch screen lands.

4a Start Tenancy

partial
Stitch 8e02dd6f705949ed9b7ebb402ec93b8d  ·  Built tenantmate-app/src/pages/StartTenancyPage.tsx
Purpose match: yes — capture the tenancy on TenantMate. But the means differ structurally: Stitch is an upload-the-agreement / AI-extracts flow; built is a manual form against POST /property_reports/:id/tenancy because no upload pipeline or extraction service exists. Tracked as Tranche IV (long-pole) of #605.

Structure

Stitch top-to-bottom: hero “GETTING STARTED / Upload your tenancy agreement.” + upload affordance + “ENCRYPTED UPLOAD” reassurance + 3-tile feature trio (Smart Extract / Risk Analysis / Secure Vault). Built: hero “GETTING STARTED / Record your tenancy.” → manual form (Property report picker, Tenancy type, Start/End dates, Monthly rent, Deposit scheme reference) → reassurance block → upload affordance kept as “Coming soon” teaser → feature trio reframed as “On the roadmap”.

Styling

Built matches Stitch's visual language well — bg-secondary-container/20 reassurance block with border-l-4 border-secondary, surface-container-lowest cards, primary CTA with arrow-forward, font-h1/h2 from design tokens. Inputs match Auth pattern. Aspirational sections visually de-emphasised, distinct from active form area.

Copy

Stitch verbatim: “GETTING STARTED”, “Upload your tenancy agreement.”, “Your documents are processed securely and never shared with third parties without your consent.”, “Smart Extract / Risk Analysis / Secure Vault”. Built rewrites hero to “Record your tenancy.” Adds “Coming soon” badge on upload, “On the roadmap” section header. CTA “Start tenancy”.

Key divergences

  • Load-bearing interaction is a manual form, not an upload+AI-extract pipeline (no Active Storage / extraction service wired)
  • Upload affordance preserved visually but flagged “Coming soon”; feature trio reframed as “On the roadmap”
  • Built adds a property-report picker as the first field (Tenancy is linked to an existing Property; PWA has no Property-creation surface)
Carry-forward: #560 callouts: upload pipeline + extraction service deferred under Tranche IV of #605 (long pole — needs ActiveStorage on tenancies + a doc-AI extraction service). Current form path is the only one that ships today.

4b Move In Review Updated

partial
Stitch 61ca24b1d3e949658a5e177a3c9afa9f  ·  Built tenantmate-app/src/pages/MoveInPage.tsx
Purpose match: yes — both capture the move-in walkthrough state across inventory, meters, and evidence. Built adds an explicit walkthrough lifecycle (draft/in_progress/completed/sealed) that Stitch implies but doesn't surface. The intent-driven copy + per-tile primary buttons are KEEP-listed.

Structure

Stitch is a 4-tile RAG grid (Inventory / Keys / Meters / Issues Log) with per-tile CTAs. Built keeps a 4-tile grid but swaps Keys+Issues for Tenancy Agreement + Compliance documents (the packs that actually exist), then adds Start/Seal walkthrough sections, an inline inventory list+form, meter readings list+form, agreement detail, and a 6-row compliance table — far more granular than the Stitch tiles.

Styling

Stitch uses Material chips with bold status pills and right-aligned chevron CTAs per tile. Built uses Ionic shell with v2.1 teal tokens; tiles get coloured left-borders (border-l-primary/tertiary/error) plus icon-bg pills, and the page expands into form-driven sections beneath the grid rather than chevron-deeplinks.

Copy

Stitch microcopy is concrete demo strings (“12 of 15 tasks completed”, “DISPUTE CHARGES”). Built copy is intent-driven: “Record the property as you receive it.”, “Start your move-in walkthrough”, “Seal the walkthrough”, “Inventory is signed and locked for audit.”

Key divergences

  • Stitch Keys + Issues Log tiles replaced by Tenancy Agreement + Compliance documents tiles (no backing packs) — KEEP-listed
  • Built adds explicit walkthrough start/seal lifecycle absent from Stitch
  • Built inlines inventory and meter add-forms rather than deep-linking per-tile CTAs — KEEP-listed (Stitch's per-tile CTAs were demo placeholders)
Carry-forward: Tracked in #568 — Stitch's Keys + Issues-Log tiles have no backing pack; substitution is the agreed direction. Tranche IV of #605 covers any per-tile capture flow when those packs land.

5 Occupancy

divergent
Stitch f8d89bd1aa5441958739552393c7535b  ·  Built tenantmate-app/src/pages/OccupyPage.tsx
Purpose match: yes — both serve as the during-tenancy hub. Built reframes the screen as a content-rich daily-life dashboard because it's the only landing for seven sibling packs (rent / repairs / inspections / notices / harassment / neighbourhood / bills) with no per-pack screens yet. The 7-card layout is KEEP-listed; revisit when per-pack screens land.

Structure

Stitch: tenancy summary header → Rent Tracking card (next-due + annual progress) → 6-tile lifecycle shortcut pad (Legal / Move In / Comms & Maint / Move Out / Timeline / Requests). Built: PageIntro + tenancy summary → RentTrackingCard (next-due, outstanding banner, 3 most-recent payments) → Repairs + Inspections row → Notices & legal → Concerns + Bills row → “Deeper screens on the way” RoadmapHint. Stitch's 6-tile pad is dropped entirely.

Styling

Stitch's tile pad is a clean grid of equal icon-tiles. Built reuses the v2.1 teal Ionic shell with surface-container-lowest cards, primary left-border accents on the summary, and count badges on each card header — denser, more information-per-tile than Stitch's nav-style pad.

Copy

Stitch labels are navigation nouns (“Legal”, “Move In”, “Move Out”, “Timeline”, “Comms & Maint”, “Requests”). Built uses descriptive section names: “Daily life”, “During your tenancy”, “Rent tracking”, “Open repairs”, “Inspections”, “Notices & legal”, “Concerns log”, “Bills”.

Key divergences

  • Stitch's 6-tile lifecycle nav pad replaced by 7 data-rich sub-summary cards plus a roadmap note — KEEP-listed
  • Built surfaces actual aggregates (outstanding pennies, open-repair count, merged harassment+neighbourhood feed) where Stitch shows nav labels only
  • No deep-link affordances — built honestly flags downstream screens as upcoming via RoadmapHint
Carry-forward: Per feedback_dont_overstate_progress + KEEP list: the page deliberately doesn't render dead nav links; the 6 tiles will return when each pack gets its own screen. Tranche V of #605 (parked) tracks when per-pack screens land.

6 Move Out Review Updated

partial
Stitch 6204830209287829414  ·  Built tenantmate-app/src/pages/MoveOutPage.tsx
Purpose match: yes — both wrap up the end-of-tenancy paper trail. Built diverges on tile inventory because Stitch's Keys/Meters/Issues/Comparison live inside the walkthrough's exit_captures JSON rather than as separate entities — a Tranche IV item of #605.

Structure

Stitch: 6 RAG tiles (Checklist / Check Out Report / Keys / Meters / Issues Log / Comparison) + “Ready to finalize?” + “Submit Review” CTA. Built: 4 RAG tiles (Checklist / Check-out report / Forwarding address / Re-letting watch) + FinalizeBanner (“Ready to finalise?” / “Submit move-out review”) + HelpInfoCard explaining the missing Stitch tiles.

Styling

Stitch shows simple status pills (“Action Required”, “Verified”, “Pending”, “3 Issues”, “Watch”) with chevron CTAs. Built uses the same border-l accent + icon-bg + status-badge pattern as Move In, plus per-tile primary buttons (“Start walkthrough”, “Log report received”, “Start 60-day watch”, “Mark given to landlord”) — heavier action density per tile. KEEP-listed.

Copy

Stitch microcopy concrete demo state (“12 of 15 tasks completed”, “DISPUTE CHARGES”, “OPEN VIEWER”). Built intent-driven: “Submit your check-out walkthrough for landlord confirmation”, “Start a window where we'll log any listing-data observations”, “Where should post arrive after you move out?”. HelpInfoCard explicitly says: “Keys, meters and disputes ship next”.

Key divergences

  • Stitch Keys / Meters / Issues / Comparison tiles dropped; gap acknowledged in inline HelpInfoCard rather than rendered inert
  • Built adds Forwarding address + Re-letting watch tiles that Stitch doesn't show
  • “Submit Review” → “Submit move-out review”; Stitch's per-tile CTAs become per-tile primary buttons (KEEP-listed)
Carry-forward: Per #565 callout — Keys/Meters/Issues/Comparison map to MoveOutWalkthrough#exit_captures JSON; intentionally surfaced via HelpInfoCard until the capture flow lands. Tranche IV of #605.

7 Deposit Management Updated

partial
Stitch 7117159aab1840adbaf20b5dfa916f20  ·  Built tenantmate-app/src/pages/DepositManagementPage.tsx
Purpose match: yes — both wrap the deposit lifecycle and frame the dispute. Built drops the Legal/Comms/Timeline/Evidence tiles because they live on other screens, then doubles down on the data the deposit_dispute pack actually owns.

Structure

Stitch: “Deposit Protection Summary” + amount tile (“£425.00”, warning) + 5 info tiles (Proposed Deductions / Legal / Communications / Timeline / Evidence Pack) + “Generate Dispute PDF” CTA. Built: header + DepositSummaryCard (amount + scheme + reference + protected_on + PI served + claimed-against + remaining) + Proposed deductions list+form + Dispute case panel + Dispute costs list+form + disabled “Generate dispute PDF (Soon)”. Adds empty-state NoDeposit flow with “Record deposit” modal.

Styling

Stitch shows uniform info tiles with badge counts (“05 DOCS”, “142 MSG”, “28 FILES”). Built uses v2.1 teal tokens — DepositSummaryCard is a 2-column dl with wallet icon and protected-status pill; deduction rows are border-l-tertiary cards with challengeability badges; dispute card has hammer iconography and a state-advance button. Stitch CTA preserved as a disabled “Soon” button rather than removed.

Copy

Stitch microcopy: “Reviewing 3 separate claim items”, “Verified by TDS & MyDeposits”, “Chronological audit trail”. Built: “Record the protection certificate, track the landlord's proposed deductions, and build your dispute file in one place.” Deduction challengeability labels — “Hard to challenge” / “Worth challenging” / “Very challengeable” — replace Stitch's generic “warning” pills.

Key divergences

  • Stitch Legal / Communications / Timeline / Evidence Pack tiles dropped (live on other screens) — KEEP-listed
  • “Generate Dispute PDF” preserved as disabled “Soon” button — no export endpoint yet (Tranche V of #605)
  • Built adds substantial dispute-case + dispute-costs sub-flows (state machine, recoverable-cost ledger) that Stitch doesn't model
Carry-forward: Per #567 — dropped tiles intentional; disabled PDF preserves Stitch silhouette without implying live export. Export pipeline parked under Tranche V of #605.

8 References

match
Stitch 970dcee5f9fd483db131174fff408df4  ·  Built tenantmate-app/src/pages/ReferencesPage.tsx
Purpose match: yes — both gather reference letters from prior landlords/agents and frame them as a shareable tenant identity asset. The Structured Reference Profile stats panel landed in #598.

Structure

Stitch: “Structured Reference Profile” stats panel (Payment History 100% EXCELLENT / Property Care TOP TIER / Deposit Outcome Full SETTLED) + “Share Reference Link” + Outbound Requests list + “Build Your Tenant Identity” card + “How it works”. Built: header + StructuredReferenceProfile (3 stat tiles backed by GET /api/v1/reference_stats; each tile honours its own sufficient_sample flag and renders “Not enough data yet” with the sample-size threshold beneath when false) + Outbound requests grid + Closed grid + “Request new reference” CTA + “Build your tenant identity” info card.

Styling

Stat tiles use big-number typography (percentage + uppercase descriptor) on a surface-container-lowest rounded-2xl card with category iconography. When sample is insufficient the tile dims to surface-container and shows the threshold copy. Request grid uses standard surface-container-lowest card with avatar circle (mail/business/person icon heuristic), border-l accent by status, and uniform reference cards.

Copy

Backend-driven labels: “EXCELLENT” / “GOOD” / “FAIR” on payment history percentage; “TOP TIER” / “MID TIER” / “NEEDS WORK” on property care; “FULL” / “PARTIAL” / “FORFEITED” on deposit outcome. Insufficient-sample copy: “Not enough data yet” + sample-size threshold (e.g. “Need 3 closed rent periods”). “Build your tenant identity”, “Each successful tenancy adds to the references you can share with your next prospective landlord”, “Request first reference”.

Key divergences

  • Share Reference Link CTA and “How it works” secondary action remain dropped (no destinations)
  • Built groups requests into Outbound + Closed sections; Stitch shows one flat list with consent/response sub-states
Carry-forward: Closed by #598 / PR #620 — stats panel + sample-size-aware empty states shipped. Share Reference Link is a shareable-token surface, not in scope of #605.

9 Documents

match
Stitch 0dc7375fc3ad48a09a82caadd8fb8c06  ·  Built tenantmate-app/src/pages/DocumentsPage.tsx
Purpose match: yes — both are the tenancy document vault. The tenancy_stage enum and matching ACTIVE / PRE-TENANCY / ARCHIVED filter pills landed in #593, closing the dominant Stitch-vs-built gap. Stitch's four fixed compliance slots remain replaced by dynamic grouping (the EvidenceItem model is free-text); this is the smaller residual divergence covered inline by an explanatory help card.

Structure

Stitch: subtitle + search bar + filter pills (“ACTIVE” / “PRE-TENANCY” / “ARCHIVED”) + 4 fixed compliance cards (Tenancy Agreement / EPC / EICR / Inventory) + upload button. Built: heading + SearchInput + cache banner + StageFilterPills (Active / Pre-tenancy / Archived / All) wired to ?stage= URL search-param + dynamic issue_type groups (with “Other documents” catch-all) + DocumentCard list rows + floating FAB + HelpInfoCard.

Styling

Filter pills are rounded-full bg-primary text-on-primary when active, bg-surface-container-low with outline-variant border otherwise — mirrors Stitch's pill treatment. Single-column DocumentCards with primary left-border accent, document-text icon tile, filename + captured/size strapline, and capture_method badge. FAB sits fixed bottom-right.

Copy

Stitch quotes “Secure vault for all your tenancy records”, filter pills “ACTIVE” / “PRE-TENANCY” / “ARCHIVED” preserved verbatim. Stage-scoped empty state: “No documents in this view” / “Nothing in this tenancy stage yet. Try a different filter, or upload a new document.” — distinguished from the truly-empty “No documents yet”.

Key divergences

  • 4 fixed compliance cards (Tenancy Agreement / EPC / EICR / Inventory) replaced by dynamic groups keyed off issue_type with an “Other documents” bucket — flat EvidenceItem model, no fixed-slot schema
  • MISSING / UPLOADED status pills replaced by capture_method (“uploaded” / “photo” / etc.) badges
Carry-forward: Closed by #593 / PR #615 — stage enum + filter pills + URL round-trip shipped. Fixed compliance slots remain an open question (would require a typed-slot extension to EvidenceItem or a separate RequiredDocument model); not currently in scope.

10 Tenancy Timeline Updated

match
Stitch ad0f747c7e854430ac6791eac3e43d5c  ·  Built tenantmate-app/src/pages/TimelinePage.tsx
Purpose match: yes — both render a chronological tenancy event feed from legal setup to move-out. Stitch intro “Track your property journey from legal setup to eventual move-out” ~= built “Track your tenancy from legal setup to eventual move-out. Every event below was recorded by TenantMate as it happened.”

Structure

Built reproduces the Stitch vertical-rail timeline (icon disc + card per event) and day grouping. Adds explicit day headers (“Today”/“Yesterday”/dd mmm yyyy), a “Why a timeline?” help-info card at the foot, and three robust states (no tenancy / loading / empty / error). Stitch's single “Rent Due in 3 days” upcoming/notification card is omitted — built is strictly historical (audits-driven).

Styling

Stitch uses Material vibes with five hard-coded category colours; built maps the same vocabulary (Legal/Move In/Maintenance/Requests/Finance/Disputes/Household) to v2.1 tokens (bg-primary/secondary/tertiary). Density and card prominence match. Bottom-nav stripped (owned by AuthenticatedShell).

Copy

Category labels align (“Legal”, “Move In”, “Maintenance”, “Requests”); Stitch's “Timeline” category becomes built's “Tenancy” bucket. Per-event copy is dynamic (audit summaries) vs Stitch's curated strings like “Tenancy Agreement Signed” / “Boiler Service Scheduled”. Built adds “by {actor_email}” attribution Stitch lacks.

Key divergences

  • Stitch's “Rent Due in 3 days” upcoming/notification card not surfaced — feed is historical only
  • Stitch curated event copy replaced with dynamic audit summaries via 23-row AuditTrail::Summary mapping
  • Built adds a “Why a timeline?” adjudicator-framing card not in Stitch
Carry-forward: Cross-reference #580: AuditTrail::Summary covers Legal/Move In/Move Out/Maintenance/Requests/Finance/Disputes/Household — coverage looks complete; “Upcoming” (rent-due nudge) is the unmapped Stitch concept.

11 Communications & Maintenance

match
Stitch f4fd57e11d7e444ead84b8e41d1a75b4  ·  Built tenantmate-app/src/pages/MessagesPage.tsx
Purpose match: yes — both surface tenant↔landlord/agent/contractor/council conversation. Stitch frames it as “Active Tenancy Thread” for “Flat 14, Ashfield Court”; built reframes as a thread hub. The list→detail hub is KEEP-listed (Rails contract supports multiple threads per tenancy); attachments shipped in #604.

Structure

Stitch shows a single open thread with property header, participants row, mixed-channel bubbles (WhatsApp/SMS/App/Portal), composer with paperclip + camera affordances, and inline image evidence. Built is a list→detail hub: ThreadList of cards → ThreadDetail (back link, participants row, bubbles, composer with paperclip + thumbnail-preview attachment row) → NewThreadModal (subject/channel/participants). CommunicationEntry now has_many_attached :attachments (#604); composer accepts JPEG/PNG/PDF, 10 MB per file, 5 files max per entry. Bubbles render inline images (click-to-fullscreen) and PDFs as inline filename + download link.

Styling

Both use Material/teal vibes; built uses v2.1 tokens. Bubble treatment matches Stitch (rounded, asymmetric corners, ownSide right-align, internal-note style). Image attachments render as 12rem rounded thumbnails that open into a fullscreen lightbox; PDF attachments render as a chip with file icon + filename. Composer paperclip slides up an attachment tray with per-file thumbnail + remove button.

Copy

Built page header is “Messages” not Stitch's “Flat 14, Ashfield Court”. Composer label “New message”. Attachment errors: “Up to {ATTACHMENT_MAX_COUNT} attachments per message.” / “Each attachment must be 10 MB or smaller.” / unsupported type message.

Key divergences

  • List→detail hub vs Stitch's single always-visible thread — KEEP-listed (Rails contract supports multiple threads/tenancy)
  • No “Maintenance” sub-domain — Stitch title implies work-order surface; built reuses comms entries only (Stitch's title is conversational only — KEEP-listed)
  • Channel taxonomy diverges (WhatsApp/SMS/App/Portal → email/letter/phone/in_person/landlord_portal/text_message/other)
Carry-forward: Closed by #604 / PR #625 — multipart attachments + thumbnail preview + inline image / PDF rendering shipped. Hub→detail is KEEP-listed (not a gap to close). Automated-update bot inserts remain post-MVP.

12 Key Contacts

match
Stitch 3989c30407514d82a9742567b3f64777  ·  Built tenantmate-app/src/pages/KeyContactsPage.tsx
Purpose match: yes — both are the formal contact registry for the active tenancy. Stitch intro “Official contact registry for your current tenancy. These details are verified and should be used for all formal correspondence and service of notices.” ~= built “Official contact registry for your current tenancy. Use these details for formal correspondence and service of notices.”. Phone/email + freeholder/management_company party types + DELETE shipped in #592; “Draft a Letter” CTA wired to letter templates in #602.

Structure

Stitch lists four party types (Landlord, Letting Agent, Management Company, Freeholder) with phone, address, badges, and Call/Email/Portal/Raise-Maintenance/Copy-Address actions, plus “Draft a Letter” CTA. Built renders a unified active grid + Archived sub-grid (cards across landlord/agent/contractor/freeholder/management_company/guarantor/deposit_scheme), shows party_type + role + service_address + legal_capacity + phone (tel:) + email (mailto:) + effective dates, and an Add/Edit/Archive modal. The Draft-a-Letter CTA section pulls from useLetterTemplates() and routes to /letters/:slug on pick.

Styling

Both use Material card grid with left-accent colour bar mapped per party type. Built badges show legal_capacity (“Primary owner”, “Sole trader”) where Stitch shows “Primary Owner” / “In Contract” / “ARLA Reg: M0023941”. Phone/email rows render as tel: / mailto: action buttons with phone-portrait / mail iconography. Stitch's portal CTA absent (no per-contact portal_url field — minor residual gap).

Copy

Built party labels now include “Freeholder” and “Management Company” as first-class party types. Built CTA “Add a contact”; the Draft-a-Letter section reads “Start a formal letter against your active tenancy. Choose a template…”. The bottom card no longer apologises for missing phone/email columns — they ship.

Key divergences

  • Stitch's Portal action button absent (no portal_url field on TenancyContact yet — minor residual)
  • Stitch's “Raise Maintenance” action button absent (no work-order pack)
  • Built keeps Archive flow (PATCH effective_to=today) alongside the new DELETE endpoint for canonical-remove
Carry-forward: Closed by #592 / PR #616 (phone/email columns + freeholder/management_company + DELETE) + #602 / PR #627 (Draft-a-Letter CTA wired to letter_templates). Portal URL + Raise-Maintenance action are out-of-scope conveniences, not audit gaps.

13 Guidance Library / Advice

match
Stitch c8e6a7fc40bb4e168894169696c4bf5a  ·  Built tenantmate-app/src/pages/AdvicePage.tsx + ArticlePage.tsx
Purpose match: yes — both are the in-app guidance/advice library. Stitch's three top-level surfaces (Context-Aware Insights / Guidance / Letter Templates / External Support) all ship: stage-driven ContextBanner (#601), Letter Templates rail (#602), External Support rail (#603).

Structure

Stitch ships: “Context-Aware Insights” banner (“You are currently in the Final Month of your agreement”), search, four guidance cards, “Letter Templates” rail (Formal Repair Request / Challenge Rent Increase / Notice of Intent to Move / Deposit Dispute Submission) and “External Support” (Citizens Advice / Shelter / Generation Rent). Built ships: heading + intro + ContextBanner (six tenancy_stage variants — none/pre_tenancy/first_month/occupy/final_month/post_tenancy — each with stage-specific heading + body + priority topics) + SearchInput + topic-grouped article grid (priority topics first per stage, but no topics hidden) + LetterTemplatesRail (live useLetterTemplates() query, routes to /letters/:slug on pick) + ExternalSupportRail (live useExternalSupports() query, grouped by ExternalSupport::CATEGORIES) + HelpInfoCard footer.

Styling

Both use Material/teal card grid with left-accent colour per topic. ContextBanner renders a stage-icon disc + stage-specific heading + body in a surface-container-low rounded-2xl card. LetterTemplatesRail and ExternalSupportRail are sectioned border-l-{topic} card grids matching the existing topic palette. Built topic palette is richer than Stitch's three-bucket FINANCE/MAINTENANCE/LEGAL scheme; the priority ordering is the soft signal, not topic hiding.

Copy

Stitch's “Final Month” copy is one of six stages in built: “You're in the final month of your tenancy” → “We've prioritised the deposit-return and move-out guidance so you can plan the end-of-tenancy walkthrough, evidence the property's condition, and protect your deposit from unfair deductions.” The four seeded letter templates match Stitch's four titles (Formal Repair Request / Challenge Rent Increase / Notice of Intent to Move / Deposit Dispute Submission). External Support directory carries 10 verified-URL seeded entries (Citizens Advice, Shelter, Generation Rent, Crisis, TPO, TDS, DPS, mydeposits, Rent Smart Wales, Scottish Letting Agent Register).

Key divergences

  • Topic taxonomy is broader (multiple topics) than Stitch's 3 colour buckets — soft-prioritised by stage rather than hidden
  • Letter Templates are seeded for England (rent challenge, deposit, notice, repair); Wales / Scotland / NI variations parked
Carry-forward: Closed by #601 / PR #624 (per-stage ContextBanner) + #602 / PR #627 (Letter Templates rail + comm_generation pack) + #603 / PR #626 (External Support rail + reference_data pack). Welsh/Scottish/NI letter templates are jurisdiction work, not audit gaps.

14 App Feedback

match
Stitch f49c83b025ce41fcac86b8e669d7c9c2  ·  Built tenantmate-app/src/pages/FeedbackPage.tsx
Purpose match: yes — both are a free-text feedback form with auto-attached support context. Screenshot upload + multipart submission shipped in #595.

Structure

Stitch: heading, textarea (“What's on your mind?”), screenshot upload zone (“Tap to upload or drag image here”), auto-attached context block (Build/Route/User/Active Tenancy), Submit Feedback button, footer policy line. Built: heading, textarea with character counter (0 / 10,000), screenshot upload zone + thumbnail preview (JPEG/PNG ≤5 MB; multipart POST /api/v1/feedback), auto-attached context dl, Submit Feedback button, footer policy line, success state with “Thanks for the feedback” + “Send another”. Serializer exposes has_screenshot boolean only (no URL leak).

Styling

Stitch uses Material vibes with a dark inverse-surface metadata block — built mirrors this with bg-inverse-surface text-inverse-on-surface font-mono dl. Upload zone uses a label-wrapped hidden input with a thumbnail when a file is selected (URL.createObjectURL + revoked on cleanup). v2.1 token usage throughout.

Copy

Built heading “Help us improve TenantMate” matches Stitch exactly. Textarea label “What's on your mind?” with descriptive placeholder. Submit label “Submit Feedback” identical. Error copy on unsupported MIME / oversized file. Built still omits the “Thursday-cadence” review info box (avoids overstating SLA — per feedback_dont_overstate_progress).

Key divergences

  • No Thursday-cadence review info box (avoids overstating SLA)
  • Built adds character counter (0 / 10,000) Stitch lacks
  • Built renders an explicit post-submit success state vs Stitch's single-state form
Carry-forward: Closed by #595 / PR #613 — ActiveStorage has_one_attached :screenshot + multipart submission + magic-byte sniff + thumbnail preview shipped. Cadence claims remain off the page by choice.

15 Profile

match
Stitch a17d45e881da4751ab1babb7c1dd25de  ·  Built tenantmate-app/src/pages/ProfilePage.tsx
Purpose match: yes — both are the account-self-management surface. Avatar + member-since shipped in #594; Notifications + Biometric Login toggles (backed by account_preferences JSONB) shipped in #600. Tenancy switcher + sign-out remain in the AppToolbar popover — KEEP-listed.

Structure

Built top-to-bottom: Avatar circle (click-to-upload, JPEG/PNG ≤5 MB via PUT/DELETE /api/v1/me/avatar) + email + “Member since {Month YYYY}” + account status + tenancy badge → Preferences section (Notifications toggle + Biometric Login toggle, both backed by the JSONB account_preferences column with per-key audit expansion via PATCH /api/v1/me/preferences) → “Security & Login” section (Change email / Change password rows) → “Account Actions” (Close account) + build SHA.

Styling

Avatar is a 24x24 rounded-full bg-surface-container button with hover-opacity; renders img when avatar_url is present, otherwise a camera-outline icon. Preferences card is a bg-white rounded-xl border border-outline-variant two-row block with PreferenceToggleRow components (icon + heading + sub + Switch). Security / danger rows use the v2.1 token pattern (bg-error/border-error/20 on close-account hover).

Copy

Avatar aria-label “Change profile photo” / “Add profile photo”. Member-since renders as “Member since {Month YYYY}” from account.created_at. Notifications sub: “Send me push and email updates about my tenancy.” Biometric Login sub: “Use Face ID, Touch ID or device biometrics to sign in. Saved preference; native enablement coming soon.” (intent-only at the schema layer; native enablement parked). Close-account warning: “Permanently close your TenantMate account. Saved records remain for audit; you won't be able to sign back in with this email.”

Key divergences

  • Biometric Login toggle is intent-only — the preference saves to account_preferences, but the native enablement hook isn't wired yet
  • Tenancy switcher + sign-out intentionally NOT duplicated here — KEEP-listed (both live in the AppToolbar popover)
  • Built close-account copy preserves audit records (“saved records remain for audit”) vs Stitch's stronger “permanently remove” — more accurate to the account state machine
Carry-forward: Closed by #594 / PR #617 (avatar + member-since) + #600 / PR #622 (account_preferences + toggle UI). Biometric native-enablement is a Capacitor plugin follow-up, not a screen-audit gap.

Delta vs the 2026-05-16 audit

The #605 convergence umbrella moved eight screens up the severity ladder; one screen (Splash) saw structural-but-deliberate change unrelated to #605 (#587 / #591 / #609 / #610) and is unchanged in severity.

#ScreenWasNowClosing PRNote
3bProperty Reportdivergentmatch#597 / #611, #599 / #619Cosmetic re-port to v2.1 tokens + 6-tile signals grid + per-source verdict rule engine. Narrative + paywall remain out-of-scope marketing/monetisation, not audit gaps.
9Documentsdivergentmatch#593 / #615ACTIVE / PRE-TENANCY / ARCHIVED filter pills shipped with URL-roundtrip ?stage=. Dynamic issue_type grouping retained (4-fixed-slot model would need separate schema work).
8Referencespartialmatch#598 / #620Structured Reference Profile stats panel landed with per-metric sufficient_sample flag + sample-size empty states.
11Communicationspartialmatch#604 / #625Multipart attachments (JPEG/PNG/PDF, 10 MB × 5 max) + composer paperclip + inline image / PDF rendering. Hub→detail is KEEP-listed.
12Key Contactspartialmatch#592 / #616, #602 / #627Phone/email columns + freeholder + management_company party types + DELETE endpoint + Draft-a-Letter CTA wired to letter templates.
13Advicepartialmatch#601 / #624, #602 / #627, #603 / #626Per-stage ContextBanner (6 stages) + Letter Templates rail (4 seeded England templates) + External Support rail (10 seeded entries).
14App Feedbackpartialmatch#595 / #613Screenshot upload + thumbnail preview + multipart submit; serializer exposes has_screenshot bool only (no URL leak).
15Profilepartialmatch#594 / #617, #600 / #622Avatar + member-since + Notifications + Biometric Login toggles. Tenancy switcher + sign-out stay in the toolbar popover (KEEP-listed).
0Splashmatchmatch#587 / #591, #609, #610No severity change. Tagline dropped + swipe-up affordance added + desktop now skips splash entirely. KEEP-list rationale unchanged.
2Dashboardmatchmatch#596 / #612No severity change but the bento is now honest: Deposit tile back in (was Repairs in the prior audit because no deposit_summary); real protected/disputed/returned status caption.

Outstanding partials / divergent

Four screens remain partial and one divergent. None are convergence gaps closeable inside the #605 umbrella; all trace to product-decision deferrals (Tranches IV / V of #605) or KEEP-list standing decisions.

#ScreenSeverityReason it's not match
1AuthenticationpartialTwo-page split is KEEP-listed; minor Contact Support footer link still absent. Not in scope of #605.
4aStart TenancypartialUpload-the-agreement + AI-extract pipeline is the long-pole; Tranche IV of #605 (needs ActiveStorage on tenancies + a doc-AI extraction service).
4bMove InpartialKeys + Issues-Log tiles depend on packs that don't exist yet. Substitution is intent-driven copy (KEEP-listed) until those packs land — Tranche IV of #605.
5Occupydivergent6-tile lifecycle nav pad replaced by 7 data-bearing summary cards because per-pack screens don't exist yet. KEEP-listed; revisit when per-pack screens land (Tranche V parked).
6Move OutpartialKeys/Meters/Issues/Comparison live in MoveOutWalkthrough#exit_captures JSON; flagged via HelpInfoCard until the capture flow ships — Tranche IV of #605.
7Deposit Managementpartial“Generate Dispute PDF” preserved as disabled “Soon” — export pipeline parked (Tranche V of #605).

How to use this audit

This page is a one-shot snapshot of where the shipped PWA stands against Stitch v2.1 as of 2026-05-17, after the #605 convergence umbrella. The intended uses: