YumeHashi's Tech Stack and 5 Implementation Challenges Solved by v2.1.0

Introduction

Ever shipped a personal app and then watched it slowly fall apart under real-world use? Yeah — me too.

YumeHashi is my personal Flutter Web app that breaks dreams into goals, goals into tasks, and turns the whole thing into action. Renamed from “YumeLog” in April 2026, now at v2.1.0. It’s been live long enough to hit the interesting problems.

This article zooms in on the technical internals:

  • The tech stack and why I picked each piece
  • The serverless, zero-cost infrastructure
  • 5 real problems that surfaced in production, and the fixes

Architecture Overview

[User (Browser)]
      | HTTPS
      v
[GitHub Pages] ---- Flutter Web build artifacts (static hosting)
      |
      +-- [Firebase Auth]      Anonymous → Email auth
      +-- [Firestore]          Full JSON sync (3s debounce + SHA-256 diff)
      +-- [Google Apps Script]  Stripe proxy / feedback
      |         +-- [Stripe]   $2/month subscription
      +-- [GitHub Gist API]    Remote config (invite codes, settings)
      +-- [Browser SQLite]     Drift ORM + drift_worker.js (WASM)

The key design call: the primary store lives in the browser as SQLite. Firestore is just a “full JSON cloud backup.” Most reads and writes finish locally, which keeps Firestore’s free-tier write quota (20,000/day) comfortably safe up to DAU 3,000.

Key Tech Stack

LayerTechnologyWhy
UIFlutter (Dart)One codebase, Web + Windows
StateRiverpodCompile-time DI, testable
Local DBDrift (SQLite)Type-safe queries, WASM for Web
AuthFirebase AuthSmooth anonymous → email migration
PaymentStripe (via Apps Script)No secret keys on the client

Running at zero monthly cost for over a year now. The only thing that could ever turn the meter on is Firestore writes (the DAU 3,000 threshold).


5 Implementation Challenges

Challenge #1: Slow Initial Load

HAR analysis showed First Paint at 3.4s when cached, 6-10s on cold start. Not great.

Problem: Apps Script’s Stripe verification took 1.8s and sat right in the middle of a serial dependency chain.

Solution: Three moves in parallel — cache premium state before runApp(), push external calls into addPostFrameCallback, and add preconnect/preload hints to index.html.

Challenge #2: Inbox Data Growth

After a year of operation, accumulated notifications started pressuring both memory and Firestore. Solution: Auto-delete read notifications older than 30 days. Unread notifications are protected regardless of age — deleting unread items would quietly erode user trust, which is exactly the kind of thing you don’t notice until it’s too late.

Challenge #3: Completed Task Accumulation

After 10 months, task list rendering got noticeably sluggish on real devices. Solution: Default-hide completed tasks plus auto-delete completed tasks older than 30 days via DataRetentionService. Added an FAQ entry: “Export anything you want to keep before auto-deletion kicks in.”

Challenge #4: Duplicate Announcements

Problem: Removing entries from announcements.json didn’t remove them from users’ inboxes.

Solution: Treat announcements.json as the single source of truth — delete DB records whose dedup_key no longer exists in JSON.

Challenge #5: CI Version Check Race Condition

Problem: CI’s version-check ran after merge because of queue delay, so it compared identical versions and yelled.

Solution: Skip the check when git merge-base --is-ancestor HEAD origin/main — meaning the PR has already landed.


AI-Driven Development Stats

ItemValue
Time to first release3 weeks (from zero Flutter experience)
Current versionv2.1.0
Test cases847 (unit + widget + integration)
Source lines~30,000 (lib/ + test/)
Commits160+

App: YumeHashi (free trial available). Repository: GitHub.

Contact

Feel free to reach out with any questions or feedback.

Get in touch