BUILT WITH:
Figma
React Native
VS Code
JavaScript
I actually shipped it.

I officially submitted my first app.
It feels surreal because a couple of months ago it was just an idea. I had no clue where to even start, and now BestList is available for beta testing through TestFlight.
It's honestly weird seeing something that used to live in Figma and my terminal sitting on my phone like any other app.
Quick recap: What is BestList?
BestList is a personal food ranking app where you can log dishes, rate them, remember where they're from, and share your list with friends.
Tried tacos at a new spot but not sure if you'd go back? Log it.
Found a ramen place you loved but can't remember the name six months later? It's already on your list, rated and ranked.
The next time someone asks, "Do you know a good ramen spot?" you don't have to rely on your memory. Just send them your list.
The hardest part: keeping the MVP boring
The hardest part of building the MVP was honestly keeping it... boring. Bare bones. Nothing fancy. Just solving the core problem.
Log the dish. Remember where it came from. Rank it. Share it.
It was tempting to keep adding features that would make the app feel more exciting. A social feed. Better discovery. Photo galleries. Geo-tagging. But none of those solved the original problem. The priority wasn't shipping the biggest app possible. It was making sure the foundation was solid.
AI definitely sped up the coding process, but I also wanted to make sure I understood what it was generating and that I was following programming best practices. My future self is the one who has to maintain this codebase.
What made it into the MVP
Categories (dish types)
Create entries
Upload photos
Attach restaurants using the Google Places API
Score dishes across multiple categories
Automatically rank dishes within a list
Personal lists with full CRUD functionality
Share read-only lists through a public web link
Deployed shareable web page
Basic profile and list views
Authentication and database setup
Google Sign-In
Apple Sign-In

For such a simple app, it touched almost every discipline involved in software development.
In my first post, I wrote:
"I had to put my creativity aside and think about what was actually practical."
Looking back, I don't think I put creativity aside at all.
It actually takes creativity to simplify a solution and translate it into a product that's intuitive enough for someone else to use without needing an explanation.
Tools
Codex | Used inside VS Code as my coding agent. I planned the work, wrote structured prompts, and delegated implementation while making sure I understood what it was doing before moving on. |
|---|---|
Claude | My tutor and thinking partner. I used it to review implementation plans, explain what was happening under the hood, and quiz me so I could actually retain what I was learning instead of just accepting the output. |
CodeRabbit | My code reviewer. Since I was building solo, it helped catch issues that both Codex and I missed. More importantly, it forced me to slow down and review my own code before merging. |
GitHub | I used GitHub intentionally to build good habits. Working in branches, making meaningful commits, creating pull requests, and reviewing changes made the project feel much more like real software development instead of just hacking something together. |
Vercel | Used to deploy the shareable read-only list. Since BestList is a mobile app, I still needed a way for someone to open a shared list without downloading the app. |
EAS Build, Apple Developer & TestFlight | Used to build, sign, and distribute the app for iOS beta testing. |
My approach with AI
One thing that became surprisingly important was my AGENTS.md file.
I treated it as the source of truth for the project because it's the very first thing my coding agent reads each session.
Instead of relying on memory or rewriting instructions every chat, I documented everything in one place: MVP scope, styling rules, design system, tech stack, architecture decisions, and coding patterns.
That meant the agent wasn't making random implementation decisions.
It knew:
NativeWind only
TypeScript throughout
No unnecessary libraries
Mobile-only portrait layouts
Reuse existing components before creating new ones
Supabase is the source of truth (no mock data shortcuts)
Those constraints made the project feel much more intentional. The AI wasn't just generating code. It was working within a system I had already designed.
The other thing that changed my workflow was keeping each chat focused.
Instead of one giant conversation, every chat had one job.
Read
AGENTS.mdfirst.One feature.
Clear constraints.
Reference material when needed.
Simple prompts produced better results.
the messy middle
Refreshing my React knowledge
Halfway through the project I realized I had forgotten some React patterns.
Things like when to use an initial value versus a lazy initializer. Instead of moving on and hoping for the best, I paused and refreshed my understanding. It would've been easy to copy whatever AI suggested, but I wanted to understand my own codebase so I wasn't creating technical debt for future me.
Backend, databases, and security
This was honestly the part that intimidated me the most. Frontend bugs are annoying.
Security mistakes are scary. One of my biggest fears was accidentally exposing sensitive information or misconfiguring permissions. So this was another area where I intentionally slowed down. I spent time learning authentication, OAuth, API keys, environment variables, and what was actually happening under the hood.
One example was Google Sign-In.
I assumed creating an iOS Client ID was the correct choice because... I was building an iOS app. Turns out Supabase's authentication flow required a different setup because I needed redirect URLs. Understanding why that mattered taught me much more than simply following a tutorial.
Another concept I spent a lot of time learning was Row Level Security (RLS).
I wanted to make sure someone opening a read-only shared link couldn't accidentally modify data or gain access to someone else's account. Those aren't the most exciting parts of software development, but they're some of the most important.
Pull requests and CodeRabbit
One of the best habits I picked up was using pull requests even though I was the only developer.
I'd create a branch, finish a feature, let CodeRabbit review it, then take the time to understand whether each suggestion actually made sense.
That review process forced me to slow down.
Instead of immediately merging because "it works," I started asking:
Is this readable?
Is this maintainable?
Is this actually an improvement?
For a first React Native project, I think that was one of the best habits I could've built.
Current status
BestList is officially on TestFlight and ready for beta testing. Which honestly feels surreal.
If you'd like to help test it, click here.
The next challenge: putting BestList out into the world
Ironically, building the app wasn't my biggest fear. Marketing it is. Shipping means letting people see something that isn't perfect. It means opening yourself up to feedback and accepting that someone might think your idea is dumb. That's scary.
I've always been someone who's happiest behind the scenes. Being the person building something is very different from being the person sharing it. But that's also the point of this website.To be proud of the things I create. To document the messy middle.
And maybe... instead of lurking on Reddit for once, I'll actually post something.
Future builds
This definitely isn't the end of BestList.
I have a long list of ideas that didn't make the MVP, but now I finally get to build from a stable foundation instead of trying to do everything at once.
Some things I'm excited to explore:
Improving the onboarding experience.
Making lists feel more personal and customizable.
Better search and filtering.
More detailed stats and insights.
Refining the overall UI and interactions based on beta feedback.
More importantly, I want to continue documenting the journey.
There are so many topics from this project that deserve their own post:
What I learned about authentication and OAuth.
Why RLS matters.
My AGENTS.md workflow.
Working with AI intentionally.
Shipping with EAS Build and TestFlight.
Lessons from my first beta test.
This post is really just the beginning.
key takeaway
A few months ago I wrote:
"Programming is hard."
I'd update that now. Building software is hard. Software isn't just writing code.
It's product design. UX/UI. Architecture. Backend. Security. Deployment. Testing. Maintenance. Communication.
Building BestList gave me a completely different appreciation for everyone involved in creating software. If an app crashes or has a bug, I'm probably not going to get frustrated anymore. I know how much work goes into making something feel simple.
And finally...I have to remind myself that I built this app for me. I just happen to think other people might find it useful too.
this is not the ending of this journey.
If anything, shipping BestList feels like the beginning.This post wasn't meant to cover everything I learned because honestly... there's way too much. Over the next few weeks I'll be writing more about the technical lessons, the mistakes I made, the things that surprised me, and everything I wish I had known before building my first app. For now, I'm just going to take a second and appreciate the fact that something that started as a random idea is now sitting on my phone—and on a few other people's phones too. That's pretty cool. 😊