← Projects
Design case study

BloomScan

Turn a single photo into an identifiable plant profile—care and safety included—without burying people in botanical databases.

BloomScan interface showing scan flow and result layout
Primary flow: upload → analysis state → structured result with care cues.
RoleFront-end · UI · flow
TimelineCourse-scale build
ToolsReact · TypeScript
TypeWeb app · identification

Why this exists

Problem

Plant ID apps often dump Latin names and long care articles before answering the simple question: “What is this, and is it safe on my balcony?” That mismatch makes the result feel technical instead of actionable.

BloomScan was framed around immediacy: one photo in, a structured profile out—identification, care basics, and safety signals in a scan-friendly layout.

Intent

Goals

Ownership

Role & scope

What I owned

Screen structure for upload, loading, success, and error paths; presentation of results; spacing and hierarchy so dense plant data stays scannable.

Scope & constraints

In scope: responsive layout, component states, copy tone for errors and empty uploads.

Out of scope: training a new vision model from scratch or building a full plant encyclopedia backend.

How the work moved

Process overview

Same rhythm as other work on this portfolio: frame the user job, map states, design screens, then tighten with a running build.

  1. 01Frame — Define the “happy path” and the failure states users actually hit (bad lighting, wrong file).
  2. 02Map — Wire upload → processing → result so the UI never leaves the user guessing what the app is doing.
  3. 03Design — Lock a card system for species + care + safety.
  4. 04Refine — Reduce chrome; test on small widths where one-handed use matters.

Framing

Research & insights

Informal review of existing plant apps and a few hallway conversations—not a formal study. The pattern was consistent: people screenshot results, they do not read five paragraphs.

Intentional choices

Key design decisions

Structure

Designing the identification pipeline

From a design angle, the product is a pipeline: image in, normalized response out, then a presentation layer that turns raw labels into a profile people can act on. The UI’s job is to make each stage legible—not to expose every technical detail.

Request → profile (simplified)

The interface mirrors that sequence so users always know whether they are waiting on upload, inference, or rendering. That alignment is what keeps the experience calm when latency exists.

async function analyzePhoto(file) {
  setStatus("processing");
  const raw = await requestIdentification(file);
  return mapToProfile(raw);
}

Upload → Service → Structured UI

Evolution

Iteration & refinement

Early layouts leaned on a single scrolling column. Later passes separated scan, status, and result so each state had breathing room and clearer primary actions.

BloomScan UI after layout refinement
Same build, tightened hierarchy: analysis and result regions read as distinct steps.

Outcome

Final product

BloomScan final interface
Shipped prototype: photo, action, and structured result on a single calm surface.

Implementation

Build snapshot

The front end is built as components that mirror the flow above—so state changes in code line up with what users see between upload and profile.

BloomScan React component structure excerpt
Representative structure from the repo.

Closing

Reflection & next steps

Insight: The biggest win was treating latency as a first-class design problem—without that middle state, the rest of the UI feels untrustworthy no matter how polished the result card is.

Tradeoff: A thinner feature set meant less “wow” on paper, but it kept the story honest for a student timeline.

Next: Test with a handful of non-expert users on real garden photos; add explicit accessibility review for color-only cues; document confidence thresholds in the UI copy.