DEV Community

Cover image for How I Built a Habit Tracker With Living Trees Using React and Firebase at 17
Ali
Ali

Posted on

How I Built a Habit Tracker With Living Trees Using React and Firebase at 17

I'm Ali, 17, CS student. I built JustGoBloom as a portfolio project and it accidentally became a real product with over 100 users. Here's the full technical and personal journey.

The Idea

I wanted a habit tracker that wasn't just checkboxes. The concept: every goal becomes a tree. Show up daily, your tree grows through 9 stages. Miss a day, it wilts. 7 unique tree types, 3 visual modes, team gardens, the works.

The Tech Stack

Frontend: React + Vite. Vite was used over CRA because the dev server is instant and hot reload actually feels hot. The entire app is a single page app with all routing handled in state, no React Router needed since the navigation is simple enough.

Backend: Firebase handles everything. Authentication with email and password, Firestore for the database, Cloud Messaging for push notifications, and Analytics for tracking. Firebase was the right call for a solo project.

Hosting: Vercel with a custom domain through GoDaddy. Auto-deploys on every git push. The entire deploy pipeline is just git push and Vercel handles the rest.

PWA: Service worker for offline support, web app manifest for install prompts. Bloom works as a progressive web app so users can add it to their home screen.

The Tree System

This was the most interesting technical challenge. Each tree is a pure SVG component that renders differently based on its growth stage and tree type.

The TreeSVG component takes a stage index (0 through 5+), a color, a size, and a tree type. Each tree type (Evergreen, Goldleaf, Blossom, Willow, Sage, Summit, Ironwood) has unique canopy shapes at every stage. Blossom trees have heart-shaped leaves with pink flowers. Goldleaf uses triangular polygons. Willow has drooping branch paths.

The color system uses HSL manipulation to create depth. A darken function converts the base color to HSL, reduces the lightness, and converts back to hex. This gives each tree canopy lighter and darker leaf clusters without needing separate color definitions for every tree type. One base color in, automatic shading out.

The Streak System

The streak calculation handles both daily and weekly goals differently.

For daily goals, it walks backwards from today counting consecutive days with check-offs. If today or yesterday has a check-off, the streak is alive.

For weekly goals (like "gym 3x per week"), it groups check-offs into calendar weeks (Sunday through Saturday) and counts consecutive weeks where the user hit their target frequency. One tricky bug I hit: on Sundays, the current week has zero days elapsed, so the old code killed the streak immediately. The fix was to not require any check-offs for the current week since it just started.

The Garden

The personal garden is an SVG scene with a sky gradient, hill silhouette, and grass ground. Trees are positioned in a grid pattern using foreignObject inside the SVG so that React components (the TreeSVG) can render inside an SVG context.

Each tree gets a glow halo using radial gradients, a trunk shadow using a low-opacity ellipse, and the tree is wrapped in a div with flex alignment so it sits on the grass naturally.

Three visual modes (Light, Dark, Dawn) swap the entire color palette. The sky gradients, grass colors, hill opacity, and even the celestial bodies change. Dark mode adds twinkling star animations. Dawn mode uses warm pinks and peaches.

Bloom Teams

The most complex feature. Teams use Firestore with subcollections for goals and encouragements nested under each team document.

When a user opens a team garden, two onSnapshot real-time listeners activate. One watches the team document for member changes (joins, leaves, renames) and one watches the goals subcollection for new goals, check-offs, and deletions. Everything updates instantly across all team members without refreshing.

The team garden renders member rows with grass strips separated by dirt furrows. Each member's trees are positioned in a staggered zigzag pattern within their row. Name pills sit inside the SVG on mobile and outside with connecting tabs on desktop.

The encouragement system uses deterministic document IDs ({fromUid}_{goalId}_{date}) to enforce a one-per-day cooldown without needing composite Firestore indexes. When a user opens the app and has unread encouragements, a cinematic celebration animation plays with water drops, golden glow rings, sparkles, and the message "Keep Blooming."

Push Notifications

Firebase Cloud Messaging with three Cloud Functions:

  1. Morning reminder at 8am in the user's timezone
  2. Evening nudge at 8pm if they haven't checked in
  3. Streak warning when they're about to lose a streak

The timezone-aware part was important. A user in Montreal shouldn't get their morning reminder at 3am because the server runs on UTC.

What I Learned

Mobile testing is non-negotiable. So many things that looked perfect on my laptop broke on actual phones. Trees disappearing, buttons getting clipped off screen, text too small to read. Always test on a real phone before pushing anything live.

Real-time features change everything. Before I added live listeners, users had to refresh to see changes. The moment I made team gardens update instantly when someone plants a goal or checks off a day, the whole experience felt alive. That's the difference between a website and a product.

Building is the easy part. I spent weeks adding features like journals, push notifications, three languages, team gardens. But features don't matter if people don't come back to use them. I should have spent more time talking to users and less time adding things nobody asked for.

Ship before it's ready. The first version of Bloom looked rough. The current version has cinematic animations, 7 tree types, team gardens, and 3 languages. But none of that would exist if I'd waited for perfection before launching.

The Numbers

About 110 registered users. 306 Instagram followers at @justgobloom. Users in Canada, UAE, Brazil, and Zimbabwe. All organic, zero ad spend. 9.6% week 1 retention which is my biggest problem right now.

What's Next

React Native app for iOS and Android this summer. Bloom Pro with garden customization. And figuring out why 90% of users don't come back after week 1.

If you want to try it: justgobloom.com. It's free.

If you're a young developer thinking about building something, just start. A portfolio project that turns into a real product is the best thing you can put on your resume.


Follow the journey: @justgobloom on Instagram and TikTok

Top comments (0)