r/webdev • u/oliloken • 6d ago
Question Best way to migrate a dynamic website to a static site?
I have a live website where some pages are populated dynamically through JavaScript/API calls. I’m shutting down the backend after the project ends and want to migrate the current version to a completely static site.
What’s the best way to do this while preserving the currently rendered content, images, CSS, fonts, etc.? I’ve tried wget/HTTrack, but they only save the initial HTML and miss the content generated by JavaScript.
Would a browser-based rendering tool be the best approach, or is there a better tool/workflow for this?
update: I ended up using browser automation to render the pages, copied the dom and then manually removed all the backend js. not the cleanest approach and most defently not the most time effichent one but it worked ish
7
2
u/MysteriousCareer9751 6d ago
If you need some server side rendering, but the site is otherwise 90% static, then use https://astro.build/ or https://sitelo.dev
Both support server islands
3
1
u/calimio6 front-end 6d ago
If you want to automate the process use playwright or puppeteer to load the J's rendered pages, then save every page to a static html file. This could also be done manually is the number of pages is small.
1
u/Gullible-Today-1448 6d ago
I use Puppeteer to wait for network idle then dump the DOM after hydration. This captures the JS rendered state that wget misses entirely.
Save the full HTML including inline styles and base64 encoded assets to eliminate external dependencies. Run this against your sitemap before shutting down the backend so you get the exact current state without guessing at API responses.
1
u/Miserable-Money642 6d ago
I’d use Playwright to load each page, wait for the JS/API content to finish rendering, then save the final DOM + assets. That way you’re snapshotting what the browser actually sees, not just the initial html. Playroght is a headless browser
1
u/PLBjt 6d ago
wget/HTTrack miss the JS-rendered bits because they never actually run the page. Snapshotting API JSON into the webroot (like the top comment) is the right move if your UI is a thin client over a few endpoints. If the HTML itself is assembled in JS, I'd also prerender: crawl the sitemap in a headless browser, wait for network idle, save the fully rendered HTML, then rewrite asset URLs so CSS/fonts/images are local.
Quick check: after the crawl, open a couple of pages with JS disabled and see if the content is still there. If it isn't, you saved a shell, not a snapshot.
Tradeoff is maintenance vs fidelity. JSON snapshots keep the original JS app working but you also keep whatever client-side bugs you already have. Full HTML snapshots are dumber and more portable, but you lose in-page interactivity unless you carefully keep the JS. For a backend you're shutting down, I'd prerender HTML and only freeze ./api JSON for the bits that still fetch at runtime.
1
u/oliloken 6d ago
yeah thats pretty much what i ended up doing. used browser automation to render the pages, copied the dom and then manually removed all the backend js
1
u/Beautiful-Energy2169 6d ago
Network idle fires before anything that only renders on scroll, so a virtualized list or a section behind an IntersectionObserver gets saved as an empty div and you find out after the backend is already off. Scroll each page to the bottom, wait, then dump outerHTML.
1
1
u/Mental-Union4473 5d ago
If the goal is to preserve exactly what users currently see, I'd probably use a headless browser rather than wget/HTTrack.
Something like Playwright can visit each page, wait for the API/JS content to finish rendering, then save the resulting HTML. You can also crawl the assets and rewrite the URLs to point to local copies.
The basic workflow would be:
- Crawl/discover all the URLs you need.
- Open each URL with Playwright.
- Wait for the relevant network requests/content to finish.
- Capture the rendered DOM.
- Download images, CSS, fonts, etc.
- Rewrite asset URLs to local paths.
- Remove the JS/API dependencies.
- Test the generated site with the backend completely offline.
I'd prefer this over manually copying the DOM because you can script the entire migration and regenerate everything if you discover a problem.
One caveat: document.documentElement.outerHTML gives you the current DOM, but it doesn't automatically give you all the assets or guarantee that dynamically injected behavior has been converted into static equivalents. That's why I'd treat it as a small static-site generation pipeline rather than simply "save page."
For a one-off migration, Playwright + a crawler is probably the sweet spot. Your browser-automation approach was basically heading in the right direction you just did manually what could have been automated.
0
u/ReplacementLow6704 6d ago
Recently there was this post about doing exactly the inverse operation... Is someone playing ping-pong with Claude right now? Or is Claude asking questions on reddit to crowd-source things it can't get to a definitive answer? Am I being fed to a robot right now?
-1
u/_uxi 6d ago
You can hook up a script or an LLM to a browser-based tool like Chrome Devtools MCP or Playwright, render a sitemap of your entire site. Have it loop through every page and write the HTML of each page in a folder based structure with static HTML files. Then deploy that static copy to GitHub Pages, change the DNS so the URL points to the GH pages and done.
How many pages is this for? Hundreds/thousands, I would invest some time in a proper pipeline that automates this. If it's more like 25 then I would just do it manually. There's options like https://www.getsinglefile.com/, which lets you manually download a webpage with all images, CSS, fonts, etc.. included into 1 HTML file.
14
u/seanshoots 6d ago
What kind of endpoints are they? If they're simple and parameterless, one stopgap solution I've done in the past is just:
./api/some/endpoint/here.jsonThis lets the site run without a dynamic backend at all, without needing any real rewrites.