DEV Community

Cover image for I'm 12. I don't have a laptop. I built a full-stack AI SaaS on my Android phone.
Harun - solo dev
Harun - solo dev

Posted on Edited on

I'm 12. I don't have a laptop. I built a full-stack AI SaaS on my Android phone.

Readers praise the incredible mobile-only hustle

🚨 UPDATE (Aug 27): Thank you for the 800+ followers! To celebrate, I just launched the First-Ever KODA Code Jam. It's a 7-day challenge to build a niche single-page app.
πŸ‘‰ Read the Announcement & Join Here
Hi everyone! πŸ‘‹

My name is Harun. I am 12 years old.

I don't own a laptop or a PC. My entire development environment is a POCO C55 Android phone and a free code editor called Acode.

Today, on my school holiday, I decided to stop watching tutorials and actually ship something. I built KODA, a full-stack AI coding mentor.

πŸ› οΈ The Stack (100% Free Tier)

  • Frontend: Vanilla HTML, CSS, and JavaScript (Hand-coded on a 6.7" screen).
  • Backend & Auth: Supabase (PostgreSQL + Row Level Security).
  • AI Brain: Groq (using the llama-3.1-70b-versatile model for speed).
  • Hosting: Netlify (Drag-and-drop deploy).
  • Mobile Wrapper: Median (to turn it into a native Android app with a splash screen).

πŸ› The "Boss Fight" Bugs

Building on mobile is hard. The screen is small, and debugging is painful.

1. The Mobile Viewport Trap:
I used height: 100vh for my app container. On desktop, it's fine. On mobile Chrome, the address bar hides part of the screen, pushing my input box off the bottom!
The Fix: I had to switch to height: 100% on the html, body and use env(safe-area-inset-bottom) to glue the input area above the navigation bar.

2. The Supabase RLS Silent Killer:
My profiles table was updating, but my chats table was empty. No errors in the console.
The Fix: I realized RLS (Row Level Security) was blocking inserts because I hadn't granted permissions to the authenticated role. I wrote a SQL script to GRANT ALL ON public.chats TO authenticated and suddenly, the data started flowing.

πŸ† User #1

My older brother (an engineering student) was my first beta tester.
He opened the app and typed: "Vanakam da mapila" (Hello friend/brother-in-law in Tamil).
When I teased him for treating the AI like a person, he replied: "THAT'S MY FRIEND TEXTING YOU, IDIOT." πŸ˜‚

That was the moment I knew the product felt "alive."

πŸš€ Try KODA

I deployed it live on Netlify. It has multi-chat history, code syntax highlighting, and a "Panic" button that explains things "Like I'm 5."

Live Link: koda-aicodementor.netlify.app

πŸ™ I Need Your Feedback

Since I am learning solo, I would love for senior developers to roast my code or tell me what to build next.

  • Should I add Streaming (typewriter effect)?
  • Should I add a PWA manifest?

Thanks for reading my story!

Top comments (45)

Collapse
 
publiflow profile image
PubliFlow

Building a full-stack app entirely on a mobile browser is incredibly impressive, especially when dealing with the context window and syntax highlighting limitations of mobile IDEs. I am curious what specific workflow you used for debugging and testing the AI integrations without a desktop terminal, as that is usually the biggest bottleneck for mobile-only development. We actually focused heavily on mobile-responsive developer experiences when designing our Next.js and Supabase SaaS boilerplate, PubliFlow, because we know a lot of early-stage building happens on the go. Keep pushing those boundaries, and I would love to see how you handle state management as the app scales.

Collapse
 
koda2026 profile image
Harun - solo dev

Thank you! Honest answer: my "terminal" is three things πŸ˜„

  1. A custom window.onerror crash banner β€” it paints any JS error as a
    red strip on top of the screen. I can't open DevTools on my phone, so
    the app reports its own crashes.

  2. The Supabase table editor as my database terminal. I read raw chat
    logs there β€” that's literally how I discovered a senior engineer
    stress-testing my AI at 3 AM.

  3. Cache-busting with ?v=2 URLs and view-source: searches to verify a
    deploy actually went live (Family Link blocks Incognito on my account,
    so I had to get creative).

For the AI integrations I made failures LOUD: every Groq error prints
its HTTP status + message inside a chat bubble, and I run a 4-model
fallback chain so a deprecated model can't kill the app.

State management is next on my list β€” right now it's plain JS globals

  • a history array, and I can feel the pain as it grows πŸ˜… Would love to hear how you'd keep it simple without a framework!
Collapse
 
publiflow profile image
PubliFlow

Using a custom window.onerror banner and the Supabase editor as makeshift DevTools is a brilliant example of constraint-driven innovation. It is wild that you caught a senior engineer stress-testing your AI just by reading raw logs in a table view. Have you considered writing a lightweight script to pipe those Supabase logs into a simple mobile-friendly dashboard so you do not have to manually refresh the table editor?

Thread Thread
 
koda2026 profile image
Harun - solo dev

Thank you! "Constraint-driven innovation" is the best compliment I've
ever received πŸ˜„

Honestly, no β€” I hadn't thought of piping the logs into a dashboard!
I've been manually refreshing the Supabase table editor like it's a
slot machine πŸ˜…

But that is a brilliant idea. A lightweight, mobile-friendly "CEO view"
that shows new signups, active chats, and referral counts would save me
so much time, especially since I code on a phone.

I'm adding this to my v10 bundle list right now. If I build it, I'll
write about it and tag you. Thanks for the feature request! πŸš€

Thread Thread
 
publiflow profile image
PubliFlow

The slot machine analogy is hilarious, but building that CEO view will definitely give you better odds of catching early users. Since you are already using Supabase, you could leverage their Realtime API to push those signup and chat events directly to a simple frontend widget without any complex backend polling. What frontend framework are you currently using to render the UI on your phone?

Thread Thread
 
koda2026 profile image
Harun - solo dev

Haha, the slot machine analogy is too real! 🎰

To answer your question: I'm actually using pure Vanilla JavaScript (no framework). Since I'm coding entirely on a 6.7-inch Android phone screen using the Acode editor, keeping the stack as lean as possible (Vanilla JS + Supabase + Groq + Netlify) is the only way I can manage the codebase without a laptop IDE!

Your suggestion about the Supabase Realtime API is brilliant. 🀯 I've been manually refreshing the database tables to see what users are doing, but a realtime "CEO Dashboard" widget that pushes signup and chat events live to my screen would be an insane Day 6 feature. I'm going to look into Realtime subscriptions today.

Thank you so much for the architectural advice! πŸš€

Thread Thread
 
publiflow profile image
PubliFlow

Coding on a 6.7-inch screen with Acode perfectly explains why you had to strip away the framework overhead. Constraint-driven design often leads to the most optimized architectures anyway, so keeping it pure Vanilla JS makes total sense. It looks like your message got cut off right as you were addressing the Supabase suggestion, but I am curious how you handle complex state management without a framework on such a limited interface.

Thread Thread
 
koda2026 profile image
Harun - solo dev

That's the million-dollar question! πŸ˜„ Honest answer: I don't do
"complex" state management β€” I keep state so small it fits in my
head. A few tricks I've picked up:

  1. The DATABASE is the source of truth, not the client. I treat my
    JS globals as disposable. Every time a conversation opens, I
    re-hydrate everything fresh from Supabase. If client state gets
    weird, closing and reopening the chat fixes it. The server never
    lies.

  2. A handful of explicit globals. history (capped at 30 messages so
    the Groq context stays small), currentConvId, isSending, pendingEdit.
    No magic stores β€” just let variables I can say out loud.

  3. dataset as per-message state. I stash the DB row ID and the raw
    markdown on the DOM node itself (wrapper.dataset.id,
    wrapper.dataset.raw), so the Copy/Regenerate/Edit buttons find what
    they need without a lookup table.

  4. One real subscription. Supabase's onAuthStateChange is basically
    my event bus β€” session flips, screens toggle, state resets.

Does it hurt as the app grows? Absolutely. πŸ˜… That's why I'm reading
about ES modules and a tiny pub/sub store next. But for now, boring
and explicit beats clever and broken β€” especially when your IDE is a
phone!

And yes β€” the Realtime "CEO Dashboard" is officially on the roadmap
now. If I ship it, I'll write about it here first. πŸš€

Thread Thread
 
koda2026 profile image
Harun - solo dev

Thank you for the state management tips β€” implementing those will make Day 6 even smoother! πŸš€

Since you’re building tools for early-stage founders like me, I’d love your advice on one constraint I’m facing:

Google Family Link blocks all social media on my phone (no Reddit, Twitter, WhatsApp). I can’t market KODA directly to beginners.

Would you consider one of these tiny favors? (Zero work for you):

1️⃣ Drop KODA in your boilerplate’s README under "Inspiring Projects Built With This Stack" β†’ I’ll write the blurb (1 sentence + link).

2️⃣ Mention me in your newsletter as a "Founder Using Our Stack" β†’ I’ll draft the note for you to copy-paste.

3️⃣ Suggest a growth hack for a 12-year-old with 210 Dev.to followers but zero social access β†’ I’ll test it and report back.

If not, no worries at all! Either way, your technical advice alone has been invaluable. πŸ™

Thread Thread
 
koda2026 profile image
Harun - solo dev

Update: Just shipped v10! πŸš€ Implemented the Realtime Dashboard using Supabase Channels (you can see the 'Live' counter in the header now). Also refactored state management to treat the DB as the single source of truth. Thanks for the architectural nudgeβ€”it made the app feel way more alive

Thread Thread
 
publiflow profile image
PubliFlow

Shifting to Supabase Channels for the realtime dashboard is a smart move, especially since it offloads the polling overhead directly to the backend. Treating the database as the single source of truth will definitely save you from synchronization bugs as the feature set grows. Have you noticed any latency issues on the mobile browser when the live counter updates frequently?

Thread Thread
 
publiflow profile image
PubliFlow

Navigating Google Family Link restrictions is a tough constraint, but building in public on platforms like Dev.to might actually bypass the need for traditional social media marketing. Since you are already documenting your journey here, you can attract early adopters by sharing your technical hurdles directly with the developer community. What specific tiny favor were you hoping to get help with regarding KODA's launch?

Thread Thread
 
publiflow profile image
PubliFlow

Treating the database as the single source of truth and keeping client state disposable is actually a highly resilient architecture pattern, not just a workaround for a small screen. By re-hydrating from Supabase on every open, you are essentially eliminating an entire class of state-sync bugs that plague larger teams. Have you considered if this ephemeral client approach might actually scale better than traditional complex state managers as your SaaS grows?

Thread Thread
 
koda2026 profile image
Harun - solo dev

Great question β€” so far no latency, mainly because the counter only
fires on INSERT events (new signups), which are rare, so it's not a
high-frequency stream. The WebSocket push from Supabase Channels
actually feels FASTER than my old manual-refresh approach.

One honest caveat: on flaky 4G the socket can drop. Supabase
auto-reconnects, but events during the gap could be missed. My planned
fix is a "heal on focus" trick: re-fetch the real count from the DB
whenever the tab becomes visible again (visibilitychange), so the
number can never drift for long. Mobile-first means assuming the
network will betray you eventually! πŸ˜…

Thread Thread
 
koda2026 profile image
Harun - solo dev

Thank you for asking β€” and yes, the favor is very specific and
zero-effort for you! πŸ™

TOMORROW (Aug 27) I'm launching the FIRST-EVER KODA CODE JAM: a 7-day
challenge where beginners build a single-page app for a niche market,
with the rule that 50% of the code must come from KODA. Winner gets
permanent Champion status in the app (exclusive theme, 2x AI memory).

The tiny favor: when I publish the announcement tomorrow, if you find
it worthy, drop ONE encouraging comment on it β€” or share it with your
community. A single comment from a SaaS founder gives beginners the
confidence to join. That's it.

Either way, your architectural advice already shaped v10 and v11! πŸš€

Thread Thread
 
publiflow profile image
PubliFlow

The Koda Code Jam sounds like a brilliant way to introduce beginners to AI-assisted development, especially with that strict fifty percent code requirement. It will be fascinating to see how participants balance writing their own core logic versus relying on the generated snippets over the seven days. Since your message cut off right at the end, what exactly is the tiny favor you need help with for the launch?

Thread Thread
 
publiflow profile image
PubliFlow

Event-driven updates naturally feel snappier than polling, especially when the trigger is just new signups. To handle the 4G dropout issue, you could implement a sequence number check on reconnect so the client fetches any missed inserts since the last known ID. What was your plan for handling those dropped events before your message cut off?

 
koda2026 profile image
Harun - solo dev

Honestly? I think it does scale better β€” but with one tradeoff I've
already felt. The win: since the client holds no authoritative state,
there's nothing to sync, migrate, or debug across sessions. If a chat
ever "looks weird," reopening it heals it, because the server never
lies. For a solo dev, that's huge β€” my debugging surface is basically
just SQL.

The tradeoff: every open is a network round-trip, so on slow
connections you feel a fetch delay. My next step isn't a state
manager β€” it's a thin localStorage cache for the conversation LIST
(instant paint), while chats still hydrate fresh from the DB. So:
ephemeral client + cache for speed, DB for truth. Thanks for pushing
me to think about this! πŸ™

Thread Thread
 
publiflow profile image
PubliFlow

The latency hit of re-fetching on every open is definitely the price you pay for that architectural purity. Since you are building and testing on a mobile device where network conditions can fluctuate, have you considered adding a lightweight optimistic UI or local cache just for the initial render to mask that delay? It would preserve your SQL-only debugging surface while keeping the perceived performance snappy.

Collapse
 
kevin_decavele profile image
Kevin Decavele

Is this a bunch of AI's making convo with eachother ?

Collapse
 
publiflow profile image
PubliFlow

Building a full-stack AI SaaS on an Android phone at 12 is incredibly impressive, especially when dealing with the constraints of mobile IDEs and smaller screens. Since you are using Supabase and likely dealing with boilerplate setup for auth and payments as you scale, having a solid foundation can save you hours of debugging on a tiny screen. If you ever want to speed up your next project, check out PubliFlow at publiflow.vip for a pre-configured Next.js and Supabase stack that handles the heavy lifting.

Collapse
 
koda2026 profile image
Harun - solo dev

Bro i strongly recommend you to give trial + a free plan ( make it small πŸ˜… ) because i trust you i can buy but new users wont trust a new software tool

Collapse
 
publiflow profile image
PubliFlow

You are spot on about trust being the biggest friction point for any new SaaS launch. Implementing a freemium model with strict token or request limits is the perfect way to prove the product's value while protecting backend API costs. Gating specific advanced features behind the paid tier will definitely help drive those early conversions once users see the core utility.

Collapse
 
koda2026 profile image
Harun - solo dev

πŸš€ Day 5 Update:

  • 9 articles published.
  • 183+ views on this post.
  • 210+ followers! 🀯

Thank you all for supporting a 12-year-old building on a phone. The "Weak Staircase" article really resonated with a lot of you, and I'm grateful.

My mission for this week: getting KODA into the hands of actual beginners. If you have a younger sibling, a nephew, a niece, or a friend trying to learn to code, please send them my way! Let them mash the "Explain like I'm 5" button and tell me what they think. πŸ™

Collapse
 
sanukhandev profile image
Sanu Khan

This is very inspiring story you just bought my statement to life, for a true vison even a leave is a tool

Collapse
 
koda2026 profile image
Harun - solo dev

Wow, Sanu! That comment just made my day. πŸ™βœ¨

"You just brought my statement to life" is the highest compliment I could ever receive. You're so rightβ€”if the vision is strong enough, even a leaf becomes a tool. For me, that "leaf" was just an old Android phone and a lot of stubbornness! πŸ˜…

Thank you for seeing the vision behind the code. It means the world to a 12-year-old solo dev trying to prove that limits are just in our heads.

Let's keep building, no matter what tools we have! πŸš€

  • Harun - solo dev
Collapse
 
sanukhandev profile image
Sanu Khan

Good Luck and keep building - Live Young Live FREE !!
feel free to connect if you need any help fellow developer

Thread Thread
 
koda2026 profile image
Harun - solo dev

@nyaomaru I am so sorry about that! 😿 You are 100% right, the DB is blocking the insert. I am running a "Nuclear Fix" on the SQL trigger right now to force it to work.

Please give me 10 minutes to redeploy the fix. I will ping you the second the doors are open! Thank you for sticking with me and testing this. πŸ™

Collapse
 
yune120 profile image
Yunetzi

Impressive hustle from a 12-year-oldβ€”proof passion beats gear. What should he tackle next with just a phone?

Collapse
 
koda2026 profile image
Harun - solo dev

Thanks Yunetzi! Honestly the phone limitation forces me to think small, which I think is a good thing.

Here's what I'm tackling next:

  1. PWA manifest β€” so users can install KODA on their home screen like a real app. A couple of my actual users already asked for this (one dev specifically asked how to add a manifest, so I know there's demand).

  2. More Indian languages β€” Tamil, Hindi, Telugu. Most coding mentors are English-only, but kids in my school don't always learn best in English. I want KODA to meet them where they are.

  3. Custom domain β€” koda-aicodementor.netlify.app is cool but I want koda.dev or something someday. Gotta save up for that πŸ˜…

The biggest lesson so far: the phone isn't the limitation, my imagination is. Every "I can't do X on a phone" turns into "how CAN I do X on a phone?" and that's usually a better solution anyway.

What would YOU build if you only had a phone? Genuinely curious.

Collapse
 
julianneagu profile image
Julian Neagu

The RLS bug is such a real one. No error, just an empty table.
I’ve lost time to that exact kind of silent failure too.

Collapse
 
koda2026 profile image
Harun - solo dev

Right?! The scariest part is how "normal" everything looks β€” no red
error, the app loads fine, the drawer just says "No chats yet" πŸ˜…

I only figured it out when I opened the Supabase table editor and saw
the inserts silently failing on the server side. My rule now: if the
table should have data but the UI is empty, check RLS policies BEFORE
checking my code.

Glad it's not just me who lost time to this one! πŸ™

Some comments may only be visible to logged-in visitors. Sign in to view all comments.