Sign in with Google

How to Take Notes While Learning to Code

Three note types, kept separate, that you will actually reread instead of a vault you never open.

beginner9 min read
learning-metanote-takingprogrammingstudy-skills

You followed a tutorial, typed everything the instructor typed, and filled twelve pages with code you no longer understand. A week later you hit the same error you already solved and cannot find where you wrote down the fix. The problem is not that you took bad notes — it is that transcribing code is not note-taking. It trains your hands to reproduce keystrokes while leaving nothing in your head, and it produces a document with no question in it, which is a document you will never have a reason to open again.
iWho this is for
Anyone working through a course, a book, or a first project who is writing things down and suspecting it is not helping. You need a plain text editor and about fifteen minutes to set up three files. No app purchase required.
Notes work when they force you to produce something from memory. That is the finding behind what psychologists call the testing effect, or retrieval practice: in Henry Roediger and Jeffrey Karpicke's experiments, learners who were tested on material retained substantially more of it later than learners who reread it for the same amount of time — even though the rereaders felt more confident. Copying code down is closer to rereading than to testing. You are transcribing, not retrieving, so nothing is being strengthened.
Programming makes this worse in a specific way. Code is procedural — the value is in being able to produce it in a new situation, not recognize it on a page. A page of copied code looks like understanding and is not, which is why people who take beautiful tutorial notes still stall the moment they open an empty file. The fix is to write notes that are claims and questions in your own words, and to keep three kinds of them apart so each one has a clear job.
Almost everything worth writing down while learning to code is one of three things, and mixing them in one file is why nobody rereads their notes. Keep three separate destinations from day one.

Three files, three jobs

  1. 1The working log — a running, dated, disposable record of what you tried, what broke, and what fixed it. Append-only. Never organized. Written while you work.
  2. 2Concept notes — one idea per note, stated as a claim in your own words, with the smallest runnable example that proves it. Written after the thing works.
  3. 3The snippet library — patterns you know you will reuse, each stored with the context that tells you when it applies. Small, curated, ruthlessly pruned.
!The rule that makes all three work
Never copy code you have not run. If a snippet is in your notes, it executed on your machine and you watched it do the thing. Unrun code is a rumor, and a notes file full of rumors is worse than no notes at all.
The working log is one file per project, appended to as you go. It is not meant to be pretty and it is not meant to be permanent — it is a scratch buffer for your short-term memory so you stop re-deriving the same dead ends. Its highest-value entries are errors, because the same error will absolutely find you again.
markdown
## 2026-03-14

- Goal: get the /users endpoint returning JSON

- ERROR: TypeError: Object of type UUID is not JSON serializable
  - Doing: returning the SQLAlchemy row straight from the route
  - Cause: json.dumps has no idea what a UUID is; it only handles
    str/int/float/bool/list/dict/None
  - Fix: str(row.id) at the boundary. Real fix: a response model that
    declares id as a string.

- Tried and abandoned: custom JSONEncoder subclass. Worked, but every
  new type needs another branch. Not worth it here.

- Open question: does the framework already do this conversion for me?
  -> check tomorrow

A working log entry — errors get all four fields, always

The four fields on an error entry — the exact message, what you were doing, the cause, and the fix — are the highest-return notes you can write, and the exact message matters most. Paste it verbatim, including the type name and the line, because six weeks from now you will search your own notes for that string rather than the open web, and a paraphrase will not match.
A concept note is one idea, titled as a claim, in language you would use out loud. Write it after you have the thing working, never while you are still fighting it. This is deliberate: while you are stuck you do not yet know which detail was load-bearing, so a note written mid-struggle records your confusion rather than the concept. Writing it afterwards also forces you to reconstruct the idea from memory, which is exactly the retrieval that makes it stick — and having to phrase it yourself is the generation effect doing free work for you.
markdown
# A Python list is a reference, so copying it with = does not copy it

