Globie Earth: Guardians of the Forest is an Android app where you adopt a real tree in the Isaan Valley of Northeast Thailand, grow a digital guardian that mirrors it, and watch a forest come alive as deeds turn into planted saplings. The partner is a real NGO (OpenmindProjects), and the trees are real trees in real ground.
The whole thing runs on one rule, and the rule is not a marketing slogan. It is a filter that has already cost us eleven features.
If it isn't derivable from something the device, the register, or a recording actually did — it doesn't get a number, and it doesn't get a label.
That's it. No live feed we don't have. No sensor we don't own. No percentage we can't compute. No physiology we can't read.
Sounds obvious. It's brutal in practice, because the person it argues with most is the person who drew the mockup.
The deletion rule.
We drew the original mindfulness dashboard as a mockup. Mockups are allowed to be aspirational — they sketch the product you wish you had. Then we sat down to build it, and found that the mockup had quietly promised things that don't exist. Here is the log, unedited.
|
# |
The mockup said |
What actually ships |
Verdict |
|---|---|---|---|
|
1 |
"432 Hz Solfeggio Resonance — Isan Morning Mist Chimes (Live Stream)" |
The on-device 432 Hz tone. It is either running, or it is not. There is no stream and there never was. |
Deleted — the stream |
|
2 |
"Real hydrophones & sap sensors in Ban Chiang Wae" / "Hydrophone Sensor #04" |
Two bundled mp3 field recordings plus the tone. The word |
Deleted — the sensors |
|
3 |
"Binaural Delta Wave 0.5–4 Hz" |
One 432 Hz sine plus an 864 Hz octave overtone. That is a |
Deleted — the claim |
|
4 |
"Deep SWS" / "REM Boundary" / "Melatonin Peak" |
Nothing. Invented physiology. Dropped with the visualizer it lived in. |
Deleted |
|
5 |
"AI Companions" / "Ask Mae Kae Na or Phaw Yang Na anything" / two live |
Pre-rendered clip playback only — 56 owner-approved lines served as static files. No microphone, no text-to-speech call, no model in the loop. The app names the limit where it sells the feature: "with live voice & chat coming later." |
Deleted — the conversation |
|
6 |
A working level slider on the tone channel |
The tone is mixed by two real sliders now — one on the mindfulness mixer, one in the Sound Studio session. The standalone library card still says "fixed level", because there the tone plays alone with nothing to balance it against. |
Re-scoped — and since shipped |
|
7 |
"42 Min This Week" |
Total logged listening, all-time, with an explicit caption. The store keeps one cumulative counter — there are no per-day buckets, so "this week" was arithmetic we could not do. |
Re-scoped |
|
8 |
"View Journal" |
Nothing. Nothing in the app stores a journal, so the button is dropped rather than pointed at an empty screen. |
Deleted |
|
9 |
Five hotlinked |
A CSS gradient plus a Material Symbols glyph on every card. Nothing hotlinked, nothing to break. |
Deleted |
|
10 |
"Kae Na" / "Yang Na" / "Ban Chiang Wae" / "Isan" |
"Khae Na" / "Yaang Na" / "Isaan Valley" — matched to the names the voice personas are actually given. |
Relabelled |
|
11 |
"14 kg Forest Bond" |
The CO₂ already summed from |
Kept — it was derivable |
11 promises went through the rule: 7 deleted outright, 3 re-scoped or relabelled, 1 kept because it turned out to be derivable. Zero invented numbers left on any screen.
Before: the mockup
The mockup. Every card on it says something we could not back.
After: what shipped
The dashboard that shipped. Fewer cards. Every word on every one of them is checkable.
The sound library, labelled for what it is
"432 Hz Solfeggio Tone · Generated on this device · Web Audio" — and it is. You can hear it being generated.
The rule isn't only for the mockup. Here are four real bugs from the public build log.
Every "Read more" toggle rendered a large serif EXPAND_MORE next to its label, in the middle of our clean UI. The React component was correct. The font was not.
We ship a hand-subsetted Material Symbols woff2 containing only the ~169 glyphs the app actually names. expand_more was never in the subset, and the bundled font declares no fallback family — so the browser printed the ligature name in its default serif face instead of failing silently.
Measured before the fix:
forest → 24 px (one glyph)
volume_up → 24 px (one glyph)
chevron_left → 24 px (one glyph)
expand_more → 264 px (11 characters of text)
The fix was not to re-subset the font. It was to use a glyph we already ship — chevron_left, rotated -90deg when collapsed and 90deg when open, with aria-hidden on the glyph because the visible Read more / Show less label already names the control.
Then we swept all six bottom-nav tabs for the same bug: every rendered icon checked as width / fontSize, and every icon name in the app probed by injection. ExpandableText was the only casualty — and then it wasn't. The Deeds vault was built afterwards and reintroduced expand_less on its detail toggle; the same sweep caught it again and the same swap fixed it. A subsetted icon font is not a rule you remember once, it is a rule you re-run.
Two gotchas worth stealing: a subsetted icon font with no fallback fails loudly as text rather than silently as a blank box — that's the good failure mode, keep it. And Tailwind v4's rotate-* utilities write the standalone rotate property, so getComputedStyle(el).transform reads none even when the rotation is applied — read .rotate instead.
RevenueCat has a failure mode that does not throw.
purchasePackage does not error for a package that exists but carries no entitlement. So: we had guardian_premium attached to guardian_unlock, while the product the app actually sells and requests is forestkeeper_monthly:monthly.
Result — a user pays, the purchase succeeds, the SDK reports success, and the app unlocks nothing. No exception. No red text. A happy path that gives the customer nothing.
Moved guardian_premium onto forestkeeper_monthly:monthly, and set the four dead one-time products to inactive rather than deleting them (a Play product id is permanent and never reusable; a one-time product is only deletable if never purchased).
The lesson we wrote into the project memory:
When you wire an entitlement, assert on the entitlement — never on the absence of an error.
The two guides are Khae Na (Thai แค-นา) and Yaang Na (Thai ยางนา). They are the emotional core of the app and their names matter.
Hume's Voice Library has no Thai voice. Available languages are English, Japanese, Spanish, Hindi, Arabic, German, French, Italian, Korean, Portuguese and Russian. None of them is Thai.
So the pronunciation rule is explicit and written down:
แค-นา in the script; the English spelling is Khae Na.ยางนา in the script; the English spelling is Yaang Na.We did not promise Thai audio. We promised two correct names.
A guide line playing with its tone label
The written line is displayed during playback, the tone says what it is and where it came from, and playback starts only from a user action — never on its own.
This is the one that stings.
We had already written the honesty standard — no faked sensors, no faked brainwave entrainment, no invented figures. And then the new dashboard mockup walked all three straight back in: a "live" chime stream, hydrophone and sap sensors we don't own, and a delta-wave readout that implies an EEG we don't have.
The rule found it. Not a code review — the rule. Because the question is the same for a mockup as it is for a feature:
Can this be derived from something the device, the register, or a recording actually did?
Nobody could answer yes for any of them. That's §3 above — the deletion log is the fix.
The rule applied to our own work, and we changed our own dashboard. That is the whole point.
A short sample of what "no invented numbers" cost us, in code:
deeds, not a number we typed.68% and 82%. A bar asserts a scale, and there was no scale. We deleted the bars rather than invent the scale to justify them.The last bullet is not from the deletion log. It came from writing this post: publishing the store listing — "Every figure in the app is cited — nothing invented" — made us re-read every screen against that sentence, and two labels and four bars did not survive it. Writing in public caught something our own review had missed, which is the entire argument for writing in public.
Subtracting is the easy half. The hard half is being specific enough to let real work through — a rule that only ever says no stops being a build tool and becomes a slogan.
Two features cleared it in the same release, on exactly the same terms.
Focus mode is one timed session, not a screen of settings. Pick 15, 30 or 60 minutes — or leave it open-ended — and the app takes the screen: a full-screen breath pacer, a soundtrack bed, a nature layer and a carrier tone, all at levels the mixer underneath already has. Every level it sets is a whole step of that mixer's own 5% sliders, so the summary line and the slider you open afterwards can never read as two different numbers. A finished session adds to the same listening counter every other screen shares, and to nothing else — there is no "sessions completed" total, because the device never produced one.
The Sound Studio is the opposite instinct, and it is the better argument for the rule as a tool rather than a brake. You describe a track in words, pick up to three styles from the app's own palette, and a cloud render comes back into your own library — where it then appears inside focus mode as a bed, in the same row as the built-in ones.
What makes it publishable is the machinery, not the model:
studio.globie.earth), reached with the same device id every other write in the app uses. There is no provider key in the client.api.studio_tracks. The mp3 never does — the audio goes to a volume, and the row keeps a filename, a length and a sha256.That last point is the whole test. A generated track is not a number we invented — it is a recording we can point at, with a receipt. Same question as §3, and the Studio answers it.
Focus mode
Focus mode's opening mix — three engines, at levels the mixer already has, rather than a preset name.
The Sound Studio
Describe it, choose styles, get a track. What lands in the library feeds the same mixer focus mode runs on.
Public feedback has not changed this app yet — and we are not going to pretend it has. Every bug in §3, §4 and §6 was found by us, going down our own build log. When a reply changes something, it gets written here with a link to the post that caused it. If that never happens, this section will still say so on submission day.
But building in public did change the app, in two ways that have nothing to do with replies:
It carried the mission further than the store listing can. Globie Earth is not a tool with a growth loop bolted on. It is an argument about old-growth cover in the Isaan Valley and the smallholder families who carry the cost of losing it. A store listing has room to say what the app does; it has no room to say why it should exist — why every purchase ends in real ground, why we deleted eleven features rather than describe them dishonestly, why a 432 Hz tone is labelled as a tone. Six days of dated posts under #Shipaton #BuildInPublic put that argument into feeds where it could be read, argued with, and passed on, in front of people who were never going to search for a reforestation app. That is awareness of the problem we could not have bought, and it is the clearest thing building in public gave us. What we will not do is dress it up as growth: we are not going to quote a reach number we cannot tie to a source.
It made our own media become true. Writing the deletion log in public meant every line of it had to survive a reader asking "prove it" — and the cheapest way to keep a published log honest is to keep deleting. Then, when we relabelled the mindfulness dashboard, we found that our own screenshots and both demo GIFs still showed the wording we had just removed. They were the build-in-public media, not private notes. So we re-captured all of them, animations included, so that what we show and what we ship are the same thing. A build-in-public post that shows a screenshot of a claim you just deleted is a slower way of lying. That re-capture would not have happened on a private build log, and it is the most concrete thing this has done to the app so far.
The two posts that drew the most replies were the two failure write-ups — the entitlement that granted nothing, and the icon font that printed its own name. We answered every reply.
If you want to change a line in this app: the comments are open, and the deletion log above is the list of things we already gave up. Tell us what's next.
com.globie.earth). First public release in the Shipaton window; the Journey tab is free to explore.forestkeeper_monthly (the guardian_premium entitlement) plus three consumable tree products (Mother Tree $5, Father Tree $15, Sacred Pair $20).forestkeeper_monthly) grants a 30-day free trial; redeem it at play.google.com/redeem.