We make Blog Import, a Framer plugin that moves a blog into Framer CMS from an export file. Its test suite had 267 passing tests on the morning of 27 October. Then we imported real exports, from public repos where people had committed their own blog backups, into a Framer project, and found four bugs in one afternoon. None of them would have shown up with the hand-written fixtures.

1. & in image addresses

A Hashnode backup with 18 posts imported fine, but 27 of 67 images failed to copy. Most were pbs.twimg.com/media/...?format=jpg&name=medium.

The post bodies are HTML, so an & inside a src attribute is written as &. We read the attribute with a regular expression and handed ...?format=jpg&name=medium to Framer's image upload as is. Twitter's CDN doesn't know a parameter called amp;name.

The fix is one line: decode & (and &, &) before uploading, and look the decoded address up when swapping the new one back in. It affects every source, not just Hashnode. A WordPress image URL with ?w=1024&h=768 would have failed the same way; our fixtures never had one. After the fix, 2 images failed, and both were dead at the source (a 404 and a 403).

2. The old site says no, sometimes

Importing the newest 25 posts from wordpress.org/news means copying 147 images. Two runs in a row lost 2 and then 4 images, different ones each time, and the posts whose cover was among them came in without a cover. Every one of those images loaded fine with curl a minute later.

We already paced uploads in batches of 10 with a pause between them, and retried one by one when a batch failed. The one-by-one retry came right after the rate limit, so it got limited too. Now the images that still fail get one more slow pass at the end: wait 10 seconds, then one image per second. The third run lost none.

That pass can take a minute on a big blog, and the progress line used to stay on "Copying images, 45 of 45" the whole time. It now says "Trying 38 images again, 12 of 38".

3. Importing again forgot the layout

At the time, Blog Import could put everything in one collection (Framer's Basic plan allows only two) or in four linked ones, chosen with a checkbox. The checkbox always started unticked, so importing a one-collection blog a second time quietly added three new collections. The plugin now saves the layout with the collection and reads it back; for collections imported before that, it looks at which fields exist. It has since gained a third layout, Blog plus categories, which also fits on Basic.

4. A message that wasn't true

A real Ghost export from 2025 had 9 images written as __GHOST_URL__/content/images/.... Ghost exports leave out the domain, so the plugin asks for the old site's address. We gave it, and 10 images still failed: the blog has since moved to a static site, and the old image addresses now return an HTML page. The results screen said those images "still load from the old site". They didn't. It now says they still point to the old site and show only while it is online.

Re-importing got fast as a side effect

Re-importing the same posts used to copy every image again, about 30 seconds for 25 Squarespace posts. Framer's plugin API can read back the items a plugin wrote (getCollections() then getItems()), so the plugin now pairs each image in the new body with the one already in Framer, by position and the text around it, and only uploads what is new. The same re-import now takes under 2 seconds, and a cover that can't be fetched no longer replaces the one already there.

What we'd tell anyone writing an importer

  • Test with real exports early. GitHub has plenty: search for Squarespace-Wordpress-Export, kind#post (Blogger), __GHOST_URL__ (Ghost), or a Hashnode backup repo. Treat them as data, read only, and don't publish other people's posts.
  • Old sites rate-limit and die. Design the image step for partial failure, and make the message say exactly what the user's site will look like.
  • Our seven sources, from those runs: WordPress (live site), Substack, Medium, Ghost and Hashnode from real exports; Squarespace and Blogger from real exports too, with failures only on third-party images (a dead host and Wikimedia refusing hotlinks).

Blog Import is on the Framer Marketplace. The newest 25 posts import free; a license for the rest is $29 for one project or $59 for any number, paid once.