Solution

How Disaster Compass is architected and implemented — a rules-based, transparent action planner.

System architecture

Three layers, cleanly separated: a React presentation layer, a pure decision engine, and an in-memory state and data layer.

Presentation layer

A React single-page app rendered with TanStack Start (SSR) and routed by file-based TanStack Router. Styling is Tailwind CSS with shadcn/ui (Radix) primitives.

React + TypeScript

Typed, component-driven UI.

TanStack Start + Router

File-based routes under src/routes with SSR and scroll restoration.

Tailwind + shadcn/ui

Utility styling over accessible Radix primitives.

Leaflet map

Renders routes, shelters, and hazard layers over North Creek.

Decision engine

Pure, deterministic functions turn signals into action. No black box: the same inputs always produce the same output, and every score is explained inline.

decideAction (lib/actions.ts)

Maps disaster + household profile to a single go / stay / wait action with a reason.

scoreRoute (lib/scoring.ts)

Scores routes from 100 using named terms — flood, bridge, blocked-road, distance/time penalties and elevation, shelter-fit, accessibility bonuses.

getBestRoute

Selects the highest-scoring non-rejected route, with a safe fallback.

Recovery checklist (lib/recovery.ts)

Builds the phase-aware post-event checklist.

State & data

Root-level React context holds the golden-path flow so decisions survive navigation. The demo runs on in-memory seed data — no live APIs, no database.

ScenarioContext

Disaster selection, route choice, volunteer approval, recovery progress — provided above all routes.

PhaseContext

Tracks the active lifecycle phase (Prepare / Respond / Recover) and resident vs community mode.

Seed data (data/seed.ts)

Households, shelters, routes, and blocked roads for the fictional town of North Creek.

TanStack Query

Caching layer ready for any async data fetching.

Implementation principles

Transparent by construction

Every recommendation shows its inputs, weights, and rejected alternatives. Trust is earned in the UI, not asserted.

Deterministic & testable

The engine is pure functions with unit tests (e.g. recovery.test.ts) — reproducible and easy to verify.

Lifecycle-shaped

Code is organized around Prepare, Respond, and Recover so the product mirrors how emergencies actually unfold.