Reverse Engineering ChatGPT's Frontend: How One Developer Built a Time Machine for Webpack Bundles
Hook
Every time OpenAI deploys ChatGPT, they overwrite evidence of what came before. One developer decided to preserve it all—using nothing but Node.js scripts and a healthy curiosity about what's hiding in webpack chunks.
Context
When you're analyzing open-source software, git history tells you everything: what changed, when, and why. But what happens when you need to understand the evolution of a closed-source web application like ChatGPT? The code is right there in your browser's DevTools, shipped as minified webpack bundles, but it's ephemeral. Each deployment overwrites the previous version, erasing any trace of what features existed, how bugs were fixed, or when capabilities appeared.
This is the problem that chatgpt-source-watch solves. Created by developer 0xdevalias, this project functions as a versioned museum of ChatGPT's frontend code. Rather than letting webpack chunks disappear into the void with each deployment, it systematically downloads, unpacks, formats, and archives them. The result is a searchable, diffable historical record that makes it possible to answer questions like "When did ChatGPT add GPT-4 support to the UI?" or "What code changed between the version that had the bug and the one that fixed it?" For security researchers, competitor analysts, and anyone documenting AI tool evolution, it's an invaluable resource that transforms reverse engineering from archaeology to science.
Technical Insight
The architecture of chatgpt-source-watch is elegantly simple: it's a pipeline of small Node.js scripts that can be chained together via stdin/stdout, following the Unix philosophy of doing one thing well. The workflow starts with extracting script URLs from ChatGPT's DOM, then filtering against already-saved files to identify new chunks, downloading them to an 'orig/' directory, and finally unpacking and formatting them with Biome into an 'unpacked/' directory optimized for diffing.
The script extraction is straightforward but clever. When you load ChatGPT, the page includes numerous webpack chunks—each a separate JavaScript file containing different parts of the application. The project includes scripts that parse these URLs and compare them against what's already archived. Here's the conceptual approach (simplified from the actual implementation):
// Extract script URLs from ChatGPT's HTML
const scriptUrls = Array.from(document.querySelectorAll('script[src]'))
.map(script => script.src)
.filter(src => src.includes('/_next/static/'))
// Filter out already-archived files
const existingFiles = fs.readdirSync('./orig')
const newChunks = scriptUrls.filter(url => {
const filename = url.split('/').pop()
return !existingFiles.includes(filename)
})
// Output for the next step in the pipeline
newChunks.forEach(url => console.log(url))
The real innovation comes in the unpacking stage. Webpack bundles are intentionally minified and optimized for production—they're unreadable for human analysis and nearly impossible to diff meaningfully. The project solves this by running each bundle through Biome, a fast code formatter written in Rust. This normalization transforms compact, single-line production code into properly indented, consistently formatted JavaScript that git can diff intelligently.
What makes this particularly powerful is that the scripts are composable. Want to verify your changelog is complete? Pipe the list of archived files through the validation script. Need to find chunks that were never archived? Chain together the extraction, filtering, and comparison scripts. This pipeline architecture means you can extend the toolkit without rewriting core functionality—you just add another script to the chain.
The project also demonstrates a hybrid archival approach. While it primarily downloads and stores webpack chunks directly, it also references WayBack Machine snapshots for builds that might have been missed. This creates redundancy: if the local archive is incomplete, researchers can still reference the timestamp and pull historical versions from archive.org. It's a pragmatic acknowledgment that manual archival will inevitably have gaps, and designing for those gaps is smarter than pretending they won't exist.
The CHANGELOG is manually maintained but follows a structured format that correlates dates with build IDs and notable changes. This human curation is actually a feature, not a bug—automated change detection in minified code produces too much noise, while a curated changelog highlights meaningful shifts like new features, major refactors, or security-relevant changes. The repository becomes not just an archive but an annotated historical record.
Gotcha
The most significant limitation is that this is fundamentally a manual process masquerading as automation. While the scripts streamline downloading and formatting, you still need to regularly check ChatGPT for updates, run the extraction, review what's new, download the chunks, update the changelog, and commit everything to git. There's no daemon watching for deployments, no CI/CD pipeline triggering on OpenAI's release schedule. If you don't check for a month, you'll miss deployments, and those webpack chunks will be gone forever unless the WayBack Machine happened to crawl them.
The second major limitation is coverage. This project only captures webpack bundles that are present in the initial DOM. If ChatGPT uses dynamic imports to lazy-load code after interaction (clicking a button, opening a feature), those chunks won't be captured unless you specifically trigger them and re-run the extraction. You're also completely blind to backend changes—API modifications, prompt engineering adjustments, model updates—none of that is visible in frontend webpack bundles. And if OpenAI changes their bundling strategy (switching from webpack to Vite, adopting a different CDN structure, implementing more aggressive obfuscation), the extraction scripts could break entirely. This is reverse engineering, which means you're always playing catch-up with the original developers' architectural decisions.
Verdict
Use if: you're researching how ChatGPT's UI has evolved over time, need to understand when specific features were added or removed from the web interface, are doing security research that requires analyzing frontend code changes, or want to build tooling that depends on understanding ChatGPT's client-side architecture. This project gives you the raw materials that would otherwise be impossible to obtain. Skip if: you need fully automated monitoring without manual intervention (this requires regular hands-on effort), you're primarily interested in ChatGPT's backend behavior or API changes (this only captures frontend webpack bundles), you want real-time alerts when deployments happen (updates are manual and retrospective), or you're looking for a turnkey solution rather than a DIY research toolkit. This is a historian's tool, not a surveillance system—powerful for understanding the past, but labor-intensive to maintain.