This is part of a series on the modern web stack, written from a WordPress developer’s seat for people who’ve built on the web for years and still hit stack terms they can’t define. The goal is literacy, enough that you can read any stack list and know what each piece does. The opening post explains why the stack looks so foreign.
Each post has a 10-15 minute audio companion, generated with NotebookLM, for the gym or the commute.
The first time I opened a Next.js codebase I closed it again within ten minutes. The JavaScript wasn’t the hard part. I had no idea what most of the files were for.
A node_modules folder with what looked like 40,000 directories inside. A package.json with strange version syntax. A tsconfig.json I couldn’t parse. A vite.config.ts doing things to imports. Files ending in .tsx that looked like HTML had crawled inside JavaScript and died there.
I’ve been writing PHP since the early WordPress days. I know what a composer.json is, I know require_once, and I know vendor/. None of that knowledge transferred. Modern JavaScript looks like PHP from a parallel universe where every decision went the other way.
What follows is the cheat sheet I needed: what modern JavaScript is, what TypeScript adds, and how the toolchain maps onto the PHP world you already know.
Three things are going on, and they’re easy to confuse.
JavaScript the language
This is what you write. The JavaScript that runs in browsers today is far more capable than the jQuery-era version you remember. It has modules, async functions, arrow syntax, destructuring, optional chaining and classes that work, and they show up on nearly every line of a modern codebase.
TypeScript, the type layer
TypeScript is JavaScript with a type system on top. The code looks almost identical, plus type annotations. A separate tool strips the types and compiles it to plain JavaScript before it runs, so the runtime never sees them.
The toolchain around them
Everything else: the package manager that pulls in dependencies, the bundler that combines your code into shippable assets, the runtime that executes server-side code, and the config files that glue it together.
You can write modern JavaScript without understanding any of this. You can’t read a Next.js codebase without all of it, so here’s each piece.
Modern JavaScript Is a Different Language
If your last serious encounter with JavaScript was jQuery selectors and $.ajax, brace yourself. The language grew up. These patterns appear constantly:
// Imports and exports: like require_once, but they declare what's actually used
import { useState, useEffect } from 'react';
export function MyComponent() { ... }
// Arrow functions: like PHP's short closures, but they're everywhere
const double = x => x * 2;
// Destructuring: pulling values out of objects or arrays
const { name, email } = user;
const [first, second] = items;
// Async/await: the cure for callback hell
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
// Optional chaining and nullish coalescing
const city = user?.address?.city ?? 'Unknown';
None of this is exotic, all of it ships in production today, and you’ll see it within the first ten lines of any modern codebase you open.
TypeScript and PHP Type Hints
PHP 7 and 8 gave you type hints. They mostly work: declare that a function expects an integer, and PHP throws at runtime if you pass a string.
TypeScript does the same for JavaScript with two big differences. The checking happens at build time, before the code ever runs. And the type system is far more expressive than PHP’s. You can describe the shape of an object, arrays of specific types, functions whose return types depend on their arguments, and unions of several types in one slot.
type User = {
id: number;
email: string;
role: 'admin' | 'editor' | 'subscriber';
posts?: Post[]; // ? means optional
};
function getUserName(user: User): string {
return user.email.split('@')[0];
}
In 2026 almost every serious modern web project uses TypeScript by default. A team that doesn’t will be migrating within a year, so treat TS as the language rather than an option.
The Toolchain and Its Config Files
Here’s the rough mapping a PHP developer can hold in their head:
| Modern JS | PHP equivalent |
|---|---|
package.json |
composer.json |
npm install / pnpm install |
composer install |
node_modules/ |
vendor/ |
package-lock.json / pnpm-lock.yaml |
composer.lock |
| Node.js (or Bun, Deno) runtime | The PHP interpreter |
| A bundler (Vite, Webpack, Turbopack) | No real PHP equivalent |
TypeScript compiler (tsc) |
Roughly PHP’s optional static analyzers (Psalm, PHPStan), but enforced |
The bundler row deserves a pause. PHP files run as you wrote them. JavaScript for the browser has to be packaged: many small source files combined, dead code removed, modern syntax compiled down to what older browsers understand, assets fingerprinted for caching. That’s the bundler’s job. Vite is the modern default, Webpack is the old guard, and Turbopack is the next-generation tool from the Next.js team. Frameworks handle the config, so you rarely touch any of them by hand.
The WordPress Analogue
npm is to JavaScript what Composer is to PHP.
package.jsonis yourcomposer.json, andnode_modules/is yourvendor/. TypeScript is what PHP type hints would look like if Rasmus Lerdorf had been a Haskell programmer.The bundler is the one piece with no counterpart. WordPress and PHP don’t have one because they don’t need one. The browser can’t execute raw modern JavaScript spread across hundreds of files, so a bundler stitches it together before deployment. Accept that one extra step and everything else is a better-tooled version of what Composer already gave you.
The Toolchain, Row by Row
This is the lay of the land for 2026. You don’t need to learn each tool in depth. You need to know which row each one sits on, so when someone says “we use Bun and Vite” you can place both.
| Layer | What it does | Default in 2026 | Other options |
|---|---|---|---|
| Runtime | Executes server-side JS | Node.js | Bun, Deno |
| Package manager | Installs and locks dependencies | pnpm or npm | yarn, Bun |
| Bundler | Packages JS for the browser | Vite or Turbopack | Webpack (legacy), esbuild, Rollup |
| Type system | Static type checking | TypeScript | Plain JS with JSDoc types (rare) |
| Linter | Catches errors before runtime | ESLint | Biome (newer, faster) |
| Formatter | Auto-formats code | Prettier | Biome |
| Test runner | Runs your tests | Vitest | Jest (legacy), Playwright (browser tests) |
With this table, a job ad or a repo README full of these names stops being noise.
I hold a few opinions here. Use pnpm over npm: it’s faster, uses disk space more sensibly, and almost every modern project defaults to it now. TypeScript is the language, and plain JavaScript is the exception. Bun is interesting but not yet the safe default for production work, and Node.js is still where the boring infrastructure lives.
What This Changes for WordPress People
Three practical wins once the JavaScript mental model is in place.
Reading code stops being scary. The reason a Next.js repo felt impenetrable wasn’t React, the Drizzle queries or the deploy pipeline. It was the JavaScript syntax. Once you can parse arrow functions, destructuring, async/await and ES modules at a glance, half the code in any modern project becomes legible. The wiring post later in the series builds on exactly that.
You can also evaluate AI-generated code. Ask an agent to “add Supabase auth to my Next.js app” and it’ll produce a hundred lines of TypeScript across five files. Without TypeScript fluency you can’t tell whether the result is competent or garbage. Modern stack literacy starts here, and everything else builds on it.
And you start to see PHP’s design choices differently. JavaScript spent fifteen years catching up to a particular idea of what a programming language should be, and it overshot in places. PHP 8 got there too. Once you can read both, you can pick the right tool for each job without religion, which is a small superpower in client work.
Five Gotchas That Bite PHP People
=== instead of ==
JavaScript’s loose equality (==) does type coercion in strange ways: 0 == '' is true, and so is null == undefined. Use === everywhere unless you have a specific reason not to. Modern linters flag it for you.
this is weird
What this refers to inside a function depends on how the function was called, not where it was written. Arrow functions inherit this from the surrounding scope, which is usually what you want. Regular functions don’t, which is why people fall in love with arrow functions.
null and undefined are different
Almost no other language makes this distinction. null means explicitly empty, and undefined means nobody has assigned anything. In practice you mostly handle them together with ?. and ??, but the difference bites when you start using third-party APIs.
Everything is async eventually
Anything involving the network, the filesystem or a database returns a Promise. You handle Promises with await inside an async function, or with .then(). Forget that and you get functions returning Promise<unknown> instead of the data you wanted.
Hot reloading changes debugging
When you save a file in modern development, the browser updates in place without reloading. That’s wonderful when it works and confusing when it doesn’t. State sticks around, and old code is sometimes cached. When something feels haunted, a hard reload usually fixes it.
From Recognizing JS to Writing It
To internalize modern JavaScript rather than just recognize it, a few resources are worth your time.
YouTube, for the gym or commute
- “Modern JavaScript Tutorial” by JavaScript Mastery (about 3 hours, watchable in pieces). It covers the modern syntax features in one place, with examples that map nicely to other languages.
- “TypeScript in 100 Seconds” by Fireship for orientation, then “TypeScript Tutorial” by The Net Ninja as the longer playlist if it sticks.
Official docs worth bookmarking
- MDN’s JavaScript guide is the canonical reference. Skim the “Modern JavaScript” sections and treat the rest as on-demand lookup.
- The TypeScript Handbook: start with the “Everyday Types” page. Most production TS uses maybe 20 percent of the language, and that page covers it.
- Total TypeScript by Matt Pocock. The free tier takes you from beginner to competent, and the paid tier is where you’d go if TS becomes a daily tool.
The next post moves from language to framework: React, in WordPress terms, where components turn out to be template parts with a JavaScript brain. If Next.js itself is what you’re after, Next.js, the WordPress of React covers it.

Leave a Reply