Assigning a list to a second name gives you two names for one object.
Mutating through either name changes the same underlying list.

    a = [1, 2]
    b = a
    b.append(3)
    print(a)        # [1, 2, 3]  -- a changed too

    c = a[:]        # or list(a)
    c.append(4)
    print(a)        # [1, 2, 3]  -- a did not change

Why I care: this is what broke the grid in the tic-tac-toe project.
[[0]*3]*3 makes three names for ONE row.

Still fuzzy: how deep does a[:] copy go if the list holds dicts?
(Answer: one level. Nested objects are still shared -> copy.deepcopy.)

A concept note — one claim, one minimal example, one honest gap

The title test
If a note's title is a noun phrase like Python lists, it is a folder pretending to be a note. Retitle it as a sentence that could be true or false. A claim can be checked, argued with, and recalled; a topic can only be scrolled past.
The snippet library holds the handful of patterns you keep needing — reading a file safely, a project's argument-parsing boilerplate, the exact incantation for a database session. Each snippet gets one line above it saying when to use it and one line saying what it assumes. Without that context you end up pasting a pattern into a situation it was never right for, which is a slower failure than looking it up again.

Deciding where notes live

  1. 1Working log: in the project repository, as a plain LOG.md at the root. It is about this codebase, it should travel with it, and it should show up in your diffs.
  2. 2Snippets: also in the project when they are project-specific; in your editor's snippet feature or a single shared file when they are language-level.
  3. 3Concept notes: outside any one project, in one flat folder of plain Markdown files. Concepts outlive repositories.
  4. 4Honest recommendation: start with a plain folder of .md files and your editor. Move to a dedicated notes app only once you have fifty notes and a real complaint about finding them.
Notes you never revisit are a diary. The habit that converts the pile into knowledge is small: ten minutes at the end of the week, reading only this week's log. You are looking for entries that stopped being situational and became general — those get promoted into concept notes, and the log entry can then be forgotten with a clear conscience.

The ten-minute Friday pass

  1. 1Read this week's log top to bottom. Do not edit it, just read.
  2. 2Mark any entry you would want to know again in three months.
  3. 3Promote each marked entry into one concept note, written from memory first and then corrected against the log.
  4. 4Answer or delete every open question you left. An unanswered question from three weeks ago is noise.
  5. 5Delete one thing. Usually a snippet you never used. The library stays useful by staying small.
There is one category this system deliberately does not handle: raw syntax you want in your fingers, like a language's string-formatting spelling or the flags of a command you use weekly. Notes are the wrong tool for that, because you do not want to look it up faster — you want to not look it up. That is what spaced repetition is for, and it pairs cleanly with this: concept notes for understanding, flashcards for recall.

Symptom, cause, fix

  1. 1You have 400 notes and still cannot answer a basic question without searching the web. Your notes are transcripts, not claims. Pick ten notes, retitle each as a sentence, and delete anything that survives no rewrite.
  2. 2You stop taking notes after three days. You were writing during the hard part, which competes with the work. Log while working (one line, ugly), write concept notes after.
  3. 3The same error keeps costing you an hour. You wrote the fix but not the exact message, so search never finds it. Paste error text verbatim, always.
  4. 4Notes feel like a chore with no payoff. There is no review step, so nothing you write is ever read. Add the Friday pass before adding anything else.
  5. 5You copied a snippet and it broke in a new project. It was stored without its assumptions. Add the when-to-use and what-it-assumes lines to every snippet.
  6. 6You cannot find a note you know you wrote. Your folder structure is doing the work search should do. Flatten the folders and title notes as full sentences, which makes them searchable in plain language.
The system above is deliberately tool-agnostic, and plain files carry you a long way. When the flat folder starts to strain, How to Use Obsidian for Note-Taking covers the linking and search that make a few hundred concept notes navigable, and How to Build a Second Brain covers the wider capture-and-review method this borrows from. Since your working log belongs in the repository, How to Use Git is the other half of keeping it alongside the code it describes. And if you want the study side handled properly rather than assembled from habits — session design, review scheduling, what to memorize versus what to practice — the Learning Mastery roadmap sequences it in the order the pieces actually build on each other.