HAP studying on his laptop

Station 2: Finding Things

How JavaScript locates elements in the DOM tree

After Station 1, I understood that the DOM was a living tree of objects. But understanding the tree exists and actually finding something IN it are two different problems.

I wanted to change the robot's name on my Robot ID Card. The card had a <span> with id='robot-name' holding the text 'HAP-7000'. I knew document was my way in. But document is the WHOLE tree. I needed to reach one specific branch.

So I asked my AI coding agent to help me grab that element. What happened next taught me two things at once: how JavaScript finds elements in the DOM, and why I need to question AI-generated code even when it works. 🟠

Quick Reference

How I Learned to Push Back and Why →

I Needed to Find the Robot's Name

I had my Robot ID Card rendered in the browser. The DOM tree was right there in DevTools — I could see every node, every branch. But seeing the tree and reaching into it to grab a specific element? Those felt like completely different skills.

I knew the <span id="robot-name"> element held the text "HAP-7000." I knew document was the root of the tree. What I did not know was the syntax to connect those two ideas.

So I did what felt natural — I asked my AI coding agent: "How do I grab the element with id robot-name?"

The AI's Answer Worked... But Grace Said One Word

The AI agent gave me this:

What the AI generated:
const robotName = document.getElementById('robot-name');

I pasted it in, ran it, and it worked. The element came back. I was ready to move on.

Then Grace Hopper appeared in the sidebar. She looked at the code and said one word:

Grace Hopper:

"Outdated."

One word. No explanation. That is how Grace works — she tells you WHAT to notice. The rest is my job. She does not hold your hand. She points, and then she waits to see if you are curious enough to follow.

I almost ignored her. The code worked. Why would I question working code?

I Decided to Push Back

Instead of asking the AI to "fix it," I decided to understand WHY Grace flagged it. I connected the MDN MCP server and asked a chain of six questions. Each answer led to the next question:

Question 1

"What is getElementById?" — It is a method from DOM Level 1, the original DOM specification from the late 1990s.

Question 2

"When was it introduced?" — DOM Level 1, standardized in 1998. That is nearly three decades ago.

Question 3

"What is the modern replacement?"querySelector(), part of the Selectors API.

Question 4

"How does querySelector differ?" — It uses any CSS selector, not only IDs. The same selector syntax from my stylesheets works in JavaScript.

Question 5

"Can querySelector do everything getElementById does?" — Yes, and more. It handles classes, attributes, pseudo-selectors, and complex combinators.

Question 6

"Performance differences?" — Technically getElementById is faster in microbenchmarks, but the difference is irrelevant in any real application.

I kept going until I felt understanding click. One question would not have been enough. It took the full chain — each answer revealing the next question I needed to ask.

What I Understood After Pushing Back

getElementById is a 1990s tool that only finds elements by their ID attribute. querySelector uses CSS selectors — the same syntax I already knew from writing stylesheets — and can find elements by ID, class, tag, attribute, or any combination.

The legacy way (getElementById):
const robotName = document.getElementById('robot-name');
The modern way (querySelector):
const robotName = document.querySelector('#robot-name');

Notice the # — it is the same CSS selector syntax used in stylesheets. The # means "find by ID."

I always have to remember that the AI Agent makes mistakes and that I own this code. When I don't know myself, I push back and find a way to learn before I proceed.

Grace Validated What I'd Earned

After I rewrote the code with querySelector and explained my reasoning in a comment, Grace appeared again:

Grace Hopper:

"That is the correct instinct, HAP."

She validated the process, not the answer. She did not say "good code." She said "correct instinct." The instinct to stop, question, and understand before proceeding — that is what mattered to her.

I named the pattern I had followed: notice → stop → interrogate → understand → codify.

I Edited AGENTS.md

Understanding something is one thing. Making sure the AI does not repeat the mistake is another. I opened my project's AGENTS.md file — the file that gives instructions to my AI coding agent — and added two rules:

Rules I added to AGENTS.md:
## DOM API Rules
- Use querySelector/querySelectorAll exclusively. Never use getElementById,
  getElementsByClassName, or getElementsByTagName.
- Before generating DOM API code, consult the MDN MCP server to verify
  the recommended modern approach.

This is the "codify" step — the last piece of the pattern. When I learn something important, I write it down where it will have an effect. Not in a notebook I will forget about, but in the file that controls how the AI generates code for this project.

The full pattern: notice → stop → interrogate → understand → codify.

HAP surrounded by tangled code with an 'oops' expression

HAP's Confession:

  • I almost moved on with the working getElementById code. Working code felt like finished code. It took Grace's single word to make me pause.
  • My first instinct was to ask the AI to "fix it" instead of learning WHY it needed fixing. That would have given me a better line of code but zero understanding.
  • I almost stopped after one question. "What is getElementById?" felt like enough. But the six-question chain is what gave me real understanding — each answer unlocked the next question.

Finding Things Quick Reference

1

querySelector Replaces getElementById

document.querySelector('#robot-name') does everything document.getElementById('robot-name') does, plus it works with any CSS selector — classes, attributes, combinators, and more.

2

CSS Selectors Are the Key

The string inside querySelector() is a CSS selector — the same syntax from stylesheets. #id, .class, tag, [attribute] all work. One syntax for CSS and JavaScript.

3

Working Code Does Not Equal Good Code

Code that runs without errors can still be outdated, fragile, or hard to maintain. The fact that it works is necessary but not sufficient.

4

Push Back on AI-Generated Code

When something feels off — or when someone like Grace flags it — do not ask the AI to fix it. Ask questions until I understand the problem myself. Then decide what to do.

5

Codify What I Learn

Understanding is fragile if it stays in my head. Writing rules in AGENTS.md means the AI will follow what I learned on every future generation. That is the codify step.

What's Next

I felt confident. I had querySelector. I had a pattern for pushing back. I was ready to find any element on the page.

So I tried document.querySelector('robot-name') — and nothing happened. No error. No element. It returned null.

Knowing the method and knowing how to write selectors are two different skills. In Station 3, I learned exactly how CSS selectors work inside querySelector — and why that missing # made all the difference. 🟠

Quick Reference

How I Learned to Push Back and Why →