Read this when you want to quit

When In Doubt

You wrote this page for yourself. These are the questions you've already asked and the answers that convinced you. Come back here every time you want to switch courses, start a tutorial, or convince yourself you're not ready.


Your history — and what it actually means

You finished CS50x. You almost finished CS50W but ditched it after reading a Hacker News thread calling it a bad course. You completed The Odin Project's Foundations. You finished Full Stack Open Parts 0–7 — the entire core curriculum. You went back to The Odin Project's JavaScript path and got all the way to the Battleship project. Then you started wondering if you should do something else.

Read that again. You have completed more coursework than most people who land junior developer jobs. The problem was never your knowledge. The problem is that every time you finish something, instead of building with what you learned, you look for the next course to fill a gap that doesn't exist.

CS50x gave you fundamentals — algorithms, memory, how computers work. CS50W gave you web basics. TOP Foundations gave you HTML, CSS, and JavaScript basics. FSO 0–7 gave you the entire modern stack: React, Node, Express, MongoDB, Redux, React Query, testing, deployment. TOP's JavaScript path reinforced your JS fundamentals and gave you OOP practice.

You're not behind. You're over-prepared and under-practiced.


"I feel like I lack fundamentals"

You don't. Here's what you actually know from FSO alone: React (components, hooks, state, effects, context, refs), Node.js and Express (routing, middleware, error handling, REST API design), MongoDB and Mongoose (schemas, models, queries, population, validation), authentication (JWT, bcrypt, login flows), state management (Redux Toolkit, React Query, useReducer, useContext), testing (Vitest, SuperTest, Playwright, React Testing Library), deployment, React Router, Material UI, styled-components, ESLint, Webpack basics.

That's not "lacking fundamentals." That's a professional stack. The reason it feels abstract is because you learned it by following instructions. The moment you use these tools to solve a problem you defined yourself, the abstraction evaporates. It's like knowing how to drive in a parking lot — you know the mechanics, you just haven't been on the highway yet.

The fundamentals you think you're missing will reveal themselves the moment you need them. You'll be building the invoice system and think "wait, how should I structure this Mongoose schema?" — and you'll re-read that one section of FSO Part 3 and it'll click instantly because now you have context. That's 10x faster than re-reading the whole course preventatively.


"Should I finish The Odin Project?"

No. You're on the Battleship project. What's left after that? A few more Node/Express projects that teach you things you already know from FSO — routing, MVC, databases. Then TOP uses EJS templates for server-rendered HTML. You know React. You're never going to use EJS professionally. The remaining TOP projects are specified for you — every student builds the same blog, the same members-only clubhouse. Interviewers have seen hundreds of identical TOP portfolios.

TOP's remaining content teaches you things you already know using tools you won't use. The only thing it gives you that these projects don't is hand-holding. And that's exactly what you need to stop relying on.

If finishing TOP takes 3–4 months and you still need to build real projects afterward, you'll be in the exact same position you're in now — just 3–4 months closer to internship applications with nothing new to show for it.


"What if FSO just taught me tools? It all feels so abstracted"

Every tool is an abstraction over something lower. Mongoose abstracts MongoDB. Express abstracts Node's http module. React abstracts DOM manipulation. The Odin Project doesn't fix this — it shows you a slightly different level of abstraction with different tools. You'd still be "just learning tools."

The abstraction anxiety goes away when you push a tool until it breaks. When Mongoose's .populate() is too slow for your dashboard and you drop into raw aggregation, you'll learn what Mongoose was hiding. When React Query's cache invalidation doesn't work how you expect, you'll dig into how caching actually works. This only happens in real projects. No course will push you there because courses are designed to avoid those edges.


"I ditched CS50W because a Hacker News thread said it was bad"

A Hacker News thread. You threw away months of work because strangers on the internet had opinions. Those strangers don't know your situation. They don't know what you've completed. They don't know your goals. Half of them are senior engineers who think every course is bad because they learned by reading man pages in 2003.

CS50W wasn't a waste. It gave you exposure to web fundamentals before you did FSO. The projects you built were practice. The fact that some commenter thought the course wasn't rigorous enough doesn't erase what you learned from it.

