-
-
A Pomodoro companion that grows with your focus.
-
A calm Pomodoro workspace designed to disappear while you focus.
-
Two mysterious companions, each with their own behavior, world, and story.
-
Focus changes the world around your companions.
-
The longer you focus, the more personal their messages become.
-
Turn focused time into a personal history of what you care about.
-
Earn Coins through focus or purchase optional content through a RevenueCat-powered economy.
-
o make the world feel personal, I transformed photos taken by my family and real flowers into pixel-art assets.
-
Built in Flutter and tested repeatedly on a real iPhone—not just in the simulator.
-
Challenges
About the project
Nordic Focus is a distraction-free Pomodoro app inspired by Scandinavian minimalism, Nordic soundscapes, and the feeling of watching a small world slowly come to life.
At first glance, it is a simple focus timer. But behind the timer live two mysterious little creatures. One feeds on food. The other purifies water.
As users spend more time focusing, they earn Coins, their companion's affection increases, new dialogue is unlocked, and the world around the creatures gradually comes alive.
I designed Nordic Focus around one idea: What if time spent focusing could become more than a number? Instead of treating 25 minutes as just another statistic, Nordic Focus turns those 25 minutes into progress inside a small living world.
Built for the Next Gen Award
Nordic Focus is not just another productivity tool; it's a living diorama in your pocket. Submitted for the Next Gen Award, this app is fully developed, perfectly optimized for real iOS devices using StoreKit Sandbox, and ready to demonstrate a flawless RevenueCat ecosystem—even before hitting the App Store.
Inspiration
In today's hyper-connected world, maintaining deep focus can be surprisingly difficult. Many productivity apps add more dashboards, notifications, statistics, social features, or visual stimulation in an attempt to keep users engaged.
I wanted to approach the problem from the opposite direction. Inspired by Scandinavian minimalism and the calming atmosphere of Nordic landscapes, I designed Nordic Focus to be visually quiet and easy to understand.
The timer itself should not compete for attention. The app should become almost invisible while the user works. But I also wanted to answer a second question:
How can we make people want to return without turning productivity into pressure? My answer was companionship and discovery. The companions do not interrupt the user while they work. Instead, they quietly react to the user's focus. A completed session gives Coins.
The selected companion accumulates focus time. Affection levels increase at 25, 60, 120, and 240 minutes. New messages then become available in the Fairy Archive, turning accumulated focus time into an unfolding story.
A World That Grows With Focus
The two companions are designed around completely different forms of "consumption."
🍓 Appetite Enhancer This creature's hair is actually living slime. It can wrap around food and swallow it. It loves eating so much that when it first meets the user, its first thought is: "You look... delicious." It is kind enough not to eat the user, however.
Instead, it happily eats beside them while they work. As the user's focus time increases, its messages slowly change from playful encouragement into attachment.
What begins as: "I'll sit here while you work." eventually becomes: "I used to enjoy eating by myself. But now... it feels strangely quiet when you're gone."
💧 Appetite Suppressant
This creature's cloak is actually a network of plant roots. The roots extend into the ground and absorb water. Polluted water is purified through the creature and eventually returns to the environment as clean vapor, while flowers bloom around it.
It has spent a very long time performing this cycle alone. At first, it simply accepts the user's presence. But after many focus sessions, it begins to notice their absence. "I spent a very long time working alone. Now, I notice when you are gone."
The relationship gradually becomes more personal without ever explicitly explaining what the creature is feeling. The user discovers the story through the messages they unlock.
What It Does
- Distraction-Free Nordic Timer
The core experience is a clean Pomodoro timer with: 25-minute Focus 5-minute Short Break 15-minute Long Break Custom durations Quick presets A 1-minute quick-test mode for demonstrations
I also added quick duration pills directly to the timer so that common durations can be selected without navigating into Settings. The quick-test mode makes it possible to demonstrate the full reward loop immediately during a hackathon presentation.
- Your Work Becomes Part of the Story
I wanted focus tracking to feel personal rather than purely numerical. Users can select categories such as:
Math & Logic Study & Reading Work & Code Creative & Hobby Fitness & Health Other
They can also create their own categories with a custom name and emoji. Each completed Focus session automatically records time both for the selected category and the currently equipped companion. The data is persisted locally, so it remains after restarting the app.
This means the app can answer two different questions: What did I spend my time on? and Who did I spend that time with?
The Categories tab visualizes total focus time, category breakdown, percentages, and the currently active category.
- Affection and the Fairy Archive
Every companion has an affection level based on accumulated focus time. The progression is:
Level Focus Time Acquaintance 0 min Good Friend 25 min Trusted Ally 60 min Best Companion 120 min Soulbound 240 min
As affection increases, new messages are unlocked.
These messages are collected in the Fairy Archive, where users can see:
Affection level Total focus time Progress toward the next level Unlocked dialogue Locked dialogue and its unlock condition Message collection progress
The archive also includes the Categories view, turning the screen into a combination of story collection and personal focus history. I also designed the message system as a data-driven catalog: adding a new dialogue entry to FairyMessagesCatalog automatically makes it available to the archive at the specified affection level.
- Focus Creates Visible Reactions
The companions do not simply swap between static images.
During a session, the Appetite Enhancer eats different foods, while the Appetite Suppressant absorbs water and grows flowers.
For example, the food sequence cycles through items such as apples, cinnamon rolls, pancakes, cloudberries, and blueberries. The animation was carefully timed so that the food is completely consumed before the companion transitions into its satisfied expression.
This makes the relationship between focus, character, and world visible rather than purely textual.
Monetization & The RevenueCat In-App Economy
Rather than gatekeeping essential productivity behind aggressive subscription paywalls, Nordic Focus utilizes RevenueCat (purchases_flutter) to power a balanced, ethical micro-economy:
- Earned Through Focus: Users naturally accumulate coins simply by completing Pomodoro sessions (+10 Coins per session).
- Consumable Coin Store (via RevenueCat): For users eager to instantly unlock premium companions or ambient soundscapes, we offer flexible consumable coin tiers:
- Handful of Coins (+100 Coins): $0.99
- Pouch of Coins (+500 Coins - Unlock Imp!): $3.99 (Most Popular)
- Chest of Coins (+1,200 Coins): $7.99 (Best Value)
- Fair Unlockables: Accumulated coins can be redeemed in the Nordic Shop to unlock additional elemental companions (e.g., Appetite Suppressant Imp for 300 Coins) and exclusive soundscapes (e.g., Glacier Stream BGM for 150 Coins).
Small Details I Added to Make the World Feel Personal
One part I especially wanted to avoid was making every visual asset feel like generic game decoration. To add warmth and variation, I used photographs taken by myself and my family as source material, converted them into pixel art, and incorporated them into the app.
I also used photographs of real flowers as references and converted them into pixel-art patterns using MakeBead. This gave the app a visual language that is partly designed and partly grounded in real things I have actually seen.
The result is intentionally a little more handmade than a typical productivity app.
Audio as Part of the Experience
Nordic Focus also treats sound as part of the environment rather than just background music.
Users can choose how ambient audio behaves around Focus and Break periods:
Always Focus only Break only
The selected behavior persists through Settings, and the audio state is coordinated with timer start, pause, resume, and break transitions.
I also integrated additional soundscapes into the same reward system, so users can unlock new ambient tracks through the Shop. Purchased soundscapes immediately become available from the main soundscape interface.
Audio credits and licensing information are also exposed in-app and documented in the repository.
How I Built It
- Flutter / Dart
- Riverpod
- just_audio
- RevenueCat / purchases_flutter
- shared_preferences
- Feature-based application architecture
- Flutter app + interactive GitHub Pages demo
The core state is separated into timer, audio, shop, focus statistics, category, companion affection, and message systems.
Focus statistics, category data, unlocked messages, and companion progress are persisted locally with SharedPreferences.
Challenges We Ran Into
- Making Character Animations Feel Like Real Characters
One of the more subtle problems was that the companion images did not all have the same proportions. When a character changed from a normal pose to a larger eating or smiling pose, simply placing every image inside the same centered box caused the character's apparent size and position to shift.
I had to analyze the original image dimensions, establish a consistent scale, and pin every sprite to the same baseline so that only the upper part of the character changed position.
I also had to deal with image flickering during state transitions. In the web demo, changing an image's src could temporarily display an old image at the new size. In Flutter, asynchronous image decoding could create a one-frame gap where the character disappeared.
I solved this by preloading the sprites and keeping the different poses available simultaneously, switching visibility instantly rather than repeatedly creating and decoding new images.
- The Web Demo and the Real iPhone Were Not Behaving the Same
One of the biggest practical lessons was that a browser demo and a real mobile device can expose completely different problems.
On the real iPhone, I encountered issues such as:
- Horizontal overflow in control bars
- Overflow in the Coin Store
- Overflow in the reward dialog
- Sprite flickering
- Incorrect timer duration synchronization
- Incorrect BGM behavior when pausing and resuming
For example, the reward dialog initially overflowed because long text such as "Appetite Enhancer Friendship" was competing for width with the level indicator. I had to redesign those rows using Expanded, Flexible, wrapping, and ellipsis handling rather than simply shrinking the entire UI.
The same process happened repeatedly: observe the real-device bug → identify the layout/state cause → change the implementation → test again.
That iterative process became one of the most valuable parts of building the project.
- Synchronizing the App and the Demo
I wanted the GitHub Pages demo to feel like a real extension of the application rather than a static mockup.
That meant synchronizing features such as:
- Fairy Archive
- Categories
- Quick timer presets
- Reward dialogs
- Soundscape unlocking
- BGM behavior
- Character switching
The demo was updated alongside the Flutter implementation, and the project documentation records verification of the JavaScript syntax and deployment process.
- Designing the Animation Around the Artwork
Another challenge was not purely technical.
Because the companion artwork is hand-drawn and each pose has a slightly different canvas size, I had to make implementation decisions around the art itself.
Instead of forcing every image into an identical rectangle, I changed the rendering approach so the original image proportions were preserved with a uniform scale factor and a fixed baseline.
This is a small implementation detail, but it mattered because the artwork is one of the most visible parts of the app.
- Building a Monetization System Without Breaking the Reward Loop
RevenueCat was another area where implementation details mattered.
At one point, failed or cancelled purchases could incorrectly fall through to the success path and add Coins. I traced that behavior to the purchase error handling and changed the logic so Coins are added only after a confirmed successful purchase.
This also required careful handling of StoreKit testing and fallback product lookup so the purchase flow could be exercised on a real iPhone during development.
Accomplishments I'm Proud Of
A Productivity App With a Memory
Nordic Focus remembers what the user did and what happened because of it.
A completed session can simultaneously affect:
Coins + Focus Category + Companion Affection + Story Progress
That made the timer feel less like a stopwatch and more like a living system.
A Character System That Is Actually Extensible
The companion dialogue was built as a catalog rather than hard-coded into individual screens, so new messages can be added without redesigning the archive system.
The same approach is used across other systems so that categories, audio, unlockables, and companion states remain separate and extensible.
Real-Device Iteration
The project was not only tested in a development environment.
I repeatedly tested the behavior on an actual iPhone and fixed issues that only became obvious on the physical device, including layout overflow, sprite transitions, timer synchronization, and audio state handling.
The final project walkthrough records a full-project static analysis result of 0 errors, 0 warnings, and 0 lints.
What I Learned
The biggest lesson was that restraint and depth are not opposites.
The UI can stay minimal while the underlying system becomes surprisingly rich.
A user might only see:
a timer, a little creature, and a few buttons.
Underneath that interface, however, the app is tracking categories, companion-specific focus time, affection levels, dialogue unlocks, persistent state, audio modes, purchases, and character animation states.
I also learned how important physical-device testing is.
A layout that looks perfectly reasonable in a simulator or browser can fail immediately on a real phone.
And perhaps most importantly, I learned that story can change the meaning of a productivity metric.
25 minutes focused is a number.
25 minutes that made someone in this little world a little happier is a story.
That is the idea I wanted Nordic Focus to preserve.
What's Next for Nordic Focus
I would keep this section shorter than your current one. The current "Apple Watch / cloud sync / seasonal bestiary..." list is fine, but the story-driven direction is stronger.
A Larger Little World
Future companions could introduce new environments, mechanics, and stories while keeping the same core loop:
Focus → Affect the world → Build a relationship → Discover the story
Potential future companions could be connected to auroras, forests, frost, sunlight, or other Nordic-inspired phenomena.
The companion archive could also eventually grow into a larger story collection, with hidden narrative fragments that only become visible after enough time has been spent with each creature.
One thing I'd change about the overall submission
Your original Project Story has a lot of feature inventory language:
"Flutter & Dart..." "RevenueCat..." "just_audio..." "SharedPreferences..."
Those are useful, but they shouldn't be the thing the judges remember.
I would make the submission's narrative flow:
- Focus problem ↓
- Quiet Nordic design ↓
- Two strange companions ↓
- Focus changes their world ↓
- Affection unlocks story ↓
- Categories and archive make progress personal ↓
- Real-world photos/pixel art make the world yours ↓
- Real-device iteration makes the experience robust
That way, the technical implementation supports the story rather than competing with it.
Log in or sign up for Devpost to join the conversation.