Back to Blog
Case StudyCase & Studies

Booster App: Building a Daily Habit Experience Across iOS & Android

Building Booster was more than "make an app that shows quotes." It was about crafting a daily experience.

15 min read
Dec 4, 2024

On the surface, Booster looks simple:

"Show one quote a day, let users like it, share it, and feel inspired."

But here's the thing:

When you try to turn something spiritual and timeless into a daily consumer app, the engineering challenge becomes much more intense:

🧘

It must feel calm, not noisy

🌍

It must behave predictably, even when you travel across time zones

Notifications must feel like a ritual, not spam

📍

The quote must be ready at 9:36 AM sharp, every single day, across continents

❤️

Likes must be fair — one user, one like — no cheating, no multiple taps

📱

UX across iOS and Android must feel like the same product, even though the frameworks are completely different

This is the story of how Booster evolved from a simple idea to a cross-platform daily habit system — engineered, designed, refined, and entirely built through ChatGPT collaboration.

1

Starting Point: Designing a Daily Ritual, Not an App

The very first question wasn't technical:

"What should a spiritual quote app feel like?"

Most apps chase engagement.

Booster chases presence.

I intentionally designed it like a slow, mindful experience:

One quote only

Delivered at the same time every day

Gentle animation instead of attention-grabbing UI

A tan, warm color palette that feels grounded

Zero clutter, zero decisions, zero friction

The operational definition was:

Core Philosophy:

A user should open Booster and instantly feel calmer than they were 2 seconds ago.

Everything — backend, notifications, UX — was built to serve that feeling.

2

The 9:36 AM Experience: A Product Requirement Disguised as Engineering

Most apps send notifications when content is published.

Booster sends it at 9:36 AM local time, regardless of where the user lives or travels.

Why 9:36?

Because it's a time that feels intentional — not automated.

But this unlocked a surprisingly complex set of problems:

2.1 Timezone awareness on the backend

Every device passes:

tz = device's IANA timezone

Examples:

America/Toronto

Asia/Kolkata

Europe/London

The backend computes:

"Today" based on that timezone

Which quote belongs to that date

Whether the user has already viewed or liked it

Then it returns the content aligned to that timezone.

If a user travels — India → Canada → USA — the logic continues to evaluate "today" correctly.

That might sound trivial.

It's not.

2.2 Notification scheduling logic

The backend generates two pipelines:

iOS

APNs

Android

FCM

The notifications are not "fire and forget".

They follow a structured flow:

1

Device registers its FCM/APNs token

2

Device sends timezone

3

Backend stores: token, platform, timezone

4

Notification cron runs: Every minute, Segments users by timezone

5

Pushes notifications exactly at 9:36 AM THEIR local time

2.3 Timezone edge case I had to solve

When I traveled to India and came back to Canada, the iOS device was still receiving notifications on Indian time because APNs token → timezone mapping didn't refresh aggressively.

The fix:

Tokens now re-register on every app launch, not just the first install

Tokens also re-register on timezone change events

Backend ignores stale timezone records

This is the kind of detail no one notices unless it breaks — but when it works, the product feels magically reliable.

3

Backend Architecture: A Calm Pipeline With Predictable Behavior

Booster's backend is intentionally minimal but extremely deliberate.

3.1 Tech stack

Node.js

Backend runtime

Express

API framework

MongoDB / Mongoose

Database & ODM

Cloudflare Pages

Frontend hosting

Render

Backend hosting

APNs + FCM

Push notifications

3.2 API endpoints

The system exposes a few core endpoints:

GET /api/quote/today POST /api/quote/{id}/like POST /api/quote/{id}/view POST /api/notifications/register

Simple surface.

Complex logic underneath.

3.3 "One user, one like per day"

Users shouldn't spam likes.

But Booster is anonymous — there's no login.

Solution:

Privacy-First Design:

Use a locally stored, cryptographically unique device ID (iOS & Android) tracked in DB

Stores which quote was liked

Prevents re-likes

Works offline

Survives app kills

Respects privacy (no personal data)

3.4 The "day" boundary rule

"Like" permission resets at midnight in device local timezone.

NOT

midnight UTC

NOT

midnight server time

YES

midnight in device local timezone

This seems small.

It's actually a full habit-cycle design problem.

4

iOS Engineering: Building a Minimal, Modern SwiftUI Experience

On iOS, Booster is written in SwiftUI, heavily optimized for:

Layout performance

Smooth animations

Offline caching

Background fetch handling

Share sheet integration

4.1 The core view model

Everything flows through:

QuoteViewModel

It:

Fetches today's quote with timezone param

Stores viewed state

Handles like logic with UserDefaults

Exposes a reactive state for SwiftUI

4.2 Screenshot generation for saving/sharing

Booster supports:

Save to Photos

Share sheet

Social sharing

The screenshot engine:

Captures only the content (no UI chrome)

Uses SwiftUI → UIKit bridging

Handles high-resolution rendering for retina devices

Uses a unified canvas so both light/dark mode look identical

4.3 9:36 AM Notification UX

When user taps the notification:

App opens directly into the quote

No splash screen delay

No blocking spinners