This is a pattern: you do the work, then let external validation (or the lack of it) convince you the work was worthless. Stop reading course reviews. You've already done the courses. The only review that matters now is: "can I build things with what I know?" The answer is yes. You just haven't proven it to yourself yet.


"MERN stack is saturated. Should I learn .NET / another stack?"

Switching to .NET would restart the tutorial loop in a new language. You'd spend months learning C#, ASP.NET, Entity Framework — and be right back at the "I know the tools but haven't built anything real" stage. The stack doesn't matter for internships. What matters is demonstrating that you can build software. A great MERN project beats a mediocre .NET tutorial project every time.


"Should I skim all of FSO to refresh?"

No. Skimming 7 parts is procrastination disguised as preparation. You'll spend a week "reviewing" and retain 10% because there's no context for it to stick. When you're mid-project trying to remember JWT middleware setup, you'll re-read that one section of Part 4 and it'll click in 15 minutes because you need it right now. Bookmark the FSO table of contents. Use it as a reference, not a textbook.


"I'm missing things — I didn't even know express-validator existed"

You'll discover express-validator (and dozens of other libraries) the moment you need input validation and Google "how to validate request body express." That's how every working developer learns new packages — by needing them, not by having a course introduce them.

No course covers everything. If you'd done a different course, you'd know Joi or Zod instead and be worrying about not knowing express-validator. The packages you don't know about yet are not gaps in your education. They're Tuesday afternoons at work.


"How do I know if my code is bad?"

Your tests catch bugs you'd never find manually. Write SuperTest cases for edge cases — zero quantity, negative discounts, tax on zero subtotals. The act of asking "what weird input could break this" teaches you to write better code.

After finishing a feature, wait a day and re-read your own code. You'll immediately spot functions doing three things instead of one, 200-line components that should be split, and queries running inside loops that could be single aggregations.

ESLint catches an entire category of issues automatically — unused variables, missing useEffect dependencies, inconsistent returns.

Deploy and use your own app. Click through every flow as the actual user. "What if I click Submit twice?" "What if the server is down?" "What if I delete a client with unpaid invoices?" Every question reveals a gap.

After you've built something, search GitHub for similar projects. Look at how others structured theirs. You'll find patterns you missed — and you'll also find that your code is better than a lot of what's out there.


"What about the 100-line function that could be a one-liner?"

You learn this by writing the 100-line version first. The first time you write 15 lines to transform an array and then discover .reduce() does it in 3, you'll remember reduce forever. The first time you write 40 lines of manual validation and then discover Zod, you'll understand why validation libraries exist.

Write it the long way. Feel the pain. Discover the short way. Understand why the short way exists. You cannot shortcut this process. Every senior developer wrote terrible code for years before writing clean code. The difference is they wrote code.


Why you keep wanting to course hop

It's not about the course. It's about control. In a course, the difficulty is managed for you. Lessons are sequenced. Exercises are scoped. If you fail, it's the course's fault for not explaining well enough. When you build on your own, the difficulty is unmanaged. You'll hit a wall and have no idea if it's a 10-minute problem or a 3-day problem. There's no "next lesson" button. There's just you and the blank editor.

Course-hopping is a coping mechanism for the fear of unstructured difficulty. Every time you hit a point where the learning gets uncomfortable and self-directed, your brain says "I must be missing something — let me find a better course that covers this." But the discomfort isn't a signal that you're in the wrong place. It's a signal that you're exactly where growth happens.

The FOMO is an illusion. You're afraid that TOP teaches something FSO doesn't, or that CS50W had something you needed, or that there's a perfect curriculum out there that covers everything. There isn't. Every course has gaps. Every developer has gaps. The developers who get hired are the ones who build things despite the gaps, and fill them as they go.


What to do right now

Close this page. Open your terminal. Run npm create vite@latest. Name the project "invoice-system" or whatever you picked. Initialize the Express backend. Create a Mongoose schema for a Client. Build the POST /api/clients endpoint. Test it with a REST client. You'll have your first working feature in under an hour.

The first commit is the hardest. Everything after that is just one feature at a time.


Remind yourself