Skip to content

Repository files navigation

After the Report

An evidence-led examination of what a fixed City of Phoenix missing-persons public-data snapshot can—and cannot—tell us.

Live site: phx-data.com

After the Report homepage

The original application made ten live API requests on every visit and kept the entire interface behind one loading state. Those requests repeatedly scanned the same PostgreSQL data to recalculate results that never changed.

This repository is the redesigned canonical monorepo. PostgreSQL now produces a validated, versioned snapshot at build time; Next.js prerenders the complete report from that snapshot. SQL remains reviewable and reproducible without putting a database cold start in front of every visitor.

What changed

Before Now
Create React App client shell Next.js App Router with static prerendering
10 blocking browser requests No browser request for initial report content
Repeated live aggregate scans Materialized analysis view + exported snapshot
Every chart presented equally Three guided findings and one focused explorer
“Still missing” presented as status Precise “no located date” field-state language
Raw demographic counts Within-group outcome comparison with denominator warning
Default broken CRA test Unit, component, API, desktop, and mobile coverage
Two small disconnected repos One typed workspace for web and data

Repository layout

apps/web/                   Next.js report, static API routes, and components
packages/data/
  generated/dashboard.json Versioned public data contract
  scripts/                  PostgreSQL export command
  sql/                      Normalization and analytical queries
  src/                      Types, validation, and selectors
scripts/                    One-time legacy snapshot capture
tests/e2e/                  Desktop and mobile browser journeys
docs/                       Architecture and decision records

See the architecture document for the request path, data pipeline, tradeoffs, and performance budget.

Local development

Requires Node.js 22 or newer.

npm install
npm run dev

Open http://localhost:3000.

No database or environment variable is required to run, test, or deploy the site. The checked-in snapshot is the application’s public data contract.

Verification

npm run check          # lint, typecheck, coverage, production build
npm run test:e2e       # Chromium desktop + mobile journeys

Coverage thresholds are enforced at 80% for statements, lines, and functions. The current selector and component suite exceeds those thresholds.

Regenerating the data snapshot

Regeneration is deliberately separate from the web request path.

cp .env.example .env
DATABASE_URL=postgresql://... npm run data:export -- --refresh
npm run check

--refresh rebuilds the normalized materialized view before exporting. Without it, the command uses the existing view. The exporter reconciles the outcome bucket total against the KPI record total before replacing the JSON file.

The scripts/capture-legacy-snapshot.mjs command exists only to preserve the last results produced by the retired Express deployment during migration.

Public API

  • GET /api/snapshot — the complete, immutable data contract
  • GET /api/health — deployment and data-mode status

Both routes are prerendered. The report imports the data package directly rather than making an HTTP request to its own API.

Analytical limits

  • Rows are treated as report records, not deduplicated people.
  • “No located date” means exactly that; it is not an independently verified present-day case status.
  • Missing dates and negative date intervals stay in the denominator as unavailable / invalid.
  • Demographic categories reproduce normalized source fields. They are not necessarily self-identified.
  • Without population denominators, the data cannot establish whether a Phoenix demographic group is more likely to be reported missing.
  • This is a fixed snapshot covering January 2016 through July 2025. It is not a live public-safety service.

The source dataset is published through Phoenix Open Data. This independent project is not affiliated with the City of Phoenix or a law enforcement agency.

About

A frontend to help visualize some data published by the Phoenix government. Data source: https://www.phoenixopendata.com/dataset/missing-persons

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages