Inspiration
I've been getting into philosophy recently, and it's teaching me something: many things I don't agree with have valid arguments behind them.
John Stuart Mill put it plainly in On Liberty (1859): “He who knows only his own side of the case, knows little of that.”
Understanding the other side can make your own convictions stronger. It can also make you realise you need to change them.
That is what I wanted to bring into 2 Minds: the knowledge of philosophy and manner of debating, which I've been learning. I wanted to put them into something people could pick up, understand, and argue with for themselves.
What it does
2 Minds is a library of puzzle challenges built around philosophical questions that philosophers have argued about for decades and centuries. Each puzzle introduces its question through a scenario that is easy to follow, then walks you through a connected series of choices which you, as the user, have to make.
Your answer determines which situation and question you meet next. For every opinion you choose, there is a counter argument to face. You can hold your position or take it back, but the app keeps asking you to think about what your answer commits you to.
By the end, you've learned a new concept and formed an opinion you've actually had to defend. The ending (close) tells you what philosophers have argued about the question, and the Sources screen gives you the citations, with notes and links, to go further. Afterwards, you can revisit any examined puzzle challenge and view the route you took through it. You can also open answers on the other branches and discover the arguments you didn't meet.
Your answers also shape which of six philosophical temperaments you lean toward, and the app shows it through its theme and gems, never a score. During the first-time onboarding, you will see these temperament definitions alongside their gems & reveal animations in the carousels, so you can get an early feel of what the theme changes look like.
How I built it
I built 2 Minds as a solo developer, using Kotlin Multiplatform and Compose Multiplatform. The first commit landed on August 1, and the app was live on the App Store on September 17. About 97% of the app's Kotlin and Swift source lines are shared, not counting tests or generated code. That includes the screens I designed, custom motion, puzzle logic, database and sync. The Swift side is seven small files.
One codebase ships to three stores. Room with the bundled SQLite driver gives iOS and Android the same database engine. Firebase, through GitLive's KMP SDK, handles sign-in and syncs content and records. RevenueCat's KMP SDK sells one subscription on the App Store, Google Play and the Galaxy Store, and Android ships two flavours from the same code, one for each billing system. The native side stays thin. Each app shell hands its sign-in, network and billing pieces to shared code once, at startup, and the entire expect/actual surface is six declarations.
It works offline first. Ten puzzles ship inside the app, and your record lives on your device. Signing in is optional and exists only to carry that record to your next device. When the library refreshes, it makes a single request that asks only for what changed since the last one.
The core screens and answer choreography started in Figma. In Compose, I built a small timeline system for the entrances, stamps, strikes and rewinds, then connected those moments to scrolling and visibility.
ThemeReveal is a separate library I created for this project. During a transition, it renders the content twice with different theme values and reveals the incoming version behind an animated entrance. To run it over a live, scrolling puzzle, I hoisted everything both copies have to agree on above the reveal: what you've read, every animation clock and every scroll position. That way the two worlds move as one. I extracted it, open-sourced it and published it to Maven Central. It now runs on Android, iOS, desktop and the web, with twelve reveal styles you can try in the live web demo.
Puzzles are data, checked twice. Each one is a JSON document: an opening, seven questions, fourteen answers and eight routes, with each answer's lean toward the six temperaments. A checker script holds every draft to the rulebook and a Node script publishes it to Firestore. Your temperament is plain arithmetic on your device, weighted toward your recent answers. There's no AI anywhere in the scoring, so the same answers always give the same result.
Tested on both platforms. I checked the app on devices, simulators and a foldable emulator in each posture, both half-open like a book and flat.
Along the way I gave a little back. I released anew version of compose-alert-banner 1.0.0-rc03, my own alert library, which 2 Minds uses for its notices. I also wrote up the whole build, including what iOS and Android each taught me, in a blog: Composing the app twice.
Challenges I ran into
The first challenge was engagement. Philosophy needs paragraphs of text, and reading texts cannot compete with other high-dopamine attention apps on your phone, so I designed the galley: a vertical feed of full-screen beats (like TikTok or Reels) where text appears as you reach it, and every choice, hold and take-back is something you see and feel.
The second was making that design work. Scrolling through paragraphs and turning to the next beat use the same finger movement, so I built a gesture layer that scrolls the text first and turns the page when you keep dragging past the end. The theme reveal needed the same care: two live copies of the puzzle had to stay perfectly in step while the new theme spread across them.
The third challenge was giving the puzzles a consistent formula and standard of reasoning. Each has an opening and three branching levels: seven questions, fourteen answers and eight possible routes. You follow one route through three questions, but every branch needs the same manual, dexterous care, requiring human eyes to validate, alongside using multiple LLMs to critique.
Accomplishments that I'm proud of
Actually building the app.
I gave up in my head so many times. There were plenty of moments when I wanted to stop working on the puzzle sequence and call it good enough. But that sequence is the app. If reading, choosing, holding and reconsidering didn't feel right, the rest wouldn't make up for it.
I kept pushing and refining it. Seeing a puzzle run from its opening through to the closing gem makes me proud that I stayed with it. I'm glad that I've built something positive, that could potentially empower people with knowledge.
Additionally, I’ve spent the past 11 years building mobile apps and publishing them on Google Play and the App Store, but this was my first time launching on the Samsung Galaxy Store. It was refreshing to experience a different store’s submission process. This also marks the third personal project I’ve launched independently, without any company affiliation.
Building 2 Minds to this point, with this much detail and polish, is why I'm proud to enter it for four awards:
- RevenueCat Design Award
- RevenueCat Peace Prize
- Ship Kotlin Everywhere, by JetBrains
- Best App for Galaxy, by Samsung
What I learned
Design is hard. Making something attractive was only part of it. The harder question was whether a person could understand what was happening while giving the app ordinary, imperfect attention. As a developer, this was perhaps my greatest struggle.
Foldable Support. Agentic coding has made it much easier to support multiple layouts and form factors, and since 2 Minds is an app you read, I took the chance to build for foldable postures instead of stretching a phone layout across a bigger screen. On an Android foldable like the Galaxy Z Fold, the app reads the hinge: hold it half-open and a puzzle becomes a book, with the story on the left page, your choice on the right and a shadow down the crease. Apple announced the iPhone Duo while I was still building, which was good timing: I got to test a few of my screens on it.
I documented most of my learnings and journey in this article on Medium.
What's next for 2 Minds
I want to grow the puzzle library, then build support for puzzles that go beyond three symmetric levels of arguments. Currently, I have about 40 puzzles lined up for the app, and each puzzle is quite tricky to make due to the amount of research required and ensuring that it is readable and easily digestible by the readers.
The current structure gives every challenge a clear shape. Next, I want room for questions that need a different one: an argument that deserves another step, or a branch that needs more space than its neighbour. I want the structure to follow the question further.
Log in or sign up for Devpost to join the conversation.