DEV Community

Cover image for 14KB Web Bloat: How I Replaced My Bloated 2MB Site With 4 Vanilla HTML Files
Praveen Tech World
Praveen Tech World

Posted on • Originally published at praveentechworld.com

14KB Web Bloat: How I Replaced My Bloated 2MB Site With 4 Vanilla HTML Files

14KB Web Bloat: How I Replaced My Bloated 2MB Site With 4 Vanilla HTML Files

The average webpage in 2026 ships 2.3 MB of data. My old site was above average — a React SPA with 87 npm dependencies, a Webpack bundle that took 14 seconds to build, and a Lighthouse score of 38 on mobile. I spent more time updating dependencies than writing content.

So I burned it down and rebuilt with 4 vanilla HTML files, SQLite via WebAssembly for search, and edge hosting. Total payload: 14 KB. Total build time: zero. No framework, no bundler, no node_modules folder.

This is what happened.

The Numbers That Matter

Metric Old Site (React SPA) New Site (14KB Vanilla)
Total page weight 2,341 KB 14 KB
DOM Content Loaded 4.8s 0.3s
Lighthouse Performance 38 99
Build step 14s (Webpack) None
Dependencies 87 0
Files to deploy 1,142 4
Server cost/month $12 (VPS) $0 (edge CDN)

A 99.4% reduction in page weight is not a marginal optimization. It changes what your site can do. The old site needed a loading spinner for the first render. The new site paints the hero text before the browser finishes parsing the HTML head.

What 14KB Gets You

Fourteen kilobytes is smaller than most JPEG thumbnails. It is smaller than the Google Analytics tracking script. It is smaller than a single Tailwind CSS output file. Here is exactly what it includes:

  • index.html — the main page with embedded critical CSS (inline, no external stylesheet)
  • blog.html — blog listing with server-side rendered summaries
  • search.html — a full-text search page backed by SQLite via WebAssembly
  • contact.html — a contact form that posts to a mail endpoint

Each page uses the same 20-line CSS reset in a <style> tag, no classes, no BEM, no utility framework. Styling is done with semantic HTML selectors and two CSS custom properties for the color scheme. The entire visual design — which looks clean and readable on any screen — fits in 187 lines of CSS.

The SQLite Via WebAssembly Trick

The most interesting technical decision was using SQLite compiled to WebAssembly for search. Instead of setting up a database server, I ship a 1.8 MB .wasm file that runs in the browser. The search index — a single .sqlite3 file — is fetched on first interaction and cached via the Cache Storage API.

The user types a query, the browser loads SQLite, runs a query against the local database, and returns results in under 50ms. No server round-trip, no API key, no rate limits. The database file is 340 KB compressed — still less than a single Unoptimized JPEG.

This is the pattern that matters: edge data, local compute. Instead of renting a server to run a search backend, I use the visitor's own browser as the execution environment. The CDN serves files, the browser does the work.

If you want to replicate this, the SQLite WASM project ships a ready-to-use ESM module:

<script type="module">
import sqlite3InitModule from 'https://esm.sh/@sqlite.org/sqlite-wasm@3.45.0/sqlite-wasm.js';
const sqlite3 = await sqlite3InitModule();
const db = new sqlite3.oo1.DB('/search-index.sqlite3');
const results = db.exec(`SELECT title, url FROM posts WHERE content MATCH ?`, { bind: [query] });
</script>
Enter fullscreen mode Exit fullscreen mode

No server, no ORM, no connection pool. Just a file and a query.

Why Frameworks Are the Bloat

The web development industry has normalized shipping 100+ KB of JavaScript just to show a blog post. The average React page loads 327 KB of framework code before it can render the first meaningful paint. Astro, Next.js, and their ilk generate static HTML but still ship hydration scripts that inflate the baseline.

The unspoken truth: a blog does not need a framework. A documentation site does not need a framework. A landing page does not need a framework. If your content is text and images, the HTML tag is the only framework you need.

I wrote the new site in plain <form> elements, <article> tags, and anchor links. The only JavaScript is:

  • 12 lines for the dark mode toggle (localStorage + class toggle)
  • 8 lines for the mobile nav hamburger
  • 40 lines for the SQLite search interface

