Cardona CT LabAI Tooling · Design & Accessibility
Climate Risk Intelligence · Duval County, FL

Flood Risk Intelligence Dashboard

A Design Engineering Case Study


Executive Summary

This is a single-file, interactive flood-risk dashboard covering ZIP 32257 (Mandarin, Jacksonville FL) and four surrounding Duval County ZIPs. It's a production-quality, fully responsive tool built as one HTML file (no build step, no framework, no backend), yet it pulls live FEMA hazard data, coordinates three charts, and compares a five-ZIP portfolio.

It has four views: Overview (live data with coordinated charts), Portfolio (five-ZIP comparison), Flood Lookup (live ArcGIS REST queries), and Methodology (FEMA zone classification). The whole thing was built and iterated through an AI-native, bootstrap-file-driven workflow with Claude Code. I built it to demonstrate design-engineering depth, that workflow, and a direct line to the climate-risk intelligence space. It runs at the live demo.

Problem Statement

Flood-risk data is public, but it isn't accessible. FEMA's National Flood Hazard Layer lives behind ArcGIS REST APIs that assume GIS expertise. You need to know which layer to query, how to resolve a place to a polygon, and how to read the zone codes that come back.

The people who make decisions (homebuyers, agents, portfolio managers, lenders) have no clear visual language for differentiating risk. A AE, X-500, and X zone carry meaningfully different profiles: insurance requirements, premium costs, and lender mandates all change between them. FEMA's Map Service Center is accurate and functional, but it's built for lookups, not for weighing options.

The national property-data position in this market is strong; the gap is the intelligence layer, making risk legible at the property and portfolio level. This dashboard is a prototype of that layer.

Technical Architecture

Data layer

Hazard geometry comes from a live ArcGIS REST endpoint (FEMA's National Flood Hazard Layer, Layer 28), with the U.S. Census Geocoder resolving an address into the FIPS code that scopes a live lookup. A seeded dataset of 20 properties in ZIP 32257 (risk scores, zone classifications, pricing, square footage) backs the property views, and the tool falls back to seeded NFHL geography when the live ArcGIS fetch is unavailable, so it never dead-ends. The portfolio spans five ZIPs: 32257 Mandarin, 32256 Deerwood, 32258 Bartram Park, 32065 Orange Park, and 32073 Fleming Island.

Chart layer (Chart.js)

The Overview coordinates three charts: c1, a zone-distribution bar (AE / X-500 / X counts under the active filter); c2, a median-price bar by zone; and c3, a price-vs-risk scatter color-coded by zone. All transitions tween from the current rendered value to the new target: bars and dots never reset to zero. The scatter runs hover:{animationDuration:0}, intersect:true, and hitRadius:6 so hovering doesn't trigger a full point scan on every mouse move.

Metric cards

A custom animateCountUps() reads data-from / data-target (and data-decimals="1" for the average risk score) to tween the card numbers. Before a DOM rebuild it snapshots the current displayed value and passes it as data-from, so the number tweens up or down from wherever it already sits.

Portfolio view

Four synchronized controls (tile cards, the pfC1 bar, the pfC2 scatter, and the comparison-table rows) all call pfTileClick(zip) to set the shared activeZip and rebuild. pfC1 is a stacked AE/X-500/X bar per ZIP, the active one at full opacity and the rest at 20% (hex alpha EE / 33); pfC2 plots risk against median price, the active dot blue (#1B3F6E) and the rest grey, color tweened by a 400ms rAF RGB interpolator, since Chart.js snaps backgroundColor and a manual loop is the only way to animate it.

Flood lookup, theme & responsive

The lookup queries NFHL Layer 28 live for polygon count and zone distribution (FIPS via the Census Geocoder), rendering animated progress fills. Color is a CSS custom-property token system: --surface, --bg, --text, --border, --mg (purple), and the zone colors, driving a dark-default theme persisted to localStorage, with syncThemeIcon() on DOMContentLoaded. The layout reflows at 480px: a Tabler-icon bottom nav replaces the tab bar, the hero meta stacks, the FEMA table drops two columns, and the lookup stats become a 2×2 grid. Getting the breakpoints right meant replacing every hardcoded color with a token.

Design Decisions

Delta animation philosophy

The dashboard never resets a value to zero and counts up. Every transition (bars, counters, scatter dots) captures the current rendered value and tweens to the new target, so the UI feels like it knows where it was. The two-step Chart.js technique makes it reliable: update('none') sets the baseline, then update() animates to it.

Four-control synchronization

Any of four surfaces (tile cards, the bar chart, the scatter, the comparison table) can change the active ZIP, and all route through one pfTileClick(). This wasn't the original plan; it grew iteratively because each surface is a natural place to make a selection. The result reads as coherent rather than hierarchical.

Portfolio emphasis model

All five ZIPs stay visible in the portfolio charts; none collapse. Selection is communicated with opacity (100% active, 20% inactive) and color (blue vs. grey dots). This preserves comparative context while directing attention, a deliberate choice over the common "filter to one" pattern.

Animation lock

The staggered first-build reveal is gated behind a _pfLocked flag that disables the controls and dims the UI (.pf-animating) until it clears at 2200ms. Rapid clicking mid-tween would corrupt the animation state; treating animation as a state rather than decoration, and blocking input during it, is the correct systems decision.

Single-file constraint as feature

One HTML file has no hidden dependencies, no build-pipeline assumptions, and deploys anywhere instantly. It's also the right artifact for sharing: drop it in any browser and it works. The constraint enforces architectural discipline.

Engineering Challenges Solved

What This Demonstrates

The tool is the artifact of an AI-native workflow, built and iterated through bootstrap-file development with Claude Code, where the limiting factor becomes judgment, not typing. It spans the range the work requires: a data pipeline against live government endpoints, API integration with fallbacks, animation systems with hand-written interpolators, responsive layout, design tokens, and accessibility. Every notable choice (the delta animations, the portfolio emphasis model, the four-control synchronization) is deliberate, with a rationale. And it sits squarely on the climate-risk mission: making property risk legible at the interface layer. Production-quality and built in days.

Live Demo

Build
Single HTML file · no build step
Stack
Vanilla JS · Chart.js · FEMA NFHL · Census Geocoder

Open it locally or drop it on any static host; there's nothing to compile.