What migrates cleanly
- Rendered pages: markup, stylesheets, scripts and images.
- Static content of every kind — the marketing pages, the docs, the portfolio.
- The visual result, since you are copying the output rather than reinterpreting the source.
What does not
- Forms. The builder was handling the submission. You need somewhere for it to post.
- Site search, if it was a hosted feature.
- The CMS. Collection pages come across as the pages they rendered to, frozen.
- Anything the builder ran server-side: redirects, password areas, personalisation.
Mirror the site
wget --mirror --page-requisites --convert-links \
--adjust-extension --no-parent https://example.webflow.io/Or use the official export if your plan has one — it produces cleaner markup than any crawler.
Publish the tree
cd example.webflow.io && zip -r ../site.zip . && cd ..
curl -X POST https://read.botook.ai/sites \
-H "Authorization: Bearer otr_live_YOUR_KEY" \
-F file=@site.zip -F expires_in_hours=neverThe archive is unpacked and served as a tree, with index.html as the entry point.
Then check it, page by page
This is where migrations fail. A 201 means the zip was accepted; it says nothing
about whether the fonts loaded or the navigation works:
for p in / /about /pricing /contact; do
printf '%s ' "$p"
curl -s -o /dev/null -w '%{http_code}\n' "https://your-link$p"
doneThen open the important pages in a browser and look at them. Automated checks catch missing files; only eyes catch a stylesheet that loaded but did not apply.
Third-party scripts
Builder exports usually reference an analytics or font script from a CDN. The viewer's strict content policy refuses third-party scripts, so those simply do not run. For a mirrored site that is mostly a relief; if a page genuinely needs the code, inline it.
Point your domain at it
A CNAME, a TXT record and a verification call, and the mirror answers on your own hostname — custom domains.
Or keep it private on purpose
Plenty of migrations are not public launches: an archive of a site you are retiring, a snapshot for a legal request, a copy a client asked for. Leave the unguessable link as-is and nothing is indexed.
Letting an agent do it
This is a good agent task and a bad manual one — fetch, rewrite links, zip, publish, verify each page renders. Registered clients can run the whole thing end to end; the verification step is the part worth insisting on, and the reason it belongs in a skill rather than in your afternoon.
Updating the mirror
Re-mirror and replace in place. Same link, same domain, new content:
curl -X PUT https://read.botook.ai/sites/SITE_ID \
-H "Authorization: Bearer otr_live_YOUR_KEY" -F file=@site.zipProving the mirror covers the whole site
Mirroring is the easy half; knowing what the mirror missed is the half people skip. A crawler only reaches pages something links to, so anything reachable only from a sitemap, a redirect or a form submission is quietly absent. Compare the two lists before you cut the domain over:
# what the builder says exists
curl -s https://example.webflow.io/sitemap.xml \
| grep -oE '<loc>[^<]+' | sed 's|<loc>||' | sort > live.txt
# what actually came down
find example.webflow.io -name '*.html' | sort > mirrored.txt
wc -l live.txt mirrored.txtThen open the published tree and check that each migrated page renders — not that the publish
returned a 201, which only means the archive was accepted. The pages that break are
predictable: absolute URLs still pointing at the old host, assets the crawler never requested, and
anything that was being generated per-request. Fix those, re-zip, and replace in place rather than
publishing a second site.
What you are giving up
The visual editor. If someone non-technical needs to edit copy weekly, a builder is a better tool and you should stay. This is the right move when the site has stopped changing, or when the thing editing it is now an agent.
What you gain
- No plan boundary between you and your own pages.
- A tree of static files you can move anywhere, forever.
- Privacy by default, which builders do not offer at all.
Questions
Does the CMS content come across?
As rendered pages, frozen at mirror time. Dynamic collections stop being dynamic.
What about forms?
Point them at your own handler. Nothing here processes a submission.
Can I migrate several sites?
Yes — one zip each, no per-site charge.