HTTP/2 200
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
server: cloudflare
cf-ray: 892349823498234-SJC
cache-control: max-age=0, no-cache, no-store, must-revalidate
x-frame-options: DENY
x-xss-protection: 1; mode=block
content-security-policy: default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’ https://cdn.segment.com https://www.google-analytics.com; style-src ‘self’ ‘unsafe-inline’ https://fonts.googleapis.com;
set-cookie: _session_id=89234jksdf89234; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT; secure; HttpOnly; SameSite=Lax
strict-transport-security: max-age=31536000; includeSubDomains; preload
x-content-type-options: nosniff
content-length: 842903
Look at that content-length. Eight hundred and forty-two kilobytes. For a landing page. That isn’t the assets, mind you. That isn’t the high-resolution hero image of a diverse group of people staring at a whiteboard in a glass-walled office. That is the html document itself. A single text file. In 1994, I could fit the entire documentation for the CERN httpd server on a 1.44MB floppy disk with room to spare for a few MIDI files. Today, a developer who wasn’t even born when IE4 launched thinks it’s acceptable to ship nearly a megabyte of angle brackets and serialized JSON state just to render a “Sign Up” button.
The web is rotting. It’s a slow, agonizing necrosis of the Document Object Model, driven by people who treat the browser like a garbage disposal for their over-engineered JavaScript abstractions. We’ve traded the elegance of RFC 1866 for a bloated, “Living Standard” nightmare that changes every time a browser vendor wants to push a new proprietary API.
Table of Contents
THE INITIAL INCISION: DISSECTING THE PAYLOAD
Let’s lay them out on the cold steel table. On the left, a standard index.html from 1996, authored in a text editor that didn’t have “dark mode” because we worked in the dark anyway. On the right, a 2024 “Hello World” generated by a modern meta-framework.
1996 Index (214 bytes):
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>The Archive</title></head>
<body>
<h1>Welcome</h1>
<p>This is a document. It loads in 14ms on a 28.8k modem.</p>
</body>
</html>
2024 Index (842,903 bytes):
A sprawling, unreadable mess of <div> tags nested thirty levels deep. A <body> tag that contains nothing but a <div id="root"></div> and a four-megabyte <script> tag that “hydrates” the page—a fancy term for doing the work the server should have done in the first place.
The hex dump of a modern page is a graveyard of redundant attributes. Look at this:
44 61 74 61 2d 73 76 67 2d 69 64 3d 22 5f 31 32 33 34 35 22
data-svg-id="_12345" repeated five hundred times. Why? Because some CSS-in-JS library needs a unique hook to inject a single line of styling that could have been a global class in 1998. We used to care about every byte. We used to worry about the MTU of a TCP packet. Now, we just assume everyone has a gigabit fiber connection and a 16-core CPU to parse the sheer volume of garbage we call html.
The transition from HTML 2.0 (RFC 1866) to HTML 4.01 was the peak of the craft. We had a Document Type Definition (DTD). We had rules. If you didn’t close your tags, the parser would scream—or at least, it should have. But we got soft. We allowed “quirks mode.” We let the browsers become “forgiving,” and in doing so, we invited the chaos that now defines the modern stack.
NECROSIS OF THE SEMANTIC STRUCTURE
The html specification was intended to describe structure, not presentation. We had <header>, <main>, <footer>, <article>, and <section>. These were supposed to be the organs of the document. Instead, we are witnessing total organ failure.
Modern web development has regressed to a state of “div-soup” that would make a 1997 Geocities page look like a masterpiece of architectural design. I’ve seen production code where a simple navigation link is wrapped in six nested <div> tags, each with a generated class name like css-17z9x0b.
<div class="Box-sc-18p077x-0 iVzXvR">
<div class="Flex-sc-177n1u6-0 hYvXvR">
<div class="Text-sc-177n1u6-0 gYvXvR">
<a href="/home">Home</a>
</div>
</div>
</div>
This is a failure of the highest order. It bypasses the browser’s built-in accessibility tree. It forces screen readers to navigate a labyrinth of meaningless containers. We had the <a> tag. It worked. It still works. But the modern developer is so terrified of the cascade in CSS that they encapsulate everything until the html is unrecognizable.
The death of the <table> tag for layout was supposed to be a victory. We were told that CSS would save us. But look at what we replaced it with: Flexbox and Grid used to create the same rigid structures, but with ten times the markup. At least with a <table>, the browser knew it was rendering a grid. Now, it has to calculate the geometry of a thousand nested boxes, all because someone decided that display: table was “old-fashioned.”
TOXICOLOGY REPORT: THE POISONING OF THE DOM
The Document Object Model (DOM) was never meant to be a high-frequency state machine. It was meant to represent a static document. When you inject a library that diffs a “Virtual DOM” and blasts updates into the real DOM sixty times a second, you aren’t “building a modern experience.” You are performing a denial-of-service attack on the user’s main thread.
The toxicology report shows high levels of:
1. Script-Induced Latency: The browser cannot even begin to parse the html until the massive JavaScript bundles are downloaded, parsed, and executed. This is the “First Input Delay” that modern metrics try to hide.
2. Attribute Bloat: The use of aria-* attributes as a band-aid for poor semantic choices. If you used the correct html tags, you wouldn’t need to manually tell the browser that a <div> is actually a button.
3. Style Injection: CSS-in-JS libraries that vomit <style> tags into the <head> at runtime. This triggers a Flash of Unstyled Content (FOUC) or, worse, forces the browser to re-calculate the entire render tree every time a user hovers over a menu item.
I remember the “Browser Wars.” I remember writing different code for Netscape 4.7 and IE 5.5. We used document.layers and document.all. It was a mess, but at least we were working with the grain of the platform. Today, we treat the browser as a mere runtime for a bloated JavaScript engine, ignoring the fact that the browser is already a highly optimized C++ engine designed specifically to parse and render html. We are building a slow emulator on top of a fast engine.
ANCESTRAL WISDOM: THE PURITY OF RFC 1866 AND HTML 3.2
We need to look back at HTML 3.2 (Wilbur). It was the last time the web felt like it belonged to the people who understood the protocols. It introduced tables, applets, and text flow around images, but it still respected the document.
The transition to HTML 4.01 and then the ill-fated XHTML 1.0 was an attempt to bring rigor. We wanted the web to be XML-compliant. We wanted strict parsing. We wanted application/xhtml+xml. But the industry chose the “Living Standard” instead—a perpetual beta state where features are added based on what the Chrome team decides is best for their advertising business.
The html tag itself has been stripped of its dignity. In the XHTML days, we had to define the namespace: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">. It was precise. It was valid. Now, we just throw <!DOCTYPE html> at the top and hope the browser’s error-correction logic can figure out the mess we’ve made.
We’ve lost the concept of the “User Agent.” The browser is supposed to work for the user, not the developer. By shipping a document that is 90% script and 10% content, we are stripping the user of their agency. They can’t “View Source” and understand what’s happening. They can’t use a custom stylesheet. They are forced to consume the “experience” exactly as the framework intended, bloated and slow.
PATHOLOGICAL ANALYSIS OF THE HEAD SECTION
The <head> of a modern html document is a dumpster fire. In 1995, you had a <title> and maybe a <meta name="description">. Today, the <head> is often larger than the entire body of a 1990s website.
Look at this typical autopsy of a <head> section:
– 15 different <link rel="preload"> tags for fonts that look exactly like Helvetica.
– 10 different <meta property="og:*"> tags for social media crawlers that will never visit the site.
– 4 different tracking scripts (Google Analytics, Segment, Hotjar, Facebook Pixel) all fighting for the same CPU cycles.
– A massive block of JSON-LD for “Schema.org” because we don’t trust the browser to understand our html structure.
The entity encoding alone is enough to drive a man to drink. We see & and " scattered like shrapnel through the document because the templating engine is too stupid to handle raw UTF-8 properly. We have forgotten that html is a text format. It is meant to be readable by humans and machines alike.
THE RESURRECTION PROTOCOL: STRIPPING THE FILTH
To save the web, we must return to the source. We must perform a total debridement of the modern stack. We must strip away the frameworks, the bundlers, the “utility-first” CSS, and the hydration logic. We must return to the pure, valid html document.
A “Resurrected” document looks like this. It is valid HTML5, but it respects the constraints of the past. It uses zero external dependencies. It loads instantly. It is accessible by default. It is the pure essence of the web.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>The Resurrected Document</title>
<style>
body {
font-family: sans-serif;
line-height: 1.5;
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
background: #f4f4f4;
color: #222;
}
header { border-bottom: 2px solid #222; margin-bottom: 2rem; }
nav ul { list-style: none; padding: 0; display: flex; gap: 1rem; }
main { background: #fff; padding: 2rem; border: 1px solid #ccc; }
footer { margin-top: 2rem; font-size: 0.8rem; text-align: center; }
</style>
</head>
<body>
<header>
<h1>Digital Autopsy Report</h1>
<nav>
<ul>
<li><a href="#findings">Findings</a></li>
<li><a href="#prognosis">Prognosis</a></li>
</ul>
</nav>
</header>
<main id="findings">
<h2>Subject: The Modern Web</h2>
<p>The subject was found in a state of advanced decay. The <strong>html</strong> was bloated with unnecessary attributes and nested containers.</p>
<section>
<h3>Vital Signs</h3>
<ul>
<li>Content-Length: 1.2KB (Healthy)</li>
<li>External Requests: 0 (Optimal)</li>
<li>Semantic Integrity: High</li>
</ul>
</section>
</main>
<footer>
<p>Hand-coded in 2024. No frameworks were harmed in the making of this document.</p>
</footer>
</body>
</html>
This document is 1.2 kilobytes. It does everything the 842KB monster does, but better. It doesn’t need a build step. It doesn’t need npm install. It doesn’t need a “deployment pipeline.” You just upload it to a server and it works. It will work in Chrome 120, and it would have worked in Netscape 2.0 (with minor CSS degradation).
The “Resurrection Protocol” requires us to stop thinking about “apps” and start thinking about “documents” again. The browser is a document viewer. When we try to turn it into a thin client for a centralized state machine, we lose the very thing that made the web revolutionary: the ability for anyone, anywhere, on any device, to access information without a 400ms “hydration” delay.
We must reject the “Living Standard” that prioritizes “Web Bluetooth” and “Web USB” over the basic stability of the <a> tag. We must demand that our tools produce clean, readable html. If your framework generates a <div> where a <button> should be, throw it in the trash. If your build tool produces a 2MB bundle for a static page, delete it.
The web isn’t dead yet, but it’s on the table, and the smell of rot is overwhelming. The only cure is a return to the fundamentals. The only cure is the raw, unadulterated power of a well-crafted html file. Write it by hand. Count your bytes. Respect the RFCs. Or get out of the way and let those of us who remember how to code finish the autopsy.
Related Articles
Explore more insights and best practices: