TenantMate review artefacts · Logical application architecture

TenantMate — 13-Screen Decision Dashboard

Generated 2026-05-10. TenantMate is a UK-tenant-focused property check tool, shipping as a PWA + iOS + Android app from a single codebase (Rails 8 API, Ionic React PWA, Capacitor native shells). Recent revisions: split Transition into Move-In + Move-Out; added References, Guidance Library, Landlord Details; plus a status-aware Dashboard, a sponsored marketplace surface, a best-practice deduction calculator, and multi-tenancy / archive support.

TL;DR — recommended build order

  1. Routing migration first. Move App.tsx from state-switch to IonRouterOutlet. Small, mechanical, unblocks every new screen.
  2. Multi-tenancy data model + Landlord Details. Tenancy is the scope unit every other screen keys off. Landlord Details is a small surface that exercises the model and is statutorily significant (s48 LTA 1987).
  3. Documents pack as first cross-cutting vertical slice. Exercises new Rails pack, RHF+zod, Active Storage / R2.
  4. Dashboard context-awareness next. Renders different content per tenancy lifecycle stage (pre / live / post). Without this the app feels static.
  5. Timeline → Move-In → Comms → Guidance MVP → Occupancy → Move-Out → Deposit (with calculator) → References (after Deposit settles).

Sponsored marketplace and letter-template engine are features layered onto Property Report / Move-In / Guidance respectively — not screens. Voice/STT, Stitch reconciliation, and now Guidance content sourcing + deduction-calculator methodology are cross-cutting decisions to resolve before their dependent screens.

Three-plane model

Architecture splits thirteen screens across three planes plus a cross-cutting Comms surface, cross-cutting voice/STT modes, a programmatically-queried Guidance Library, and an inline sponsored Marketplace.

Workflow (lifecycle order)

  • Property Report — pre-tenancy
  • Move-In
  • Occupancy
  • Move-Out (split from Transition)
  • Deposit
  • References (new — post-deposit)

Events & Notifications

  • Dashboard (status-aware, unread digest)
  • Timeline (full event log)

Information

  • Documents (vault)
  • Landlord Details (new — s48 LTA 1987)
  • Guidance Library (new — content + signposting + letters)
  • Auth (entry)
Cross-cutting surfaces: Comms — one tenancy thread, every party as participant. Voice / STT / walkthrough dictation — Comms + Transition + Occupancy. Guidance — destination screen and programmatically queried from every workflow screen (returns relevant article, signposts, and letter templates). Sponsored marketplace — inline panels on Property Report and Move-In; revenue surface, must be labelled, must not crowd out impartial Guidance. Multi-tenancy with archive — tenancy is the scope unit; profile-popover switcher; archived tenancies visually demoted but reachable.
Workflow Events Information Comms / cross-cutting

Screens

1 · Auth

Shipped
Information Rodauth

Combined sign-in / sign-up. Cookie-based auth; opaque bearer support for native clients later.

Stitch: no coverage — fresh design needed.

Files
SignInPage.tsx, RegisterPage.tsx, useCurrentAccount
Voice/STT
n/a
Build complexity

2 · Dashboard

Partial
Events Hub

Status summary + unified unread digest (notifications + comms). "See all" routes into Timeline (events) or Comms (messages). Status-aware: renders different content by tenancy lifecycle stage — pre-tenancy (search + recent reports), live (rent due, maintenance, unread comms, inspections), post-tenancy (deposit return, references in flight). Multi-tenancy: scopes to active tenancy from profile-popover switcher; archived tenancies reachable but demoted. Currently shipped as HomePage.tsx = search + recent reports (pre-tenancy variant only).

Stitch: Tenant Dashboard (desktop), Tenant Dashboard - Mobile, plus 3 Tenant Hub variants (Grid / Summary / Updated Summary). Closest to our intent: Tenant Dashboard - Mobile.

Depends on
Timeline, Comms, at least one Workflow screen for the digest to be meaningful
Voice/STT
none directly
Build complexity
Why "Partial"
HomePage exists and routes to ReportPage. The unread-digest model and Timeline/Comms deep-links don't yet exist because their target screens don't exist.

3 · Property Report

Shipped
Workflow VERIFY-stage

Pre-tenancy due diligence. Five sources live (Postcodes.io, Police.uk, EPC, Flood, VOA). Cached-data banner on network failure. Sponsored marketplace section (movers, broadband, contents insurance, deposit-replacement products) appears inline — revenue surface, labelled, separated from impartial guidance.

Stitch: Due Diligence (desktop). Useful as a layout reference; ours is shipped on mobile-first Ionic and rendered live data.