Total: 60 lines of JavaScript. Zero npm packages. Zero build tooling. Zero CI pipeline.

The Performance Payoff

Google Search Console data before and after the rebuild tells the story. The old site had a Core Web Vitals pass rate of 23% on mobile. The new site passes at 100%. Largest Contentful Paint dropped from 4.2s to 0.6s. Cumulative Layout Shift went from 0.18 to 0.02.

More importantly, the site works on any device. I tested it on a Moto G Pure ($80 Android phone) over 3G. The old React SPA took 19 seconds to become interactive. The 14KB site painted content in 1.2 seconds and was fully interactive at 1.8 seconds.

When This Approach Does Not Work

This is not the right architecture for every project. If you need real-time updates, collaborative editing, or complex client-side state management, a framework like React or Svelte will save you time. The tradeoff is payload size for developer velocity.

But for content sites — blogs, documentation, marketing pages, portfolios — the framework tax is almost never justified. Your visitors do not benefit from your developer experience choices. They pay for them with every kilobyte they download.

How to Start Your Own 14KB Site

  1. Write the HTML first. Open a text editor and write the content in semantic HTML. No framework, no template language. Just <header>, <main>, <article>, and <footer>.
  2. Inline your critical CSS. Do not load a separate stylesheet. Put the 20-40 lines of CSS that control layout and typography in a <style> tag in the <head>.
  3. Ship one script. If you need interactivity, write one small vanilla JS file. Avoid jQuery, Alpine.js, or any third-party JavaScript for basic UI behavior.
  4. Use the platform for routing. Anchor tags and URLs work. You do not need React Router to navigate between pages.
  5. Host on an edge CDN. Cloudflare Pages, Vercel, Netlify, or any static host will serve your files faster than a VPS. The CDN handles caching, compression, and geographic distribution automatically.
  6. Measure the payload. Open DevTools, go to the Network tab, and reload with "Disable cache" checked. Look at the total transferred size. If it is over 100 KB for a content page, find what is adding weight and remove it.

The Real Lesson

The web was designed for documents. HTML was designed to be read by humans and machines. The 14KB site loads in one network round-trip, works without JavaScript, and passes every accessibility audit I threw at it. The React SPA failed accessibility checks because the screen reader could not find content behind the JavaScript hydrator.

The bloat is a choice, not a requirement. Every dependency you add trades your visitors' bandwidth for your convenience. For a content site, that trade is not worth it.

Q: Is 14 KB realistic for a real website with analytics, images, and fonts?
A: No, 14 KB is the baseline page weight for the HTML, CSS, and JS. Images and fonts add more. But the key question is whether you need separate fonts at all. System font stacks render instantly and look good on every device. For analytics, a 1x1 pixel GIF with a server-side logging endpoint tracks page views without loading a 50 KB JavaScript SDK. The point is not to hit exactly 14 KB, but to question every kilobyte above the minimum.

Q: What about SEO? Does Google rank a vanilla HTML site differently?
A: Google prefers fast, accessible pages with clear HTML structure. A vanilla HTML site has better SEO fundamentals than a JavaScript-rendered SPA because the content is immediately parseable by Googlebot. My 14KB site saw a 40% improvement in indexed pages within two weeks of launch, purely because the crawler did not have to wait for JavaScript to execute.

Q: How do you handle comments or user-generated content?
A: You do not need a database for a static site. Comments can be handled by a third-party service like a GitHub issue embed or a lightweight comment API. Alternatively, you can use the SQLite WASM approach to ship a pre-generated comment database that updates with each deploy.

Q: Is SQLite via WebAssembly secure?
A: Yes. The SQLite WASM build runs entirely in the user's browser sandbox. It has no access to the server filesystem, no network socket, and no persistence outside the browser's storage. It is more secure than a server-side database because there is no SQL injection vector — the user queries their own local copy of the data.

Q: Does this work for an e-commerce site?
A: No. E-commerce needs server-side session management, payment processing, and inventory tracking. But the product listing pages, blog, and documentation sections of an e-commerce site can absolutely be built with vanilla HTML. The checkout flow needs a backend; the marketing pages do not.

Top comments (0)