Data is pre-fetched if possible

This is the difference between "nice app" and "daily habit product".

5

Android Engineering: Matching iOS Experience in Kotlin Compose

Android is not a copy of the iOS app.

It's a native Kotlin app built with:

Jetpack Compose

Retrofit for API

Kotlin Coroutines

Coil for images

FCM for notifications

Matching iOS UX on Compose was a full project by itself:

5.1 Typeface, spacing, rhythm

Android typography behaves differently.

Manrope behaves differently across platforms.

I tuned:

T

baseline offsets

T

character spacing

T

dynamic line breaking

T

padding rhythm

T

composable modifiers

5.2 Save/share parity

Android doesn't have the same "save to gallery" pattern as iOS Photos.

So I built:

Custom bitmap renderer

High-quality image generation

Scoped storage handler

Android 10+ compatibility

MediaStore write logic

Gallery integration

Toast/Snackbar system

Matches iOS confirmation UX

5.3 FCM token logic

Android aggressively refreshes tokens.

iOS doesn't.

So I added:

Token refresh handler

Instant backend sync

Debug push tester API

This is why push notifications feel instant and reliable.

6

Notification Pipeline: The Heartbeat of Booster

Notifications look simple:

"Send today's quote at 9:36 AM."

But the pipeline powering that simplicity is one of the most complex systems I designed for the project.

6.1 Token registration

Each device sends:

token platform timezone deviceId

This lets the backend intelligently group devices.

6.2 Cron dispatcher

Running every minute:

1

Determine which users currently have 9:36 AM in their timezone

2

Fetch today's quote for that timezone

3

Fire notification through APNs or FCM

4

Log delivery attempt

5

Update retry counters if needed

6.3 Quiet mode

Notifications are intentionally silent:

📳

No vibration

🔇

No sound

🚫

No intrusive banners

The philosophy:

Design Principle:

"Presence, not pressure."

6.4 Consistency testing

I built a local script to test 50+ timezone permutations to ensure:

DST changes behave correctly

Countries with half-hour offsets work

Travel doesn't break mapping

This was critical — and it saved the product when I returned from India and uncovered the timezone caching bug.

7

The UX Philosophy: Calm Technology

A lot of product decisions were built around one idea:

"The best spiritual apps don't push you. They invite you."

Examples:

No feed

Only one quote. No doom-scrolling.

No badge counts

No unread markers. No psychological pressure loops.

Warm color palette

Tan + brown → grounded, timeless.

Space and breath

Generous top/bottom spacing makes the quote feel like a poster, not an app screen.

Gentle notifications

No emoji, no hooks, no gamification.

Invisible reliability

Booster simply "works" at 9:36 AM every day. Reliability becomes a user experience.

8

Platform Parity: SwiftUI vs Kotlin Compose

Building two apps that look identical across completely different rendering systems required:

Shared design tokens

Shared spacing system

Shared typography scales

Shared card elevation logic

Shared animation curves

But here's the hidden work:

8.1 Identical rendering is not a copy-paste problem

SwiftUI and Compose interpret:

leading/trailing padding

text bounding

intrinsic height measurements

To solve this:

Engineering Solution:

I built a platform-agnostic design spec, then implemented platform-specific rendering that produced visually identical output.

This is the kind of work that separates "two apps" from "one product across two platforms."

9

Testing Booster Like a Production-Grade System

My QA background shaped everything here.

9.1 Scenario testing

Travel through timezones

Device clock drift

Manual date changes

Notification arrival without app open

Notification arrival when app already open

Like spam attempts

API rate limits

Offline caching

Middleware failures

9.2 Backend resilience tests

I simulated:

!

Token invalidation

!

Quote missing for a date

!

Server returning stale data

!

Race conditions on daily boundary

9.3 Monitoring & analytics (lightweight)

Just enough to know:

How often quotes are viewed

How likes trend

Whether notifications deliver

Not enough to profile or track the user.

Privacy remains a design principle.

10

From "App" to "Daily Habit System"

Booster isn't an app.

It's a ritual system backed by:

Backend governance

Notification pipelines

Cross-platform parity

Ultra-intentional design

Habit-friendly behavior

Timezone intelligence

Daily reset rules

Calm UX

Invisible reliability

This is what I enjoy building:

Products that feel simple on the surface

because they're engineered with discipline underneath

Case Study:

If Feedback Box was a case study in governance and workflow design, Booster is a case study in crafting habit-forming, emotionally resonant user experiences with engineering precision.

Final Thoughts

Booster started as "let's show a quote every day."

It became:

1

A cross-platform mobile experience

2

A timezone-aware content system

3

A reliable APNs/FCM pipeline

4

A privacy-respecting engagement model

5

A product that creates a daily spiritual pause for thousands of people

This project reflects the kind of leadership and engineering I bring to the table:

See the product vision clearly

Design the architecture intentionally

Build across multiple platforms

Solve the invisible problems users never see

Deliver something that "just works"

Create a system that could scale well beyond its original scope

That's what Booster represents for me — a demonstration that even the simplest ideas deserve world-class engineering.

Enjoyed This Article?

I write about building reliable systems, leading teams, and shipping products that matter.