Self-Taught to Shipped: A Journey
Published:
Umair Akhter
5 MIN READ
I didn’t go to school for this. I taught myself to code because I wanted to build things, and the only way to learn to build things is to build things.
Here’s what that journey actually looked like — the timeline, the wrong turns, and what I’d tell my past self.
The beginning: hobby projects nobody saw
The first two years were projects that lived on my local machine and nowhere else. A to-do app. A weather dashboard. A little automation script that saved me 20 minutes a week. Classic beginner trajectory.
The code was bad. But it was functional, and functional is the most important property code can have.
The mistake I made: keeping it local. Shipping — even a rough version, even to nobody — is a skill, and I didn’t practice it until much later than I should have. I spent months “almost ready to show people” and those months were wasted. Not the learning — the waiting.
The shift happened when I understood that shipping is not the reward for finishing. Shipping is how you finish.
The shift: building for others instead of myself
At some point I stopped asking “what would I find cool to build?” and started asking “what does a real person actually need?”
That reframe changed everything. A project for yourself has no user. A project for someone else has to work, has to be clear, has to solve the actual problem rather than the problem you assumed they had.
My first externally-facing tool was an automation for someone who was doing a repetitive task in a spreadsheet. It took four hours to build, saved them multiple hours per week. That feedback loop — building something, watching it help — is addictive in the right way. It also told me something important: the constraint of a real user makes you a better engineer than any amount of self-directed practice.
What self-teaching taught me that a curriculum wouldn’t
Resourcefulness. When you’re stuck, there’s no TA to ask. You figure it out, or you don’t ship. I’ve read more documentation, dug through more GitHub issues, and traced more stack traces than I can count. That skill compounds. Every time you debug something without help, you get a little better at debugging.
Scope control. Nobody told me what a reasonable project was. I had to learn it by over-engineering things that didn’t need it and under-specifying things that did. Both failure modes teach you quickly. Over-engineering a solo project is painful because you built complexity nobody asked for. Under-specifying means you launch something broken. Both experiences are data.
Shipping is a skill. Getting something from “it works on my machine” to “it’s deployed and someone else can use it” is non-trivial. It involves deployment, configuration, basic security thinking, error handling, and the ability to finish rather than endlessly refine. This skill is entirely separate from writing good code, and it’s arguably more important for a builder.
Reading other people’s code. Formal education teaches you to write code. Self-teaching forces you to read it. I’ve learned more from reading well-structured open source projects than from any tutorial. You see the decisions, the tradeoffs, the comments explaining why someone made a choice that looks strange at first.
The timeline
It took about two years from “writing scripts locally” to “building things people actually use.” Here’s the rough progression:
- Year 1: Tutorials, courses, local projects. Built fluency but no products.
- Year 2: First external tools. Started learning that real constraints (users, browsers, edge cases) are better teachers than exercises.
- Year 3: Chrome extensions with real users. First time something I built was used daily by people I’d never met.
- Now: Full-stack web apps, AI integrations, this site. Building in public.
The curve isn’t smooth. There were months where I shipped nothing useful. The common thread in the productive periods was always the same: a real user, a real problem, a deadline.
The tools I use now
My stack has settled. Astro for sites like this one. TypeScript everywhere — it catches mistakes before they reach users. Cloudflare for hosting. Python for automation and data work. AI tools for the parts of the process that benefit from assistance.
The tools aren’t the point. The discipline of shipping is the point. Good tooling just lowers the friction between idea and shipped product. The best tool is the one that gets out of your way.
What I’d tell my past self
Stop waiting until it’s ready. It will never be ready — that’s not a flaw in the project, it’s a feature of the medium. Software is never finished; it’s only shipped.
Find a real user as early as possible. A fake user (yourself, in a hypothetical) will let you get away with anything. A real user will find the edge case in ten minutes that you missed in ten hours.
Write while you build. The notes you keep about why you made a decision are more valuable than the decision itself. They become documentation, blog posts, answers to questions you’ll be asked later.
What comes next
I’m still learning. The gap between where I am and where I want to be is large, and that’s the point — it means there’s still interesting work to do.
The projects on this site are the evidence of the journey. Some are polished, some aren’t. All of them taught me something that I couldn’t have learned any other way.
Build something. Ship it. See what happens. That’s the whole method.