Product design + engineering · 2025–2026

Fresh Greens

Fresh Greens brings community safety knowledge into route planning for Black drivers. I designed and built a working React Native prototype after six interviews, scoring daylight, police presence, wildlife, road conditions, and community reports alongside public map data.

Fresh Greens welcome screen on a phone, with an illustrated Black driver at sunrise.
Role
Solo, design and engineering
Tools
Figma, Illustrator, Claude, React Native, Expo, TypeScript, Supabase
Timeline
Sep 2025 – Jun 2026
Outcome
Working React Native prototype across 26+ screens

Key moves

  • Brought community reports into the same route-scoring pipeline as public map and daylight data, then surfaced the evidence through safety chips and source detail cards.
  • Built the en-route screen around one-thumb reach: turn card, 3D map, and a safety column.
  • Shaped the routing signals from six driver interviews.

Frame1 of 6

Why time and distance were not enough

The Green Book collected community knowledge about where Black travelers could safely stop.

In interviews, Black drivers described routes in terms of more than time and distance: whether roads are lit, whether a town feels safe to stop in, and where police tend to sit. Navigation apps don't account for those signals. Fresh Greens brings them into route selection.

Research2 of 6

What interviews with Black drivers changed

Six interviews with Black drivers across the Southern US, anonymized in synthesis and led with joy and fear before any product questions. The timeline was tight, so the synthesis stayed lean: I pulled the recurring trends into four routing markers.

Moments of joy and fear have a lasting effect on how Black drivers interpret the spaces they inhabit. They stick.
Thesis · Fresh Greens, 2026

What I heard

People time trips around daylight and read lighting as safety. It came up in every interview.

  • Always leaving in the morning.
  • I wouldn't feel comfortable driving at night.
  • The street lights were sparse.

What I designed

The daylight-graded route

Raised by 5 of 6 Black drivers

Community knowledge

Five of six Black drivers described asking family or friends about an unfamiliar place before trusting institutional data.

Community reports weighted alongside public data

Interview-supported

Six Black drivers raised daylight, police presence, wildlife, and road conditions as route-planning signals.

Built in the prototype

A working React Native build scores those four signals, shows route chips, and uses detail cards to explain where a signal came from.

Not yet proven

Whether the recommendations improve safety still needs broader route testing and moderation data.

The zone-flow storyboard, done by hand. The layered route stroke marking a wildlife zone in the last panel was too dense to read at a glance, so it got simplified into the daylight gradient the app uses now.

My first instinct was to stack every safety layer onto the screen. But the interviews also said driving already takes focus, so I pulled most of it back. The safety toolkit stays hidden until a driver reaches for it.

Design3 of 6

Safer route decisions

How each route gets scored

Every route is scored on four things the interviews kept raising: light, police presence, wildlife, and road conditions. A community report feeds those same four markers through the same scoring pipeline as public data. I treated community reports as a first-class route input. The preview shows visible evidence as safety chips, while detail cards explain whether a signal comes from public map data, daylight calculations, traffic incidents, or community reports. That's how the working prototype behaves, not evidence that its recommendation is safer.

OpenStreetMaplighting · landuse · parksOSRMroute geometrySunCalcsolar geometryMapbox SearchdestinationsDOT-511state traffic feedsMapbox incidentsdriving-traffic eventsOpen-Meteoweather + visibilityCommunity reportslocal-first · Supabase when configuredAdapter layerTyped contracts. Each source speaks one shape.Scoring layerPure deterministic function.Same inputs → same routing decision. Reproducible. Inspectable.Screen layerRenders the result. Does not invent it.
Eight data inputs feed an adapter, a deterministic scoring layer, then the screen. Community reports are local-first in the prototype, with a Supabase and Postgres path behind configuration, row-level security, device UUID checks, and moderation views. Scroll the diagram to read it all.

The en-route screen is where it all lands: a turn card, a 3D map that drags with the drive, and a safety column within thumb's reach.

The current en-route prototype in motion on a simulated public route through Harlem.

A calmer interface for a traffic stop

Every prompt in a safety moment is set in Libre Franklin Regular, not Bold. The safety modal asks "What's going on?" The share sheet asks "What's the situation?" A driver who just got pulled over doesn't need "REPORT INCIDENT" shouted at them in a heavier weight than their own thoughts.

That came from the interviews too. People said the moments the app matters most call for a companion. So Bold appears only on facts the app is sure of, like ETA and the /emergency countdown.

Toolkit

Starts with the driver's question.

Four safety paths stay behind one thumb-reachable control, so navigation remains the default state.

The other safety surfaces (/roadside, /unfamiliar, /share-location, /emergency) use the same voice, each a first-class route that works with no signal.

Refine4 of 6

From routing pivot to visual language

The Google Maps feature I moved away from

  1. First pass

    At first I imagined Fresh Greens as a feature inside Google Maps, so v1 wore Google's turn banner and map chrome, with my safety controls down the side. That moved fast, and it capped the whole idea at Google Maps with a safety layer bolted on.

  2. The break

    Rebuilding it as its own app is what let the safety signals become the interface. The route preview grades the road by daylight, reads safety at a glance, flags a station you trust, and carries its own glyphs on the warm surfaces.

Type and color across a trip

The onboarding illustrations, drawn by hand. They set the warm, human register the app opens on, before a single safety signal appears.

I swapped iOS's cool grays for five warm surfaces, all built in OKLCH on the brand-green hue, so the whole app shares one tonal source.