Files
ReportPage.tsx, PropertyReportAggregator
Voice/STT
n/a
Open work
Ofcom (#264), self-host RoFRS (#263)
Build complexity
(mostly done)

4 · Move-In

Not started
Workflow Forward-looking baseline Voice walkthrough

Set the baseline for the tenancy: keys received, prescribed information confirmed received, photo inventory of every room, meter readings, working-condition checklist (boiler, smoke alarms, locks). One-day event; low-stress; the goal is "every dispute reference 6 months from now points back here". Counterparty: landlord or agent.

Stitch: Move-In & Docs. Lift checklist + inventory affordances; the docs panel within is split out into our Documents screen.

New pack
move_in
Voice/STT
★ Walkthrough dictation — voice earns its keep. Tenant narrates while photographing; each utterance → inventory line + attached photo.
Depends on
Active Storage / R2 wiring, on-device STT plugin, Landlord Details (counterparty), Documents (prescribed info filing)
Build complexity

5 · Occupancy

Not started
Workflow In-tenancy state

Structured state for the live tenancy: rent ledger, maintenance ticket status, inspections. Conversation lives in Comms; cards deep-link into thread positions.

Stitch: Living & Maintenance (desktop). Lift its rent-status, ticket-board, and inspection affordances; route the conversational triage out to Comms (Stitch keeps it inline).

New pack
occupancy
Voice/STT
STT for ticket descriptions and inspection notes (dictation; audio discarded)
Depends on
Comms (for deep-link), Documents (for inspection PDFs), Timeline (for event surface)
Build complexity

6 · Move-Out

Not started
Workflow Backward-looking settlement Voice walkthrough

Exit settlement: notice given, exit photo inventory, comparison against the Move-In baseline (side-by-side per room), final meter readings, key return, forwarding address. Different mental model from Move-In — adversarial review is in scope. Stretches over weeks; feeds directly into Deposit. Counterparty: landlord, agent, deposit scheme.

Stitch: Move-Out & Deposit. Lift the exit-checklist + comparison affordances; the deposit ledger within is split out into our Deposit screen.

New pack
move_out
Voice/STT
★ Walkthrough dictation — same affordance as Move-In; record what changed since baseline
Depends on
Move-In (for the baseline to compare against), Active Storage / R2, Landlord Details, Deposit (downstream consumer)
Build complexity
— comparison-against-baseline UI is the novel bit

7 · Deposit

Not started
Workflow ADR escalation

Scheme registration + prescribed information at entry; deduction line items with landlord rationale + evidence at exit; per-line accept/reject/counter; ADR escalation status. Best-practice deduction calculator (e.g. light bulb £15–25; sourced from published industry data, refreshed quarterly, labelled "indicative") helps tenants benchmark each line item against fair-wear-vs-betterment frames. Methodology needs solicitor review before launch — wrong numbers worsen adjudication outcomes.

Stitch: Move-Out & Deposit contributes the deposit-ledger half (deduction lines, totals, accept/reject affordances). Lift those into this screen; the move-out half belongs in Transition.

New pack
deposit
Voice/STT
none directly (STT in Comms thread context)
Depends on
Documents (evidence storage), Comms (counterparty negotiation), Move-Out artefacts from Transition
Build complexity
— ADR + monetary handling are the riskiest parts

8 · References (new)

Not started
Workflow Post-tenancy

Lifecycle tail — runs after Deposit settles. Outbound: tenant requests landlord reference for next tenancy; tracks consent, who-it-was-sent-to, response status. Inbound: a future landlord queries us for a reference on a prior tenant; tenant approves/declines per request; we serve a structured response (or a redacted refusal). Consent + retention is GDPR-load-bearing.

Stitch: no coverage — fresh design needed.

New pack
references
Depends on
Landlord Details (reference target), Comms (delivery medium), Documents (signed letter artefact), GDPR retention call
Voice/STT
none
Build complexity
— small UI surface but high consent/GDPR load

9 · Documents

Not started
Information ★ Recommended first

Vault across all stages, filterable. Cross-cutting reference target for every other screen — the cleanest first vertical slice because it has no inbound dependencies on screens not yet built.

Stitch: docs panel inside Move-In & Docs is the closest reference (filename + tag + status). Pull that into a standalone vault screen; no Stitch screen for the cross-stage filter view.

New pack
documents
Voice/STT
none
Depends on
Active Storage + R2 (prod) / MinIO (dev) wiring
First-cut acceptance
upload, list with filter, preview, soft-delete with audit trail
Build complexity

10 · Timeline

Not started
Events Read-model

Chronological projection across all planes. Absorbs the notifications inbox. Same data source as Comms; different read-model.

Stitch: no coverage — fresh design needed.

Backing data
Existing Audited trail on Account + PropertyReport
Voice/STT
renders private voice notes as derived events
Depends on
nothing new — pure read over existing audits
Build complexity

11 · Comms

Not started
Cross-cutting WhatsApp-group metaphor

One thread per tenancy with every party as a participant (tenant, landlord, agent, contractor, scheme, council). Bubbles tagged by sender + medium. Compose for in-app only; email/SMS as read-only summaries.

Stitch: no coverage — fresh design needed. Stitch's workflow screens embed conversation inline; we pulled it out as a cross-cutting surface.

New pack
comms
Voice/STT
★ Voice notes (private + sent — distinct record types, not a flag); STT for compose box
Depends on
on-device STT plugin, GDPR retention call (flag for solicitor), audio storage in R2
Build complexity
— single biggest screen + biggest GDPR surface

12 · Landlord Details (new)

Not started
Information s48 LTA 1987

Per-tenancy register of the parties on the landlord side: name, UK service address (statutory under Landlord and Tenant Act 1987 s48), telephone, registration number where applicable (Rent Smart Wales mandatory; England's letting-agent client-money-protection scheme; Scotland's landlord register). Extends to agent / management company / freeholder where present. Source of truth for letter generation, deposit prescribed-information cross-check, and reference targets.

Stitch: no coverage — fresh design needed.

Lives where
could share tenancy pack with the tenancy model itself, or be its own parties pack
Depends on
Tenancy data model (must exist first)
Statutory note
s48 LTA 1987 — without a UK service address from the landlord, rent is not lawfully due. Surfaces in Deposit + References + letter templates.
Build complexity

13 · Guidance Library (new)

Not started
Information Cross-cutting + Letter templates

Three things in one surface: (1) editorial guidance on UK tenancy topics (deposit dispute, repair obligations, eviction notice response, rent-increase challenge, etc.); (2) support signposting directory (Citizens Advice, Shelter, Generation Rent, council homelessness team, ombudsman, deposit schemes); (3) letter templates with tenancy context auto-filled (landlord name + s48 address + tenancy ref). Same architectural role as Comms: destination screen and programmatically queried — every workflow screen can ask "give me the right guidance + signposts + letters for THIS context".

Stitch: no coverage — fresh design needed.

New pack
guidance
Content sourcing
open question — repo-tracked Markdown, headless CMS, AI-augmented? Editorial accuracy is load-bearing; legal review for each article.
Depends on
Landlord Details (for letter context); content authoring workflow; legal review process
Voice/STT
none directly (STT could power "ask Guidance" in future)
Build complexity
— simple shell, but content + legal review is the real cost

Stitch coverage

Cards above carry an S line where a Stitch screen contributes design references. Stitch's workflow screens are compounds (Move-In + Docs, Move-Out + Deposit) — we de-bundle them.

Stitch screenDeviceMaps toHow we use it
Tenant DashboardDesktopDashboardLayout reference; we ship mobile-first
Tenant Dashboard - MobileMobileDashboard★ Closest match — adapt directly
Tenant Hub - Grid ViewMobileDashboard variantAlt layout exploration; deprioritise
Tenant Hub - SummaryMobileDashboard variantAlt layout exploration; deprioritise
Tenant Hub - Updated SummaryMobileDashboard variantMost recent iteration; cross-check against Tenant Dashboard - Mobile
Due DiligenceDesktopProperty ReportLayout reference (already shipped)
Move-In & DocsDesktopMove-In + DocumentsDe-bundle: checklist/inventory → Move-In; docs panel → Documents
Living & MaintenanceDesktopOccupancyLift rent + ticket + inspection cards; route conversation to Comms
Move-Out & DepositDesktopMove-Out + DepositDe-bundle: move-out checklist → Move-Out; deduction ledger → Deposit

No Stitch coverage: Auth, Documents-as-vault, Timeline, Comms — all need fresh design (Figma or new Stitch generation).

Status snapshot

#ScreenPlaneStatusFirst milestone
1AuthInformationShipped
2DashboardEventsPartialPre-tenancy variant shipped; add live + post variants once tenancy lifecycle data exists; multi-tenancy switcher
3Property ReportWorkflowShippedOfcom + RoFRS sources (#264, #263); sponsored marketplace inline panel
4Move-In (was Transition)WorkflowNot startedChecklist + photo inventory + meter readings; voice walkthrough
5OccupancyWorkflowNot startedMaintenance ticket entry (with STT) + status board
6Move-Out (split from Transition)WorkflowNot startedExit inventory with side-by-side comparison vs Move-In baseline
7DepositWorkflowNot startedScheme registration + prescribed information at entry; deduction calculator after solicitor sign-off
8References (new)WorkflowNot startedOutbound landlord-reference request with consent flow
9DocumentsInformationNot startedUpload + filterable list + preview + soft-delete
10TimelineEventsNot startedChronological event log over existing Audited trail
11CommsCross-cuttingNot startedSingle tenancy thread; in-app messages only; voice notes (private + sent)
12Landlord Details (new)InformationNot startedPer-tenancy landlord record (s48 fields) + agent extension
13Guidance Library (new)Information / Cross-cuttingNot startedEditorial shell + signposting directory + first 3 letter templates

Open questions

Q1 · Which screen first?

With multi-tenancy now foundational, the path of least resistance has shifted: Tenancy data model + Landlord Details first (small, statutory, exercises the model), then Documents.

Recommendation: Tenancy model + Landlord Details first; then Dashboard context-awareness; then Documents. Defer Timeline/Transition until those three are bedded in.

Q6 · Guidance content sourcing

Three viable approaches: repo-tracked Markdown (versioned, simple, slow to update), headless CMS (Sanity/Contentful — collaboration with legal counsel, monthly cost), AI-augmented (LLM drafts, human-in-loop edits — fast but accuracy-load-bearing).

Recommendation: Markdown in repo for v1; legal review per article tracked in PR; revisit CMS once content volume justifies it. AI-drafting only for first-cut, never auto-published.

Q7 · Sponsored vs impartial separation

Marketplace generates revenue; Guidance must remain impartial. Risk: tenant confusion if both surface in the same context (e.g. on Property Report).

Recommendation: Strict visual + label separation. Sponsored panels carry a "Partner" badge and explicit "we earn a commission" line. Guidance content never carries sponsored placements. Editorial firewall is a stated policy, not an after-thought.

Q8 · Deduction calculator launch

Adjudication frames "betterment vs fair wear" precisely. Wrong numbers undermine tenants. Solicitor input needed before launch.

Recommendation: Build calculator UI shell concurrent with Deposit; gate live numbers behind a solicitor-approved methodology + indicative-range labelling + quarterly refresh process. Don't launch the calculator on day one of Deposit.

Q2 · Routing migration

App.tsx is currently a state-switch (no router). Build spec calls for IonRouterOutlet. Doing this before any new screen avoids retrofitting.

Recommendation: Migrate now as a small isolated PR. Touches Auth + HomePage + ReportPage only; mechanical.

Q3 · Design source

Stitch outputs exist for some screens. Figma is canonical per memory. Auth/Documents/Timeline/Comms have no Stitch coverage.

Recommendation: Use Stitch outputs as low-fidelity input only; produce Figma exports as PNG/SVG for canonical reference. Don't block Documents on Figma — its UI is generic enough to ship from a sketch.

Q4 · Stitch reconciliation

Stitch's "Move-In & Docs" and "Move-Out & Deposit" don't map to our split (Transition + separate Documents + separate Deposit).

Recommendation: Treat Stitch's compounds as workflow walkthroughs, not screens. Lift checklist/inventory affordances into Transition; lift their docs panel into Documents; lift their deposit ledger into Deposit. Don't reflexively adopt Stitch naming.

Q5 · Voice/STT scoping

Cross-cuts Comms + Transition + Occupancy. On-device first; biometric-adjacent under GDPR; tenancy chat is evidential. Memory flags solicitor input needed.

Recommendation: Resolve before Transition build (not before Documents). Pin: (a) capacitor speech-recognition plugin, (b) audio storage in Active Storage/R2, (c) Dexie offline-capture queue, (d) flag retention/deletion for solicitor as a decision record. Consider elevating to build spec.

Cross-cutting concerns

ConcernStatusAffected screensResolve before
Routing (IonRouterOutlet)Not startedAllAny new screen
Multi-tenancy data model + archiveNot startedAll workflow + Dashboard + Comms + Documents + TimelineDashboard context-awareness
Active Storage + R2Not startedDocuments, Move-In, Move-Out, Occupancy, Deposit, Comms, ReferencesDocuments
RHF + zod conventionsNot startedEvery form-bearing screenDocuments
On-device STT pluginNot chosenMove-In, Move-Out, Occupancy, CommsMove-In
Audio storage + offline captureNot startedComms, Move-In, Move-OutMove-In
GDPR retention (voice)Flagged for solicitorComms, Move-In, Move-Out, OccupancyComms
Move-In ↔ Move-Out comparison engineNot startedMove-Out, DepositMove-Out
GDPR consent (references)Flagged for solicitorReferencesReferences
Sponsored marketplace data modelNot startedProperty Report, Move-InFirst sponsored panel
Move-In photo inventory as baseline (immutable after sign-off)Not startedMove-In, Move-Out, DepositMove-In sign-off step
Guidance content sourcing (Markdown / CMS / AI)Open questionGuidance Library, every workflow screen (programmatic queries)Guidance MVP
Letter template engineNot startedGuidance Library, surfaces from Deposit + References + OccupancyFirst letter generated
Deduction calculator methodologyFlagged for solicitorDepositDeposit calculator launch
Account-scoped Dexie partitioningShippedAll
Tailwind v4 + design tokensTailwind v4 in; tokens not yet adoptedAllRevisit when 2nd or 3rd screen lands