How to Learn to Code From Scratch in 2026: The Complete Guide
Table of Contents
To learn programming from scratch in 2026 you need three things: a language (Python is the best bet for most people), around 10 hours a week for about 12 months, and a strict protocol for using AI so that it doesn’t end up doing the learning for you. Everything else — the bootcamp, the degree, the trendy language — is optional. That isn’t.
This guide is written from the other side of the table. I don’t sell a course; I make a living writing software. That changes what I’m going to tell you, starting with the uncomfortable part almost nobody writes about: the 2026 junior market looks nothing like the 2021 one, and the way you were taught to study — watch tutorials, copy along, feel productive — is exactly what leaves you out today.
The good news is the path still exists, and it’s shorter than ever. You just have to walk it differently.
What’s in this guide
It’s long on purpose: it’s built to be reopened in three months, not read in one sitting. The stops:
- Is it still worth it in 2026? — the data, unvarnished
- What coding actually is — and the 6 myths that stall you
- Which language to pick
- Set up your environment in 30 minutes
- The 9 concepts that are 90% of programming
- Your first useful program, line by line
- Debugging: the skill that decides who stays
- Git and GitHub: the bare minimum
- How to use AI without stopping learning — the key chapter
- The 12-month roadmap, month by month
- The 7 projects that actually count
- How not to quit
- From portfolio to first job
- Free resources worth your time
- The mistakes that kill 90% of attempts
Is it still worth learning to code in 2026?
Yes — but the honest answer needs two paragraphs, not one.
The bad part first. Junior hiring has collapsed. According to SignalFire’s State of Tech Talent Report 2026, new-grad hiring is down roughly 65% at the big tech companies and 76% at early-stage startups compared to 2019. The report is blunt about why:
Software engineering graduates used to spend their first 12 to 18 months writing boilerplate code, running unit tests, and performing routine debugging while learning production systems under a mentor. Those are exactly the types of tasks that the Tech Majors have automated with AI.
That’s the real problem, and it’s worth understanding precisely: AI didn’t eliminate programming jobs, it eliminated the scaffolding that programmers were trained on. The bottom rung of the ladder is what broke.
Now the good part, which is bigger. That same report notes that top graduates are twice as likely to call themselves a founder as the 2022 class, because with 2026 tooling one person builds what used to take a team. And in the real market — the one that isn’t the five biggest tech companies — demand hasn’t disappeared. It moved.
What hiring managers can’t find today is someone who:
- understands a whole system and knows where to touch it without breaking it,
- can review AI-generated code and catch when it’s wrong,
- can ship a complete feature (database, logic, interface, deployment) instead of an isolated function,
- and can translate a business problem into something buildable.
A language model does none of that today. All of it is learned by writing code.
💡 The one-line summary. Nobody gets hired to write code anymore. People get hired to answer for code. And to answer for it, you have to understand it.
The stat almost nobody puts next to that one
While junior hiring fell, software output exploded. The result is far more code, written faster and maintained worse than ever. GitClear’s research on AI code quality, based on more than 600 million commits, measures exactly that:
| Metric | Pre-AI | 2026 |
|---|---|---|
| Duplicated blocks (index) | 40.3 (2023) | 73.0 (+81%) |
| Moved / refactored code | 21% (2022) | 3.8% |
| Churn (code rewritten within 2 weeks) | ~3.3% | 7.1% (2025) |
Translation: eight times more copy-paste, five times less refactoring, and code thrown away twice as fast. That’s technical debt piling up at a record rate, and somebody is going to have to understand it and fix it.
That somebody can be you. But only if you can read code, not just generate it.
What coding actually is (and what it isn’t)
Before installing anything, the mental model. Programming is describing to a machine, without ambiguity, how to turn some input data into a result. That’s it. Everything else — languages, frameworks, the cloud — sits on top of that idea.
And that unambiguous description has only three ingredients:
graph TB
A[Input data] --> B{Decision?}
B -->|yes| C[Do one thing]
B -->|no| D[Do another]
C --> E[Repeat as needed]
D --> E
E --> F[Result]
- Store data — variables and structures (a list of prices, a dictionary of users).
- Make decisions —
if this happens, do that. - Repeat —
do this for every item in the list.
That’s all of it. A banking system and a video game are enormous combinations of those three bricks. Someone with twenty years of experience doesn’t have more bricks — they have better judgment about how to stack them.
The 6 myths that stall people at the starting line
“You need to be good at math.” False for 95% of the work. Web apps, business systems, mobile apps and automation need high-school arithmetic and logic, which is a different thing. You do need real math for 3D graphics, cryptography, machine learning from first principles, or scientific simulation. None of those is your first job.
“You need perfect English.” If you’re reading this, you’ve cleared that bar. If English isn’t your first language: learn to read technical English, don’t wait until you can speak it. Documentation translates, error messages can be pasted into a chat and explained back to you, and a language’s keywords number about thirty.
“I’m too old.” Age bias in tech exists; I won’t pretend otherwise. But a career change at 35 or 45 arrives with something a 20-year-old doesn’t have: you understand how a company works, you can talk to a client, and you’ve watched projects fail. That is exactly what junior teams lack.
“I need a powerful computer.” Any machine from the last eight years with 8 GB of RAM handles everything in this guide. You need a strong machine for video editing, model training, or compiling huge projects. Not for learning.
“I need a degree.” It helps clear the HR filter at large corporates. You don’t need it for the small business, the agency, freelancing, or the startup — which is where nearly all first jobs come from. What you do need is evidence: public code that works.
“It’s too late, AI does it all.” AI writes functions. It doesn’t decide what to build, doesn’t answer to a client, doesn’t understand why the business bills the way it does — and, by developers’ own account, it gets things half right: in the 2025 Stack Overflow survey, the number one frustration, at 66%, was running into “AI solutions that are almost right, but not quite.” Another 45% add that debugging AI-generated code is more time-consuming for them.
Someone has to notice where the almost is.
The decision that blocks you: which language to pick
This is where half the people stall for weeks. Let me take the decision off your hands:
👉 Start with Python. Full stop. If by the end of this guide you discover that web interfaces are your thing, switch to JavaScript in week 12 and it will have cost you nothing: 90% of what you learned transfers intact.
Why Python and not something else
Python is number one in the TIOBE index for August 2026 at 18.53%, well ahead of second place. But popularity isn’t the reason. These are:
- It reads almost like English.
if age >= 18: print("adult"). No braces, no semicolons, no type declarations. Every symbol you don’t have to learn is energy that goes into logic, which is the hard part. - The errors tell you what happened. Python’s error messages are among the most readable in existence, and learning to read them is half the battle.
- It covers most of what you probably want to do: automating boring tasks, analyzing data, building APIs, scraping the web, and absolutely everything AI-related.
- The career exits aren’t only “programmer”: data analyst, automation, QA, DevOps and data scientist all ask for Python.
When NOT to start with Python
| If your goal is… | Start with | Why |
|---|---|---|
| Web pages, interfaces, animation | JavaScript | It’s the only language that runs in the browser. There’s no alternative |
| Native iPhone/Android apps | Swift / Kotlin | Learning another language first costs you months |
| Automating your office job now | Python | Excel, PDFs, email, folders. Results in week one |
| Data, AI, analytics | Python | Not a debate |
| Games | C# (Unity) or GDScript (Godot) | The engine dictates the language |
| WordPress, e-commerce, agencies | PHP | It’s where the real work is in that niche |
| “I don’t know yet” | Python | It’s the default answer, and it’s a good one |
So when does JavaScript come in?
JavaScript is almost certainly your second language, because it’s the only one that runs inside the browser: if you want something visible and clickable on a web page, it goes through JS. Throughout this guide I’ll show the JavaScript equivalent of the key examples, marked as optional, so you can see with your own eyes that the logic is identical and only the punctuation changes.
Don’t study both at once. Glance at them side by side when they appear, and pick one to practice.
⚠️ The trendy-language trap. Every year there’s a language that’s “going to replace everything” — Rust, Go, Zig, Mojo. They’re all good and none of them is your first language: their communities assume you already program. Rust entered the TIOBE top 10 in July 2026 and it’s a superb language; it’s also probably the worst language on earth to learn programming with.
Set up your environment in 30 minutes
Goal: write code and run it. You need nothing else, and all of it is free.
Option A — Install nothing (5 minutes)
If you want to write your first line today, go to replit.com or Google Colab and create a Python notebook. It works even on a phone.
Use it for week one. Then install Python for real: learning to drive your own machine is part of the job, and in an interview it shows who never left the browser.
Option B — The real install (30 minutes)
Step 1. Install Python. The stable release as of August 2026 is Python 3.14 (3.14.7 since August 5). 3.15 lands in October; don’t wait for it.
# Windows (from PowerShell)
winget install Python.Python.3.14
# macOS (with Homebrew)
brew install [email protected]
# Ubuntu / Debian / WSL
sudo apt update && sudo apt install python3 python3-pip python3-venv
⚠️ Windows: if you install from the python.org
.exeinstead of usingwinget, tick the “Add python.exe to PATH” box on the first screen. It’s the cause of 90% of thepython is not recognized as a commandposts you’ll find in forums.
Check that it worked:
python --version
# Python 3.14.7
Step 2. Install VS Code. It’s Microsoft’s free editor and the de facto standard. Get it from code.visualstudio.com and install only two extensions to start: Python (by Microsoft) and Error Lens (shows the error inline instead of in a panel).
Don’t install twenty extensions on day one. If you want to tune the editor later, I keep an annotated list in the 20 best VS Code extensions.
Step 3. Learn five terminal commands. The terminal is scary until you find out that 95% of daily use is these:
pwd # where am I?
ls # what's here? (PowerShell: dir)
cd folder # go into a folder
cd .. # go up one level
mkdir name # create a folder
Step 4. Create your working folder and first file.
mkdir learning && cd learning
code .
Inside VS Code create hello.py with this:
name = input("What's your name? ")
print(f"Hi, {name}. You just wrote a program.")
And run it from the integrated terminal (Ctrl+`):
python hello.py
If it answered you, your environment is ready. Seriously: that’s everything you need for the next six months.
The same thing in JavaScript (optional — skip it if you’re going with Python)
You’ll need Node.js installed. The file would be hello.js:
const readline = require('node:readline/promises');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const name = await rl.question("What's your name? ");
console.log(`Hi, ${name}. You just wrote a program.`);
rl.close();
Run it with node hello.js. Notice what changed: braces, semicolons, and considerably more ceremony just to read one line of text. That’s why we start with Python.
Virtual environments, explained once
The moment you install your first library you’ll read about venv and nobody will tell you why. It’s simple: a virtual environment is a backpack of libraries that belongs to one project only. Without it, all your projects share the same versions, and the day one of them needs a different version, you break the others.
python -m venv .venv # create the backpack
source .venv/bin/activate # put it on (macOS/Linux)
.venv\Scripts\activate # put it on (Windows)
pip install requests # install something inside
deactivate # take it off
Rule: one project folder, one .venv. Always create it, even for a ten-line project. It’s a three-second habit that prevents entire afternoons of pain.
The 9 concepts that are 90% of programming
Master these nine and you can read almost any program on earth. Everything else is variations and libraries.
Give them four to six weeks. Don’t read them: write them. Every code block in this section should be typed by you — not copied — and then broken on purpose to see what error comes out.
1. Variables: named boxes
A variable is a name pointing at a value. You write it with =.
name = "Ana"
age = 34
height = 1.68
is_customer = True
Python infers the type for you: text (str), integer (int), decimal (float), boolean (bool). You can ask it:
print(type(age)) # <class 'int'>
The classic trap: "5" + "3" gives "53", not 8. The + on text concatenates. Anything coming from input() is always text, even when it looks like a number:
age = input("Your age: ") # "34" ← text
age = int(input("Your age: ")) # 34 ← number
2. Data structures: when one box isn’t enough
The two you’ll use 90% of the time:
Lists — ordered collections, accessed by position (starting at 0):
prices = [120, 340, 89, 1500]
print(prices[0]) # 120
print(prices[-1]) # 1500 (the last one)
print(len(prices)) # 4
prices.append(200) # add at the end
Dictionaries — key→value pairs, accessed by name:
customer = {
"name": "Ana",
"email": "[email protected]",
"balance": 1500,
}
print(customer["name"]) # Ana
print(customer.get("phone")) # None, and it doesn't blow up
customer["phone"] = "555-1234" # add
Which one to use: if you’re going to walk through everything, list. If you’re going to look things up by an identifier, dictionary. Looking something up in a dictionary is instant even with a million entries; looking it up in a list means walking the whole thing. That difference is called algorithmic complexity, and that’s already 80% of what you need to know about it.
3. Conditionals: making decisions
balance = 1500
if balance > 1000:
print("Premium customer")
elif balance > 0:
print("Standard customer")
else:
print("No balance")
Indentation in Python isn’t cosmetic: it’s syntax. Those four spaces are what marks something as being inside the if. In other languages braces do that job.
The classic trap: confusing = (assign) with == (compare). if balance = 1000 is a syntax error in Python — and thanks to that, an error you find instantly instead of three days later.
The same thing in JavaScript (optional)
const balance = 1500;
if (balance > 1000) {
console.log("Premium customer");
} else if (balance > 0) {
console.log("Standard customer");
} else {
console.log("No balance");
}
Identical logic. Parentheses, braces, and elif becomes else if. In JavaScript always compare with === (three equals), not ==: the double equals does automatic conversions that produce surprises like 0 == "0" being true.
4. Loops: repeating without repeating yourself
prices = [120, 340, 89, 1500]
for price in prices:
print(f"The price is {price}")
total = 0
for price in prices:
total += price # total = total + price
print(f"Total: {total}") # Total: 2049
while repeats as long as a condition holds, and it’s where beginners’ programs hang:
attempts = 0
while attempts < 3:
print("Trying…")
attempts += 1 # ← forget this line and it loops forever
Survival tip: Ctrl+C in the terminal kills a hung program.
5. Functions: packaging an idea
A function is a named piece of logic that takes data in and hands a result back.
def add_tax(amount, rate=0.16):
"""Return the amount with tax included."""
return amount * (1 + rate)
print(add_tax(1000)) # 1160.0
print(add_tax(1000, 0.08)) # 1080.0
Three rules that will save you years:
- A function does one thing. If describing it requires an “and,” it’s two functions.
- The name is a verb and says what it does:
add_tax, notprocess1. - Return, don’t print. A function that prints is only good for showing things on screen; one that returns is good for everything, including printing it afterwards.
6. Errors and exceptions: keeping the program alive
try:
age = int(input("Your age: "))
except ValueError:
print("That's not a number. Using 0.")
age = 0
Don’t use a bare except: or except Exception: for everything. Catching every error hides the ones you didn’t expect, and then you spend hours hunting a bug the program was silently swallowing. Catch the specific error you know can happen.
7. Files: talking to the outside world
# read
with open("data.txt", encoding="utf-8") as f:
content = f.read()
# write
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello from Python")
with closes the file for you, even if something fails halfway. Always use it.
Always pass encoding="utf-8". Otherwise, the day a file arrives with an accent or an emoji, your program crashes on Windows and works on Mac, and you’ll lose an afternoon figuring out why.
8. Modules and libraries: not reinventing the wheel
import json # ships with Python
from datetime import date # just one piece
today = date.today()
print(today.isoformat()) # 2026-08-15
For anything not included, pip (with the virtual environment active):
pip install requests
import requests
response = requests.get("https://api.github.com/users/ortamarco")
data = response.json()
print(data["public_repos"])
You just consumed an API. Those four lines are the foundation of an enormous share of modern software.
9. Classes: when data and logic travel together
The last concept, and the one you can postpone longest. A class is a mold for creating objects that carry data and the functions that operate on it.
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Amount must be positive")
self.balance += amount
return self.balance
account = BankAccount("Ana", 1000)
account.deposit(500)
print(account.balance) # 1500
You don’t need to master inheritance, polymorphism or design patterns for your first job. You need to read a class and understand what it does, because all the professional code you’ll touch is full of them.
✅ Proof you’ve got the 9. Without looking anything up, write a program that reads a text file with one name per line, counts how many times each appears, and saves the sorted result to another file. If it takes you under an hour, this stage is done.
Your first useful program, line by line
Tutorials have you build a calculator. We’re going to build something you’d actually use: an expense analyzer that reads a CSV exported from your bank and tells you where the money goes.
Create expenses.csv:
date,description,category,amount
2026-08-01,Supermarket,food,125.50
2026-08-03,Gas,transport,80.00
2026-08-05,Restaurant,food,45.75
2026-08-08,Rideshare,transport,18.00
2026-08-10,Streaming,subscriptions,21.90
2026-08-12,Supermarket,food,98.25
And analyze.py:
import csv
from collections import defaultdict
def read_expenses(path):
"""Read the CSV and return a list of dictionaries."""
with open(path, encoding="utf-8") as f:
return list(csv.DictReader(f))
def total_by_category(expenses):
"""Return {category: total} from the list of expenses."""
totals = defaultdict(float)
for expense in expenses:
totals[expense["category"]] += float(expense["amount"])
return dict(totals)
def format_report(totals):
"""Turn the totals into readable text, largest first."""
grand_total = sum(totals.values())
lines = ["EXPENSE REPORT", "=" * 40]
for category, amount in sorted(totals.items(), key=lambda x: -x[1]):
percentage = amount / grand_total * 100
bar = "█" * int(percentage / 5)
lines.append(f"{category:<15} ${amount:>9,.2f} {percentage:5.1f}% {bar}")
lines.append("=" * 40)
lines.append(f"{'TOTAL':<15} ${grand_total:>9,.2f}")
return "\n".join(lines)
if __name__ == "__main__":
expenses = read_expenses("expenses.csv")
totals = total_by_category(expenses)
print(format_report(totals))
Run it:
python analyze.py
EXPENSE REPORT
========================================
food $ 269.50 73.1% ██████████████
transport $ 98.00 26.6% █████
subscriptions $ 21.90 5.9% █
========================================
TOTAL $ 389.40
What you just learned without noticing
This 30-line program contains more good practice than most three-hour tutorials:
| Detail in the code | Why it matters |
|---|---|
| Three small functions instead of one block | Each can be tested and fixed on its own. It’s the difference between beginner code and professional code |
read / total / format kept separate | Tomorrow you want to read from a database: you change one function and the other two never notice |
if __name__ == "__main__": | Lets you import this file from another without it running itself. It’s standard Python idiom |
defaultdict(float) | Avoids the classic if category not in totals: totals[category] = 0 |
key=lambda x: -x[1] | Sort by value, descending. You’ll use this a thousand times |
f"{amount:>9,.2f}" | Formatting: right-aligned to 9 chars, thousands separator, 2 decimals |
The docstrings in """ | Your future self, three weeks from now, will thank you |
Now break it (this is the important part)
Modifying working code someone else wrote is the fastest way to learn. Do it with this one, in order:
- Add a
payment_methodcolumn to the CSV and a report grouped by it. - Filter: only sum expenses from a month you pass in.
- Make it accept the file path from the command line (
import sys,sys.argv[1]). - Warn if any category exceeds 40% of the total.
- Export the report to a file instead of printing it.
When all five work, you can program in the sense that matters to whoever is hiring.
Debugging: the skill that separates those who stay from those who quit
Nobody writes a course called “how to debug,” and yet it’s where you’ll spend half your professional life. It’s also the exact point where people quit — not because the concept is hard, but because they believe the error means they aren’t cut out for this.
It doesn’t. Errors are the normal working mechanism. A developer with fifteen years of experience sees errors all day; the difference is they take thirty seconds where you take two hours. That difference is learnable, and it’s learnable fast.
Step 1: read the error bottom-up
Python tells you everything. The problem is that almost nobody reads it.
Traceback (most recent call last):
File "/home/ana/learning/analyze.py", line 32, in <module>
totals = total_by_category(expenses)
File "/home/ana/learning/analyze.py", line 17, in total_by_category
totals[expense["category"]] += float(expense["amount"])
^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: could not convert string to float: '1,250.50'
Read it in this order:
- The last line says what happened:
ValueError: could not convert string to float: '1,250.50'.'1,250.50'couldn’t be turned into a number. - The last
Filesays where: line 17 ofanalyze.py. - The
^^^^arrows say exactly which expression blew up. - The lines above are the path taken to get there.
That’s a complete diagnosis: the CSV uses commas as thousands separators and float() doesn’t understand them. The fix is float(expense["amount"].replace(",", "")).
Rule: never ask for help — from a person or an AI — without having read the last line of the error. At least half the time, the answer is written right there.
Step 2: the four errors you’ll see 80% of the time
| Error | What it really means | Where to look |
|---|---|---|
NameError: name 'x' is not defined | Typo, or you’re using it before creating it | Hunt the typo; check the order of your lines |
TypeError | You’re mixing types — text with number — or calling something that isn’t a function | Did that value come from input() or a file? Then it’s text |
IndexError / KeyError | You asked for position 5 of a 3-item list, or a key that doesn’t exist | Print the list/dict right before the failing line |
IndentationError | Spaces and tabs mixed, or bad alignment | Turn on “Render Whitespace” in VS Code |
Step 3: the well-placed print (yes, it works, and it works well)
Some people will tell you that debugging with print is amateur hour. Ignore them: it’s the most-used technique on earth, including by the people who deny it. What matters is placing it well:
# ❌ useless: you can't tell which of your six prints this is
print(expense)
# ✅ useful: label, type and value
print(f"[total] expense={expense!r} amount_type={type(expense['amount'])}")
The !r shows the value “as stored,” quotes included. That’s what reveals '1,250.50' is text and not a number — exactly the information you needed.
Step 4: the real debugger (5 minutes of your life)
When print isn’t enough, Python has shipped a debugger forever. Drop this line wherever you want the program to stop:
breakpoint()
Run normally and the program pauses there, handing you a console where typing any variable name shows its value. Four commands and you know how to use it:
n → run the next line
s → step inside the function
c → continue to the next breakpoint
q → quit
In VS Code it’s even easier: click to the left of the line number (a red dot appears) and press F5.
Step 5: bisection, the ultimate weapon
When you have no idea where the bug is, don’t read all the code. Cut the problem in half.
Comment out half the program. Still failing? The bug is in the half that’s left. Not failing anymore? It’s in the half you commented out. Repeat. Ten bisection steps locate a bug in a thousand lines.
It’s the same principle as git bisect, which you’ll use a year from now to find which commit broke something.
🧠 The 20-minute rule. If you’ve been stuck on the same error for 20 minutes with no new hypothesis, stop. Get up, walk for five minutes, come back. Still stuck after another 20? Then ask — an AI, a forum, a person. Not sooner (you don’t learn) and not much later (you demoralize). That timer is, literally, the single habit that most separates people who finish from people who quit.
Git and GitHub: the bare minimum
Git keeps the history of your code. GitHub hosts it online. Start using it in week 3, not when you “already know how to program”: your GitHub repo is going to be your résumé, and a year of small commits is worth more than any certificate.
These eight commands cover 95% of your first year:
git init # start versioning this folder
git status # what changed? (use it constantly)
git add . # stage all changes
git commit -m "Add report by category" # save a checkpoint
git log --oneline # view history
git push # upload to GitHub
git pull # fetch changes from GitHub
git checkout -- file.py # undo changes to one file
Three rules worth an entire course:
- Small, frequent commits. One per meaningful change, not one per day. The message is written in the imperative and says what it does, not what you touched: “Add validation for negative amounts,” not “changes.”
- Never commit secrets. Passwords, API keys and
.envfiles never go to GitHub. Once pushed, treat it as leaked even if you delete the commit. - Use a
.gitignorefrom the first commit. Keeps.venv,__pycache__and OS junk out of your history.
How to use AI without stopping learning
This is the chapter that makes a 2026 guide different from a 2021 one. Read it twice.
AI is, without exaggeration, the best learning tool that has ever existed for programming: you have an infinitely patient tutor who will explain any error at three in the morning. It is also the fastest way to never learn. Both are true, and which one you get depends entirely on how you use it.
What the data says (and why you should take it seriously)
- 62% of knowledge workers admit they think less critically when using AI, per the Microsoft Research and Carnegie Mellon study covering 936 real-world uses. The same paper contains the decisive detail: the more confidence you have in the AI, the less you verify; the more confidence you have in yourself, the more you verify. When you’re learning, your self-confidence is low by definition. You are squarely in the highest-risk profile.
- Only 3.1% of developers highly trust AI accuracy, against 45.7% who distrust it, per the 2025 Stack Overflow survey. And the number worth keeping: when developers don’t trust an AI answer, 75.3% go ask a person. Human judgment is still the referee — and that judgment is exactly what you’re building right now.
- METR’s productivity study measured something brutal: experienced developers were 19% slower using AI, and still believed they’d been 20% faster. Feeling like you’re learning fast is not evidence that you’re learning. (Honest footnote: METR has since labeled that result historical and found signs of speedup in later 2026 experiments. What hasn’t changed is the gap between perception and reality, which is what matters here.)
Put those three together and you get the portrait of the forever junior: someone who produces code that works, can’t explain it, and freezes the moment the problem leaves the ground where AI is reliable.
The two-hats protocol
The answer isn’t banning AI — that would be absurd and would price you out of the market. The answer is never wearing both hats at once.
graph TB
A[New task] --> B{Is this a concept<br/>I'm still learning?}
B -->|Yes| C[STUDENT HAT]
B -->|No: repetitive<br/>or already mastered| D[PILOT HAT]
C --> E[Write it yourself first.<br/>Even if it's ugly]
E --> F[Make it work]
F --> G[Now ask AI to review<br/>and explain]
G --> H[Rewrite it yourself<br/>with what you learned]
D --> I[Delegate, but read<br/>line by line]
I --> J[If you don't understand it,<br/>you don't accept it]
H --> K[You learned]
J --> K
Student hat (the first 6 months, nearly always): you write it first. Always. Even if it takes forty minutes and comes out ugly. Only after it works do you ask the AI to review it and explain what it would do differently. The order is non-negotiable, because learning happens in the effort of attempting, not in reading the solution.
Pilot hat (later, and for the boring parts): you delegate and review. But you review properly, line by line, with the standard that if you don’t understand a line, it doesn’t go into your code.
The five prompts that actually teach you
The difference between using AI as a tutor or as a crutch is almost entirely in how you ask.
| ❌ Prompt that leaves you where you were | ✅ Prompt that teaches you |
|---|---|
| “Write me a program that reads a CSV and totals by category” | “I wrote this and it throws ValueError. Don’t give me the fixed code: explain what the error means and give me a hint about where to look” |
| “Fix this code” | “Why does my version work but is still a bad idea? Compare it to the idiomatic form and tell me what I gain by changing” |
| “How do I do X in Python?” | “I know lists, dictionaries and functions. Explain X using only those, and tell me which new concept I need to learn to do it properly” |
| “Write the tests” | “Give me 5 edge cases my function probably doesn’t handle. Don’t write code — just the cases” |
| “Explain decorators” | “Give me three exercises of increasing difficulty on decorators, no solutions. I’ll bring you my attempts and you correct them” |
Notice the pattern: you ask for hints, comparisons, edge cases and exercises; never the complete solution. That last one — asking for exercises and bringing your attempts — turns the model into the private tutor you couldn’t afford.
The traffic light: what to delegate and what not to
| 🟢 Delegate guilt-free | 🟡 Delegate and review hard | 🔴 Never while learning |
|---|---|---|
| Explaining an error to you | Boilerplate (CRUD, forms) | The exercises in your study path |
| Translating documentation | SQL queries | Your first attempt at any new concept |
| Generating test data | Regular expressions | Portfolio projects (the core, at least) |
| Renaming and reformatting | Config files (Docker, CI) | Anything you can’t explain out loud |
| Summarizing a long file | Unit tests | The business logic you were hired to understand |
The explanation test (do this every Friday)
Open the code you wrote this week. Pick three blocks at random. Explain them out loud, as if to someone who programs but hasn’t seen your project.
- If you can: that code is yours, whether AI helped or not.
- If you can’t: delete it and write it again. It isn’t yours, and in a technical interview that shows within thirty seconds.
It’s uncomfortable, and it’s the highest-return practice in this entire guide.
⚠️ The mistake you’ll see everywhere. Plenty of people learn to direct an AI agent before they can read code, and produce whole applications that work… until they don’t. When that happens — and it does — there’s nobody to ask, because the agent no longer fits the whole project in its context and you don’t understand even the first file. On the concrete risks of that code, I wrote secure vibe coding: between 40% and 60% of model-generated code carries some OWASP Top 10 vulnerability.
Which tools to use (August 2026)
For learning, three are enough, and all three have free tiers:
- A chat (Claude, ChatGPT or Gemini) for explanations, questions and the tutor role. It’s the one you’ll use most and the one that fits the protocol above best.
- Editor autocomplete (GitHub Copilot — free for students, with a general free tier). Turn it off for the first three months. Having your line completed before you’ve thought it is exactly what stops you learning it.
- An agent (Claude Code, Cursor, Codex) for projects. Don’t touch it until month 6. Before that it will only build you things you don’t understand.
If you later want to know what running this seriously costs, I have the numbers in how much AI coding agents cost.
The 12-month roadmap, month by month
Twelve months at 10 hours a week — roughly 500 hours total. It’s the realistic minimum to reach a hireable level, and it’s sustainable alongside a job and a family. At 20 hours a week you cover it in six or seven months; at 4 hours, in two years. What doesn’t work is 30 hours one week and none for the next three.
| Month | Focus | What you should be able to do by the end |
|---|---|---|
| 1 | Syntax and the 9 concepts | Write a 50-line script with functions, without copying |
| 2 | Deliberate practice | Solve 30–40 small exercises; read a traceback unaided |
| 3 | Files, CSV, JSON, APIs + Git | Automate a real task of your own; first repo on GitHub |
| 4 | Project 1, start to finish | Ship something with a README, error handling and test data |
| 5 | Databases (SQLite and SQL) | Design 3 related tables and query them with JOIN |
| 6 | Pick a lane: web, data or automation | Have tried all three and chosen on evidence, not hype |
| 7-8 | Your lane’s framework (FastAPI/Django, or pandas) | Project 2: an app with a database and users |
| 9 | Deploy: make it exist on the internet | Your project running on a domain, not on your laptop |
| 10 | Tests, quality, and reading other people’s code | Write tests; land a small fix in an open-source project |
| 11 | Project 3: the portfolio centerpiece | Something that solves a real problem for someone you know |
| 12 | Packaging and job search | CV, tidy GitHub, LinkedIn, 20 applications sent |
How those 10 hours split
This split matters more than the total:
- 6 h writing code yourself. Exercises and project. It’s the only part that produces real learning.
- 2 h reading other people’s code. Small repos on GitHub, official docs, your own code from a month ago. Nobody does this, and it’s where the jump beyond junior is won.
- 1 h of theory. A video, a chapter, a course. One hour only. More than that is the trap described below.
- 1 h of review and notes. Rewriting in your own words what you learned this week. It sounds like school and it works for the same reason it worked in school.
The three forks at month 6
| Lane | What you build | Minimum stack | Market reality |
|---|---|---|---|
| Web (backend) | APIs, dashboards, business systems | Python + FastAPI or Django + PostgreSQL | Largest and most accessible without a degree |
| Web (frontend) | Interfaces, storefronts, visual products | JavaScript + React or Astro + CSS | Large, more crowded, more visual portfolio |
| Data / AI | Reports, dashboards, models, automation | Python + pandas + SQL | Growing fast; usually asks for more prior training |
| Automation / DevOps | Scripts, integrations, infrastructure | Python + Bash + Docker + a cloud provider | The most underrated, with the least junior competition |
If you’re unsure: backend with Python. It’s the lane with the most roles, the least dependent on fashion, and the best preparation for everything else. And if you end up in frontend, the natural route runs through understanding the JavaScript frameworks and properly learning CSS.
The 7 projects that actually count (and the ones that don’t)
A portfolio with three tutorial clones is worth zero. Whoever is hiring has seen the same Netflix clone four hundred times and knows exactly which YouTube video it came from.
What distinguishes a portfolio is that it solves a problem that existed before you needed a portfolio.
The criteria (apply them before you start anything)
- Would anybody use it, even one person? Your parent, your current boss, yourself. If not, it’s an exercise, not a project.
- Does it use real data? Real data means weird edge cases, which means interesting decisions to talk about in an interview.
- Can you explain why you chose each piece? If the answer to “why this database?” is “it’s the one in the tutorial,” it doesn’t count.
- Is it deployed? A link that opens is worth ten times a repository.
- Does it have a README? What it does, screenshots, how to run it, what you learned, what you’d do differently. It’s the first and sometimes only thing anyone reads.
The 7, in order of difficulty
- An automation for a real task of yours. Renaming invoices, sorting downloads by type, pulling data out of PDFs into a spreadsheet. Start here: it’s small, useful from day one, and forces you to handle files, errors and weird cases.
- A data collector on a public API. Query an API daily, store the history in SQLite, chart the trend. You touch APIs, databases, scheduled jobs and visualization.
- A command-line tool with arguments. The expense analyzer from this guide, properly finished:
argparse, validation, useful error messages, published on PyPI if you’re feeling brave. - A REST API with authentication. Users, login, permissions and auto-generated docs. It’s the project that most resembles actual work.
- A web dashboard over real data. Prices, weather, your city’s public transit, sports results. Backend + frontend + deployment.
- An integration between two services you use. A form that creates a spreadsheet row and fires a message. This is exactly what small businesses pay for, and almost no junior portfolio has it.
- A contribution to an open-source project. A small fix, a docs improvement, a missing test. It proves you can read someone else’s code and work inside their process — the rarest signal in a junior profile.
💡 The anchor-project trick. Instead of seven separate projects, take one and grow it over six months: first a script, then with a database, then an API, then an interface, then deployed, then with tests. The commit history tells the story of your learning better than any cover letter, and it avoids the portfolio of half-finished things.
How not to quit (the part nobody tells you)
Out of ten people who start learning to code on their own, one or two finish. The difference is almost never intelligence. It’s these four things.
1. The valley of despair
It’s real, and you should see it coming:
- Weeks 1-3 — euphoria. Everything is new, everything works, you feel like you’re flying.
- Weeks 4-10 — the valley. The feeling arrives that you understand nothing, that everyone else gets it faster, and that you’re wasting your time. This is where 70% quit.
- Weeks 11-20 — climbing out. You start solving things unaided. The click happens without warning.
- Month 6 onward — competence. The hard part is no longer the language, it’s deciding how to structure things.
The valley isn’t a sign you aren’t cut out for this. It’s the phase where you finally know enough to notice everything you don’t know. It is literally a consequence of having learned.
2. The tutorial trap
Watching someone code produces the same pleasant feeling as watching someone cook, and teaches the same amount: nothing. If you follow a video typing what appears on screen, you feel productive and you aren’t learning, because you never make the hard decision (what do I write now?).
The antidote is harsh but it works: for every hour of tutorial, two hours building something the tutorial didn’t cover. If you follow a course building a to-do API, then build an expenses one without looking. That’s where learning shows up.
3. Consistency beats intensity
One hour a day for six days beats six hours on Sunday, and that isn’t cheap motivation: memory consolidates through sleep and spaced repetition. Six contacts with the material produce far more retention than one long one.
In practice: block the same hour every day. If a day goes badly, do twenty minutes. The chain matters more than the duration; the zero is what kills you.
4. Learning alone is harder than it looks
This isn’t about morale: getting stuck with nobody to unstick you is the mechanical cause of quitting. Find at least one of these:
- An active Discord for your language.
- A study partner you check in with every Friday. That alone multiplies completion rates.
- A local meetup or community, even if you don’t follow half the talks in year one.
- Writing in public about what you learn: a thread, a post, a repo of notes. Explaining consolidates, and it builds your reputation before you have experience.
From portfolio to first job
Let’s talk numbers, honestly.
What juniors actually earn
| Source | Role | Figure (2026) |
|---|---|---|
| ZipRecruiter (US, Aug 12 2026) | Junior AI developer | $88,976 / year average |
| US aggregate job postings | Entry-level engineer, base | $70K–$95K |
| Bootcamp-reported outcomes | First job after bootcamp | ~$70,700 |
| Academy marketing pages | “Junior developer” | Consistently higher than all of the above |
That last row deserves a comment, because you’ll read it a lot: it’s marketing. The number on a bootcamp’s blog corresponds, at best, to a junior in a product company or with a foreign client — not to the role you reach with twelve months of study. Checking your expectations against sources built from real postings will save you an expensive disappointment.
And if you’re outside the US: remote work for foreign clients changes the scale entirely and doesn’t require a degree. It requires functional English, a portfolio someone can open, and the ability to work asynchronously. That’s a year-two goal, not a month-twelve one.
What hiring managers want in 2026
The junior market changed, and so did the profile being asked for:
- That you ship something complete, not a function. Database, logic, interface, deployed.
- That you use AI and can also review it. Saying “I use Claude Code daily” no longer differentiates anyone. What does differentiate is telling a story about a time you caught the AI being wrong, and why.
- That you can talk to humans. Turning a business problem into a technical plan is the scarcest and least automatable skill there is.
- That you have a public footprint. A GitHub with real activity and — if you dare — something written.
The four doors in, most to least accessible
| Door | Reality |
|---|---|
| A small business that needs automating | The most accessible. They don’t know they need a programmer; they find out when you show them an automation that saves 5 hours a week |
| Agency / consultancy | They hire in volume, train fast, pay less. It’s a paid school: you leave in 18 months with real experience and many projects seen |
| Small freelance work | Start with people who already know you. Charge little at first, hit your deadlines, ask for a testimonial. Slow and compounding |
| Startup / product company | Best paid, most demanding, and almost always wants prior experience. It’s the target for your second move, not your first |
💡 The strategy I see work most often. Offer to automate something at the job you already have. Reports, reconciliations, data loads, emails. That gets you the three otherwise-impossible things at once: a real, verifiable portfolio case; professional experience you can put on a CV; and often an internal role change without switching employers. If your current job isn’t technical, that’s your biggest competitive advantage, not your handicap.
Free resources worth your time in 2026
Everything you need to reach a hireable level is free. Genuinely. These are the ones still worth it, with their fine print:
| Resource | What it’s good for | The fine print |
|---|---|---|
| CS50x (Harvard) | Understanding how the machine works underneath: memory, algorithms, data structures | It starts in C and it’s tough. Do it in month 4-6, not on day one, or it will discourage you |
| freeCodeCamp | Structured path and certifications | Very guided: it’s easy to progress without thinking. Always pair it with your own project |
| The Odin Project | The closest to real work: it makes you read docs and get productively stuck | Web-focused. Many absolute beginners stall in the first month |
| Exercism | Exercises with free human mentoring in writing | Exercises, not projects. It’s the perfect side dish, not the main course |
| Official Python docs | The source of truth | Dense at first. Come back in month 3, when it starts paying off |
| Real Python | Deep, well-written articles on specific topics | Some content is paid |
| Roadmap.sh | Seeing the full map of a lane | Overwhelming. Use it to orient yourself, never as a to-do list |
How to combine them without wasting time: one main path (freeCodeCamp or The Odin Project), Exercism alongside for short practice, CS50 from month 4 for fundamentals, and the official docs as reference. Don’t run two main paths at once. It’s the most common way to finish neither.
What about paid bootcamps?
They can be worth it, on one condition: that you’re buying what a bootcamp genuinely provides and you can’t get free, which is structure, pace and people. What it doesn’t buy is learning — you still supply that.
Before paying, ask for three things in writing: the verifiable placement rate (not “90% of those who actively searched”), the real background of the instructors, and contact details for two graduates from a year ago. If they dodge any of the three, you have your answer.
The mistakes that kill 90% of attempts
I’ve seen them all, and nearly all are avoidable:
- Spending six weeks choosing a language. No choice is irreversible. Start today with Python.
- Learning by watching, not writing. If your week was 8 hours of video and 1 hour of keyboard, you aren’t learning.
- Jumping to a framework without fundamentals. Django or React on a shaky base builds a house of cards that collapses at the first weird error.
- Pasting AI code you don’t understand. It works today and blocks you forever.
- Studying without building anything. No project, no portfolio; no portfolio, no interview.
- Comparing yourself to people with ten years of experience. Compare yourself to you a month ago. It’s the only comparison carrying useful information.
- Chasing every new technology. Finishing one thing beats starting five.
- Not using Git from the start. You lose a year of evidence of your own progress.
- Waiting until you “feel ready” to apply. You never will. Apply in month 10 with what you have: every interview is free information about what you’re missing.
- Quitting in week 6. That’s the valley. It happens to everyone. Hold on four more weeks.
Frequently asked questions
How long? About 12 months at 10 hours a week to reach a hireable level; the first useful results around month 3.
Which language? Python, unless your specific goal is building web interfaces — then JavaScript.
And AI? Use it as a tutor, never as a generator: write it yourself first, and if you can’t explain a line out loud, delete it.
Where to start today, in 30 minutes
If you’ve read this far, the worst possible outcome is closing the tab and doing nothing. So here’s everything reduced to what you can do right now:
- Install Python 3.14 and VS Code (15 minutes).
- Create
hello.pyand run it (2 minutes). - Write a program that asks you for three expenses and prints the total and the average. Without using AI. It will take longer than you expect, and that effort is the learning (20 minutes).
- Create your GitHub account and push that file (10 minutes).
That’s day 1 of 365. The rest is repeating it.
And one last thing, which is the one that really matters: the unusual thing isn’t taking a while to understand something. The unusual thing is still being there in week 8. Almost everyone who makes a living at this went through the same valley, and the only difference between the ones who crossed it and the ones who didn’t was not stopping.
Just starting out and stuck on something specific? Tell me what error you got and what you’ve tried. And if what you actually need is someone to build or automate something for you while you learn, I do that too.