I designed the initial flows in Figma, used Illustrator for the onboarding art, and checked the system in the React Native build. I also used Claude as a critique partner while tightening token names, color roles, and copy rules, mostly to avoid second-guessing the same decisions as the system grew.

Type took three tries. Jost first, then Space Grotesk, then Libre Franklin, which carries the whole hierarchy now. DM Serif Display shows up in exactly six emotional moments, like the emergency reassurance line and the "Thanks for sharing" on /trip-summary. Reserving it for those six is what keeps them landing. Type and color both shift across the session, calm at entry, heightened en-route, resolved at the trip summary.

Color, and the job each one holds

Green carries the work

  • freshgreen#41AD49primary CTA, in-flow links
  • wiltedgreen#326936secondary CTA, headers
  • burntgreen#003F04deep accents

Four reserved safety signals

  • orange#FF9500hazard
  • red#FF3B30alert
  • yellow#FFCC00caution
  • navy#041E49safety affordances

Warm surfaces

  • surfacePage#F4F4EDpage, warm paper
  • surfaceCard#FEFDFBcard surface

Spacing, a 4pt ramp

  • xs4
  • sm8
  • md16
  • lg24
  • xl32
  • xxl48
The tokens themselves, pulled straight from theme/colors.ts and theme/spacing.ts. The spacing scale started implicit and drifted to stragglers at 5, 6, 13, and 18. Making the 4pt ramp explicit is what made that drift easy to catch.

Four colors stay reserved for safety

Green carries every button and link. Red, orange, yellow, and navy are reserved for safety signals, each tied to one meaning, so a red dot always points to something specific. Across 26+ screens, exceptions are documented as carve-outs.

Green, the general interface color, carries every CTA, link, and affordance. Four colors are held to safety-signal work, with the documented carve-outs below.

RedAlert
  • Live audio-capture indicator A pulsing dot for the active recording state on /pulled-over.
  • Destructive-action labels Remove, unpublish, and sign-out.
  • Error copy on light Swaps to the darker severityCritical token for AA (~5.6 : 1 vs red’s ~3.5 : 1).
  • iOS red on dark auth The contrast argument inverts, so default red passes there.
OrangeHazard · caution
  • Community-report pin Marks community observations apart from the institutional feeds.
  • Report FAB The same orange — the contribute-back affordance.
  • Route-preview hazard chips Police presence and low-light segments.
YellowCaution
  • General caution teardrops Map hazards and weather advisories.
  • Trusted-station gold star A documented carve-out from the caution role.
NavySafety affordance
  • En-route Shield Safety mode itself; never data state or sync.
  • /emergency SOS disc Kept distinct from the destructive-action red.

And where color is the data:

DaylightRoute grade
  • Daylight polyline Color IS the data — a per-segment daylight score. A solid → dashed → dotted cadence carries it for WCAG 1.4.1.
The reserved palette on the current en-route screen: navy for the safety Shield, red on the alert, orange on the hazard, a sun glyph for the daylight arrival, and green everywhere else.

The daylight gradient sits outside those four reserved safety colors. On /route-preview, a sun-to-moon dashed band traces what the light will do along the route.

The daylight indicator, held to one job: telling the driver what light they can expect, from now until arrival.

Where color is the signal, a second channel rides with it. On /report, severity pairs a filled warning glyph with the color, so the cue survives for anyone who can't rely on hue (WCAG 1.4.1).

Trust5 of 6

Moderating community reports

Community reports have to earn trust without being treated as less useful by default. Bad-faith and mistaken reports still need to be caught. That's what /moderation is for.

When the Supabase path is configured, reports flow into a moderation view with an investigation panel: the source device, prior and nearby reports, and coordination checks for duplicate IPs and devices. Moderators can review, hide, restore, or remove reports, and those actions are recorded in an audit log.

The report picker lets drivers contribute context without pretending every report is already verified.
The form separates structured place and welcome tags from the driver's optional written experience.

Enters

A report joins the queue

Investigation panel

  • Source device
  • Prior reports at the same spot
  • Nearby reports
  • Coordination: duplicate IPs and devices

Human decision

Reviewed, hidden, restored, or removed

A planned transparency page will publish moderation outcomes so the queue is auditable from outside.

Validate6 of 6

What I built and what still needs proof

Built in the working prototype

  • Route scoring that combines OpenStreetMap zones, DOT-511 where available, Mapbox/OSRM route geometry, SunCalc daylight data, and community reports, with route chips and source-detail explanations
  • Six-surface safety toolkit, with /pulled-over carrying ACLU-sourced guidance, on-device audio capture, and the Held-Question voice
  • Reserved-color system and warm surface ramp across 26+ screens, with 300+ accessibility attributes and 62 Figma variables
  • /moderation queue with per-report investigation panels, coordination detection for IP and device duplicates, Supabase-backed review actions when configured, and a hold-to-remove destructive gesture

Still needs proof

  • Route-quality testing with more Black drivers across regions
  • Live shared-report testing across configured Supabase builds, plus failure-mode testing for mistaken reports, coordinated abuse, and moderation outcomes
  • A public transparency page for /moderation activity and broader device testing beyond iPhone

Building the working app made the gap between a plausible safety feature and a trustworthy one much clearer. I'm confident in the interaction choices I could trace back to interviews, especially the Held-Question rule, route chips, and source detail cards. I'd want broader route testing with Black drivers, moderation outcomes, and failure cases before calling any route safer.

Next project

Navi

I also explored routing through neighborhood discovery and local booking.Read case study
View all work