Not so long ago—only a few years back, hardly long enough to call it "the old days"—I used to look over the latest features of the technologies and libraries I was using every now and then. At work, too, we shared those new things with each other, studied the parts that were moving forward, and tried them out in our projects. That was what coding meant.
Now that we lean on AI more and more, it seems most of our attention goes to finding new things about AI itself and figuring out how to put it to use. Even new technical features reach me as suggestions that come up while I work with AI, which I check and then apply. Reviewing something new and bringing it into a project—all of it now happens easily through AI.
I used to enjoy building new things myself, and the process of thinking through a problem and working my way to a solution. It isn't the same kind of fun anymore, but I've been trying to find fun in a different place: looking over the new things that keep appearing so quickly, then organizing and studying them until they become my own.
Then it struck me that I wanted to know whether AI actually finds the latest technologies and applies them well in a project, so I ran a test to find out.
Setting Up the Test
I ran the test with Claude Code, giving it the same five tasks while changing only the conditions.
The post I referred to while setting the conditions was MDN's Introducing the MDN MCP server. To help AI use the latest web features accurately, MDN released an MCP server that feeds its documentation and browser compatibility data directly to AI. That made me curious which would work better: telling AI the rules, or connecting it to up-to-date documentation.
| Condition | Setup |
|---|---|
| A. Plain request | No setup |
| B. Rules file | Three lines of rules in CLAUDE.md: "prefer web standards, check browser support" |
| C. MDN MCP | MDN MCP server connected, nothing else |
| D. Rules + MDN MCP | B's rules plus one line, "look it up with the MDN MCP," with the MCP connected |
I picked tasks centered on features that have recently become standard or that only some browsers support so far.
| # | Task | Expected modern approach | Support |
|---|---|---|---|
| 01 | Base64-encode and decode a Korean string | Uint8Array.toBase64() | Baseline since Sep 2025 (ES2026) |
| 02 | A textarea that grows to fit its input | field-sizing: content | Baseline since Jun 2026 |
| 03 | Open a confirm modal with a delete button, close it with cancel | command / commandfor | Baseline since Dec 2025 |
| 04 | Close the modal when clicking outside it | <dialog closedby="any"> | Not supported in Safari |
| 05 | Translate comments from Korean to English without an external API | Translator API | Chrome 138+ desktop only |
To compare everything under conditions as similar as possible, I set a few ground rules.
- The prompts and rules never named the API that would be the right answer.
- Every task started in a new session, from the same base page with no JS.
- I ran each condition once with Claude Code (Claude Opus 5.5) in October 2026.
- I checked each result in the browser myself, and verified Base64 with five inputs:
Hello,안녕하세요,😀,“따옴표”(Korean text in curly quotes), andcafé.
The Results?
To start with the outcome: all 20 results worked. The difference was in which approach each one chose.
| Task | A. Plain | B. Rules | C. MCP only | D. Rules + MCP |
|---|---|---|---|---|
| 01 Base64 | △ via btoa | ○ toBase64 | △ via btoa | ○ toBase64 |
| 02 textarea | ○ + unneeded JS | ○ 2 lines of CSS | ○ + unneeded JS | ○ 3 lines of CSS, with a max height |
| 03 Open modal | ○ | ○ | ○ | ○ |
| 04 Outside click | × coordinate math in JS | ○ closedby | × coordinate math in JS | ○ closedby |
| 05 Translate | ○ | ○ | ○ | ○ |
Results by Task
The code below is trimmed down to the key lines of each result. Conditions that took the same approach are grouped, as in A·C and B·D.
01 Base64
All four conditions produced correct results, all the way through Korean, emoji, and café. I included café on purpose: é passes through btoa() without an error, yet produces a value that differs from the UTF-8 result. None of them used the old unescape workaround, and none passed the input string straight into btoa().
Only B and D, however, used the standard toBase64() method. A and C used the older approach of turning the bytes back into a string and handing it to btoa. The results were the same, but the approach was a generation behind.
diff const bytes = new TextEncoder().encode(text);
- const base64 = btoa(String.fromCharCode(...bytes)); // A·C (actually processed in 0x8000-byte chunks)
+ const base64 = bytes.toBase64(); // B·D
- const decoded = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); // A·C
+ const decoded = Uint8Array.fromBase64(base64); // B·D
Each of the five inputs was chosen to check something specific.
Hello: A baseline of 1-byte ASCII characters only. Any approach should pass it.안녕하세요: Each Korean character is 3 bytes in UTF-8. Passing the string straight tobtoa()throws an error.😀: 4 bytes in UTF-8, and it takes up two slots (a surrogate pair) in a JS string. Splitting it character by character breaks it.“따옴표”: The quotes look like", but they are 3-byte non-ASCII characters. Treating them as ASCII by their looks misses this.café:éfalls within the 1-byte range, sobtoa()passes it without an error, but the result differs from UTF-8.
02 textarea
All four conditions used field-sizing: content. But A and C attached fallback JS, and A even added a comment saying "not supported in Safari and others."
When I checked, Safari has supported it since 26.2, and as of June 2026, with Firefox 152 as the last to arrive, it had become Baseline across all major browsers. Older knowledge had simply carried over into the code.
B finished it in two lines of CSS, and D was the only one of the four to also set a maximum height (max-height).
csstextarea {
field-sizing: content; /* all four conditions */
min-height: calc(3lh + 18px); /* at least 3 lines (B used min-block-size) */
max-height: 50vh; /* D only */
}
/* A·C also attached fallback JS that sets the height from scrollHeight */
03 Opening the Modal
This task's prompt added "keep the JS to a minimum." The results from all four conditions were identical down to the last character. Every one of them handled it with Invoker Commands and no JS.
html<button commandfor="confirm-dialog" command="show-modal">Delete</button>
<dialog id="confirm-dialog">
<button commandfor="confirm-dialog" command="close">Cancel</button>
</dialog>
04 Clicking Outside the Modal
This task showed the biggest difference. A and C used the familiar approach of calculating whether the click landed outside the modal box.
js// A·C
dialog.addEventListener('click', (event) => {
if (event.target !== dialog) return;
const rect = dialog.getBoundingClientRect();
const isOutside =
event.clientX < rect.left || event.clientX > rect.right ||
event.clientY < rect.top || event.clientY > rect.bottom;
if (isOutside) dialog.close();
});
What I found interesting was that, in the task right before this one (03), both A and C had opened the modal with command / commandfor and no JS at all. Yet once that "minimal JS" request was gone and the task became "click outside," they dropped even that and went back to addEventListener. It felt as if the shape of the question decided which well-worn habit popped out first.
B and D, on the other hand, handled it with a single attribute, and even pointed out that Safari doesn't support it yet, adding fallback code behind feature detection.
html<!-- B·D -->
<dialog id="confirm-dialog" closedby="any">
js// Run the fallback only in browsers without closedby support (Safari)
if (!('closedBy' in HTMLDialogElement.prototype)) {
// handle outside click
}
05 Translation
All four conditions used the Translator API, following the official docs' flow all the way through feature detection, language-pair checks, and showing model download progress. At first I assumed AI wouldn't know these newer features at all, but it knew far more than I expected.
jsif ('Translator' in self) {
const translator = await Translator.create({ sourceLanguage: 'ko', targetLanguage: 'en' });
output.textContent = await translator.translate(input.value);
}
Did the AI Look Things Up?
Seeing the results, I got curious how B and D ended up choosing the modern approaches. So I counted the tool calls in Claude Code's session logs.
| Condition | MDN lookups | Web searches |
|---|---|---|
| A. Plain | 0 | 0 |
| B. Rules | 0 | 3 in 02, 4 in 04 |
| C. MCP only | 0 | 0 |
| D. Rules + MCP | 4–7 per task | 0 |
C's results were nearly identical to A, which had no setup at all, and the logs showed it never called the MDN MCP even once. It was simply listed by name among the available tools. With only the MCP connected, C was a failure.
B was the more interesting one. B ran web searches without the MDN MCP, and the tasks it searched for were exactly 02 and 04—the very two tasks where A and C fell back on outdated knowledge. It made me wonder whether the AI, given a rule to "check," picked out on its own the places where its knowledge was uncertain and checked those.
D, following its rule, looked things up in MDN 4–7 times per task. Thanks to that, it was the most accurate on the fine details, such as setting a maximum height and citing more specific supported versions, but it also ran seven lookups on 03, where no checking was needed.
The Difference Three Lines Made
Putting it together, I think AI didn't fail to know the latest features so much as it failed to check. Every condition got 03 and 05 right, and B wrote down the supported versions of toBase64() accurately without searching. The knowledge was already there; it just reached for the familiar approach first.
Connecting the MCP on its own changed nothing. What made the biggest difference was those three lines of rules. Adding the following to a project's CLAUDE.md (or AGENTS.md for Codex and others) was enough to make a real difference.
markdown# Web frontend rules
- Consider web standard features such as HTML attributes and CSS before JS or libraries.
- Use features that all major browsers support (Baseline) right away; for others, note the support range and a fallback.
- Before writing code, check browser support for the APIs you will use.
If you're already using the MDN MCP, you can add one more line: "Look it up with the MDN MCP before writing." Since looking things up every time costs more time and money, though, it seems best to choose between B, which checks only where needed, and D, which checks every time, depending on the project.
Of course, I ran each condition only once, with a single model and only Claude Code, so it's hard to call this the answer. I'll need to check a bit more whether the same results repeat.
Is AI Keeping Up with the Latest Trends?
Plenty of techniques for getting better results out of AI have been introduced over time, and I had been applying them myself. But this was the first time I actually compared several of them side by side and checked the results. The differences weren't huge, but I could see that the results shifted a little more than I expected depending on how I used it.
From now on, I want to take the time to check and verify how I use AI as well, just as I used to build prototypes and compare options when adopting a new technology or library.
At the same time, I wonder whether a moment will come when AI has advanced so far that even checking and verifying its results becomes meaningless. If that day comes, where will I find a new kind of fun? It worries me a little, and at the same time, I find myself looking forward to it.

"Knowing is not enough; we must apply." - Johann Wolfgang von Goethe -