What Inspired Me

When people think of Hawaiʻi, they picture beaches and lush landscapes but beneath that beauty is a serious environmental challenge. Hawaiʻi is one of the most isolated island chains in the world, which led to extremely high levels of endemism. Many native species evolved without natural predators or competitors, making them especially vulnerable to invasive plants. Today, non-native species outnumber native ones, and invasive plants are among the leading threats to Hawaiʻi’s biodiversity.

Inspired by the need to build public awareness around native and invasive plant species, I created FloraFinder an interactive field guide designed to help users discover, learn about, and log native Hawaiian plants. By increasing accessibility to ecological information, FloraFinder supports conservation efforts and strengthens cultural connections to the land.

What I Learned

This project taught me that environmental tech solutions often require just as much data engineering as frontend development. I learned:

  • How to design and implement a full ETL pipeline from disparate data sources

  • How to integrate external APIs responsibly (e.g., rate limiting with the iNaturalist API)

  • How to manage datatype compatibility between Pandas, MySQL, Prisma, and JavaScript (especially BigInt serialization issues)

  • How to structure a full-stack application with Docker, MySQL, Next.js, and Prisma

  • Most importantly, I learned how to transform messy, incomplete environmental datasets into a structured, usable solution.

How I Built the Project

FloraFinder was built in three major layers:

1️. Data Engineering & ETL (Python + Pandas + GeoPandas) Because no single comprehensive dataset existed, I built a custom database by combining:

  • University of Hawaiʻi plant checklist (PDF + GIS shapefiles)

  • The UH Native Plants website (scraped for detailed plant attributes)

  • The iNaturalist API (photos, taxa IDs, summaries)

Scraped and cleaned plant metadata:

Converted shapefiles (UTM Zone 4N) to WGS84 (EPSG:4326) for Mapbox compatibility (didn't have time to completely implement)

  • Flattened nested JSON/API responses

  • Resolved missing taxa IDs and data mismatches

  • Created normalized and denormalized tables for plant details and images

The final dataset contained 842 unique plants with:

  • Scientific name

  • Conservation & native status

  • GeoJSON range maps

  • Photos & attributions

The data was then loaded into a self-hosted MySQL database using Docker.

2️. Backend (MySQL + Prisma ORM)

Designed relational schemas for plants, images, and users

Used Prisma to interface with the MySQL database

Resolved authentication plugin issues (sha256_password → caching_sha2_password)

Fixed JSON serialization errors caused by BigInt types

3️. Frontend (Next.js + Mapbox + Material UI)

  • Built as a PWA using Next.js

  • Styled with Material UI and Tailwind

  • Integrated Mapbox to visualize plant geographic ranges via GeoJSON

Created core pages:

  • Nearby plant list

  • Plant detail page with gallery and ethnobotanical data

  • User plant list

Users can browse plants, explore conservation status, view habitat and cultural uses, and log the plants they encounter.

Challenges I Faced

Data fragmentation: No single clean dataset existed. I had to merge scraped web data, PDFs, APIs, and GIS files.

GIS complexity: Shapefiles lacked proper CRS metadata and had to be manually assigned and reprojected.

API rate limits: Needed batching logic and request throttling to avoid failed runs.

BigInt serialization errors: JavaScript couldn’t parse MySQL BigInt values, requiring datatype redesign.

Sparse metadata: Many plant attributes were incomplete, forcing prioritization of records with maps and photos.

Mobile preview firewall issues: I had to pivot to web-first testing.

Deployment complexity: Due to the use of docker and node, a more complex vps-based deployment was needed

Each challenge pushed me to think more like a data engineer and systems architect rather than just a frontend developer.

Share this project:

Updates