You can understand a function during a lesson and still stare at an empty repo with no idea what to write. I’ve been there plenty of times.
An exercise tells you what you’re meant to practise. If the lesson is about arrays, the solution probably needs an array. Your own project gives you no such hint. You have to decide what you’re building, how to break it down and which part of JavaScript can get you there.
That jump made the biggest difference to the way I learn. I didn’t stop studying the fundamentals or doing exercises. I started using JavaScript in projects I genuinely wanted to use, and the concepts stopped feeling like separate pieces.
Completing exercises isn’t the same as building
Exercises have a clear purpose. They let you focus on one part of the language without carrying the rest of an application on your back. The trouble starts when you get used to always receiving the brief, the input data and the expected output.
Open a fresh repo and a different set of questions appears:
- What belongs in the first version?
- How should the data be structured?
- What happens when someone does something I didn’t expect?
- What needs to be persisted?
- When is a feature actually done?
- What can wait until later?
Feeling like a worse developer at that point is normal. A real project exposes every decision an exercise usually makes for you.
JavaScript became far more useful to me when I stopped measuring progress by the number of completed lessons and started looking at the problems I could now solve.
ICO Notes started as a completely different project
ICO Notes wasn’t originally a notes app. The first version was a website for displaying exercises from my communication course.
As the course progressed, I found a different problem. There were recorded lessons, weekly live sessions and content from several mentors, but I had nowhere I could browse all of it in a way that worked for me.
So I changed the entire project.
It went from an exercise showcase to an app that organised four programme phases, fourteen weeks of content and each mentor’s lessons. I also wanted to use it from my phone and access it offline.
That change forced me to think before writing code. The hard part wasn’t showing some text after a click. It was making a large amount of information make sense inside a website.
I had to decide how phases, weeks and mentors fitted together, how to move between sections without getting lost and how to keep long pages readable on a small screen. JavaScript was part of the solution, but the useful learning came from connecting the interface, content and behaviour.
I was building it alongside the ICO course itself, my English lessons and my web development master’s. It wasn’t a one-afternoon tutorial build. The content and the app grew together.
Once it was ready, I shared it with the ICO community. It no longer had to work only on my laptop. Other people were going to browse it, install it and use it as a reference. Small bugs suddenly mattered.
A real project doesn’t need to make money
I used to associate real projects with client work. I don’t anymore.
A project is real when it solves a specific need and somebody depends on the outcome. That might be a client, a classmate or you. If the tool is awkward and you stop using it, that’s real feedback even if nobody sent an invoice.
The same thing happened with EmoWords. The idea came from something my English teacher often said: you remember a word more easily when you connect it to one of your own experiences or emotions.
I wanted to turn that idea into an app. That brought up problems I would never have picked from an exercise sheet: storing vocabulary in the browser, playing pronunciation audio, organising several review modes, calculating progress and maintaining a streak.
I wasn’t confident with JavaScript when I started EmoWords. I used AI for support and had to research a lot. The important difference was that I understood the problem and knew how I wanted the app to behave. I could test each part and spot when a technically valid answer didn’t fit the product.
Finding an idea that will actually help you learn
Lists of 100 project ideas can get you moving, but many of them repeat the same calculator, to-do list and weather app. There’s nothing wrong with building those. The issue is that if you don’t care about the app, dropping it becomes very easy as soon as the fun part ends.
I’d start with small bits of friction instead:
- Information you check often but can never find quickly.
- Something you manage manually in notes or a spreadsheet.
- A repetitive task you could simplify.
- A tool you use that doesn’t quite work the way you want.
- An idea you’ve heard that could become something useful.
You don’t need a startup pitch. ICO Notes started because I wanted a better way to browse a course I was already taking. EmoWords started with one sentence from a teacher.
A real need gives you something a generic list can’t: a way to judge your own decisions. You know which features matter because you understand the problem.
Keep the first version small
Once you have the idea, the next trap is trying to build the finished product on day one.
If I’d thought of ICO Notes as four phases, fourteen weeks, every mentor, a PWA and full offline support from the start, I probably wouldn’t have begun. The first version only needed to prove that I could organise part of the content and move through it comfortably.
These three questions help me cut down the scope:
- What’s the one thing somebody needs to be able to do?
- What’s essential for that action to work?
- What can I add later without rebuilding the foundation?
This isn’t only project management. It makes learning easier too. If you’re tackling navigation, persistence, authentication, sync, animation and responsive design at once, you won’t know which problem is actually blocking you.
A small version lets you close the loop: build, test, find a problem and fix it.
Work slightly above your current level
If you already know every part, you’ll practise speed but learn little that’s new. If the entire stack is unfamiliar, you’ll probably end up gluing snippets together without knowing where they break.
I try to mix three things in a project:
- A foundation I already understand.
- Something I’ve studied but still need to practise.
- One new problem that forces me to research.
With ICO Notes, I could already build the visual structure. The challenge was organising a much larger app, adding behaviour and making it installable and available offline.
With EmoWords, I knew the experience I wanted, but I was still learning JavaScript. That made the build harder, but it also forced me to work out what each part was there for.
AI shouldn’t turn you into a spectator
I’ve used AI to write code. Hiding that would make the story cleaner, but less honest.
Asking for help isn’t the problem. We also use docs, Stack Overflow, videos and code from other projects. The problem is handing over the decisions as well, then accepting an implementation you can’t explain.
When I use AI, I try not to give it the entire problem. I’d rather ask for one specific piece, fit it into my code and deliberately break it to check whether I understand its limits.
Before I accept an answer, I try to ask myself:
- Could I explain this code without reopening the original response?
- Do I know which data it changes?
- What happens with an empty or unexpected input?
- Does this approach fit my project, or was it just the first one that worked?
- Could I debug it if it stopped working tomorrow?
I can’t always answer yes to everything. When I can’t, that part is still learning debt. The project may move forward, but I shouldn’t pretend I now understand the concept properly.
Shipping teaches you what localhost can’t
While an app lives only on your machine, you fill in the missing pieces without noticing. You know where to click, what data to enter and which paths to avoid.
Once you share it, that advantage disappears.
With ICO Notes, I had to think about people who didn’t know the structure as well as I did. I also had to be careful because the course content was private. I could share the tool with the community, but I couldn’t expose the material publicly.
Shipping makes you review more than the code:
- Whether people understand what the app is for.
- Whether the navigation makes sense.
- Whether it works away from your own device.
- Whether you’re exposing anything you shouldn’t.
- Whether you can explain what you built and why.
It also turns learning into evidence. Saying you know JavaScript doesn’t reveal much. Showing an app, walking through the problems you hit and admitting what you’d improve gives a much clearer picture of your level.
The process that works for me
I don’t have a perfect framework, but this pattern has repeated across several projects:
- I notice something that’s annoying or missing.
- I define a first version I can realistically finish.
- I build it on top of something I already know.
- I research when I hit a real problem.
- I use the tool and check whether it solves the original need.
- I add features once the foundation works.
- I share it and see what breaks outside my own setup.
- I document the decisions and what I’d do differently now.
I still need theory, exercises and documentation. The difference is that I now tend to arrive with a specific question.
Learning JavaScript through real projects isn’t about skipping the fundamentals or trying to build the next billion-dollar product. It’s about giving each concept a problem to answer instead of studying it as an isolated piece.
If you don’t know what to build, don’t start with the technology. Look at the tool you wish you had, the process that annoys you or the information you can never browse properly. Your next project might be there, along with the next part of JavaScript you need to learn.