There is a growing nostalgia for the mid-2000s web. Back then, websites had personality: Windows 98 bevelled windows, blinking hit counters, guestbooks, WordArt headers, and low-res pixel graphics. It felt human, messy, and delightfully unpolished.
But if you actually try to load an authentic 2006 website on a modern smartphone, the illusion shatters immediately. The <frameset>tags break iOS Safari viewports, unstyled nested tables require aggressive pinch-to-zoom, dial-up scripts crash modern browsers, and the raw inline HTML fails every security audit conceived in the last decade.
Recently, I built a nostalgic web experience (retro.ezinner.com) designed to capture that exact 2006 aesthetic—without dragging in the technical debt of the era.
The goal was an intentional paradox: make a website that looks like it was hacked together in Windows Notepad in 2006, but runs on a hardened, high-performance 2026 engineering stack.
Replacing <frameset> with Modern DOM
In 2006, multi-pane desktop sites relied heavily on <frameset>or nested <iframe> tags to simulate operating system windows.
On modern mobile browsers, nested iframes are an absolute disaster:
- Touch Scrolling Lockups: Touch gestures lock up inside the nested frame boundaries, preventing natural page momentum scrolling.
- WebKit Viewport Breakage: Viewport scaling and elastic overscroll behave unpredictably on mobile WebKit.
- Desynced History: Inner-frame navigation never syncs with the browser address bar, breaking bookmarking, deep-linking, and the back button.
Instead of fighting frames, I emulated the multi-pane OS window entirely via CSS Grid and Flexbox tied to lightweight hash routing (#projects,#services).
You get the authentic retro Windows chrome, bevelled grey borders, and title bars, but with zero iframe clipping, native smooth GPU-accelerated touch scrolling, and instant client-side state changes that update the browser URL bar cleanly.
Windows 98 Desktop vs. WAP 2.0 Mobile
In the mid-2000s, desktop and mobile were completely different internets:
- Desktop: Ran rich HTML over broadband or 56k dial-up connections.
- Mobile: Ran WML (Wireless Markup Language) or XHTML-MP over 2G/GPRS WAP gateways.
Most modern "retro" sites make the mistake of squishing their desktop Windows 98 UI onto mobile screens. Trying to tap a 12-pixel minimize button on an iPhone screen is terrible UX.
Instead, the site uses a dual-personality responsive design that splits cleanly at 768px:
- Desktop (>768px): The full Windows 98 multi-window desktop experience—glowing 3D WordArt, floating draggable window chrome, an LED visitor counter, and retro web badges.
- Mobile (≤768px): The site completely transforms into an authentic Nokia / Sony Ericsson WAP 2.0 portal:
- Top header: ASCII-style battery and signal indicators (
[▲▲▲▲▲] GPRS [■■■■]). - Navigation: Numbered WAP access keys (
[1] Обо мне,[2] Проекты,[3] Контакты). - Footer: Classic
[0] К менюback jumps.
- Top header: ASCII-style battery and signal indicators (
Instead of a broken desktop experience on a phone, mobile users get a blast of authentic early-mobile nostalgia that is genuinely readable, lightning-fast, and ergonomic to tap with a thumb.
Simulating 56k Dial-Up with Hardware-Accelerated CSS
Nothing defined the 2000s web quite like the agonizing, line-by-line render of a progressive JPEG over a screeching 56k modem.
The naive way to simulate this today is using heavy JavaScript canvas hacks or bloated 5MB animated GIFs. That defeats the purpose of building lightweight, high-performance web pages.
Instead, the modem decoding effect is powered by native, GPU-accelerated CSS:
- The Scanline Beam: A single
clip-path: inset(0 0 (100 - progress)% 0)rule paired with a bright cyan gradient beam sweeps down the image container. - The Byte Ticker: A lightweight asynchronous counter simulates erratic 56k download speeds (
Math.floor(progress * totalKB)). - The Result: Silky 60fps progressive decoding with zero layout shift, negligible CPU usage, and instant replayability on click.
/* 60fps GPU-accelerated progressive JPEG decode simulation */
.modem-image-container {
position: relative;
overflow: hidden;
}
.modem-image-container img {
clip-path: inset(0 0 calc(100% - var(--progress, 0%)) 0);
will-change: clip-path;
}
.modem-scanline-beam {
position: absolute;
top: var(--progress, 0%);
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00ffff, transparent);
box-shadow: 0 0 8px #00ffff;
pointer-events: none;
}Nostalgic Look, Fort Knox Security
Authentic 2006 web code was a security nightmare. It was packed with raw inline styling (style="color: red; font-size: 12px", bgcolor="#ffffd0") and inline event handlers (onclick="window.open(...)").
If you serve that HTML today under a strict Content Security Policy, modern browsers will block your styles, disable your buttons, and flag your site on security scanners.
To resolve this paradox, I ran the build through astro-strict-csp (my open-source Astro security integration):
- Inline Style Extraction: Every nostalgic inline style and table attribute is automatically extracted into external stylesheets and deduplicated into tiny MD5 utility classes at build time.
- Inline Event Extraction: Retro
onclickhandlers are extracted into a single capture-phase delegated dispatcher bundle (_astro/events-[hash].js). - Subresource Integrity (SRI): Every extracted script and stylesheet receives a cryptographic
sha384hash. - Zero 'unsafe-inline': The site emits an A+ Content Security Policy (
default-src 'none'; script-src 'self'; style-src 'self').
<!-- Authored 2006-style retro markup in template -->
<button onclick="playModemSound()" style="background: #c0c0c0; border: 2px outset #ffffff;">
Connect 56k
</button>
<!-- Extracted 2026 production output via astro-strict-csp -->
<button data-csp-on-click="evt-56k" class="is-7a1b2c">
Connect 56k
</button>The punchline: the site looks like a forgotten Geocities page from 2006, but it passes strict enterprise and banking-grade security audits with zero CSP violations.
Zero-Backend Hit Counters & Guestbooks
In 2006, features like hit counters and guestbooks required Perl CGI scripts (guestbook.cgi) or PHP/MySQL databases. Within six months, those scripts were inevitably abandoned or spammed with pharmaceutical bot links.
To keep the site permanently maintenance-free, all retro interactivity is engineered local-first:
- The Hit Counter: Instead of querying an external database on every page load, the counter calculates visits mathematically from a fixed epoch (January 1, 2006) combined with client-side visit increments in
localStorage. It looks and feels dynamic, persists across sessions, and requires zero servers. - The Guestbook: The guestbook comes pre-seeded with authentic, nostalgic mid-2000s entries in static HTML. When modern visitors submit a new entry, it writes directly to
localStorage, rendering their comment instantly without opening up an unmoderated spam vector.
Dual Audience: 2006 Humans vs. 2026 AI Agents
The final architectural layer addresses who actually browses the web today:
- For Humans: Dial-up sounds, Winamp MP3 player skins, pixelated cursor trails, and blinking marquee banners.
- For AI Agents: LLM crawlers, Claude Code, and autonomous coding agents get served a clean, machine-readable
/llms.txtfile directly at the root.
While human visitors explore the interactive 2006 desktop nostalgia, AI agents can bypass the retro chrome entirely, parsing a structured summary of technical skills, engineering projects, and architecture case studies in seconds.
Nostalgia Doesn't Have to Mean Technical Debt
Building retro interfaces is fun, but nostalgia shouldn't come at the cost of accessibility, mobile ergonomics, or baseline web security.
By separating the visual aesthetic of 2006 from the underlying engineering of 2026, you can deliver an authentic blast from the past that still loads in under 100 milliseconds, respects mobile viewports, and passes the strictest modern web standards. You can test drive the live retro desktop and WAP portal at retro.ezinner.com.