Automated summary
This skill downloads a Framer site (live URL or local export) into fully local HTML/JS/CSS files with no Framer CDN dependencies.
Strengths
- Downloads and sorts JS, CSS, images and media assets into dedicated local folders
- Rewrites static and dynamic ES module imports plus modulepreload links to point at local files
- Handles multi-page exports by reading the data-framer-hydrate-v2 routeIds and generates a server.js for SPA routing
- Strips the "Made in Framer" badge and editor bars, and validates media downloads via magic bytes
Limitations
- Relies on the described Framer export structure (.mjs naming, data-framer-hydrate-v2), so heavily customized sites or custom code components may break
- Fonts are skipped by default and must be requested explicitly
- Requires network access to the CDN and running server.js for SPA routes to resolve locally
Use it when you want to self-host a Framer site, remove Framer branding, or produce an offline-capable copy.
Avoid it if the site was not exported by Framer or if you only need a visual backup without rewriting JS modules.
Security analysis
CautionThe skill is a legitimate, well-scoped site-mirroring tool: it fetches public CDN assets, rewrites imports and HTML paths, strips branding, and writes a small local server. The risk profile is that of a powerful but normal dev workflow — network downloads, recursive file edits, a targeted directory deletion, and executing a generated server.js. There is no evidence of exfiltration, destructive absolute-path deletion, or obfuscation, so it warrants 'caution' rather than 'risky'.
- •Uses Bash/network to download arbitrary remote assets (JS/MJS modules, media) from Framer CDNs and then executes nothing, but the downloaded JS is later served locally via a generated Node server
- •Step 7 deletes directories (limited to 'empty' static HTML dirs, but the guard is heuristic and a mis-classified directory could remove user files)
- •Generates and runs a local server.js — running it via `node server.js` executes agent-authored code
- •No secret exfiltration, no curl|sh piping, no obfuscated payloads, no safety-disabling instructions
Examples
Export https://example.framer.app to local HTML/JS/CSS files in ./site so I can self-host it without any Framer CDN calls.Take my local Framer export in ./my-exported-site, download all CDN assets into js/, css/, images/ and media/, and remove the 'Made in Framer' badge.My self-hosted Framer export breaks on /blogs and /pricing — fix the SPA routing, rewrite the modulepreload links, and generate a server.js with URL-to-HTML mapping.name: framer-export description: Export a Framer website to fully local HTML/JS/CSS with no CDN dependencies. Use when the user wants to self-host a Framer site, remove Framer branding, or create an offline-capable version. Works on any Framer-exported site. disable-model-invocation: true allowed-tools: Bash, Read, Grep, Write, Edit, Glob, TaskCreate, TaskUpdate, TaskList, TaskGet
Framer Exporter Skill
Export any Framer website to fully self-hosted local files with no Framer CDN dependencies.
What This Does
- Downloads all assets — JS, CSS, images, video, PDF, audio, and other files from Framer CDN to local
js/,css/,images/,media/folders - Fixes ES module imports — Updates all
importandimport()paths to use local filenames, includingmodulepreloadlinks - Handles multi-page exports — Detects and processes all HTML pages (blog posts, policy pages, sub-routes) with their unique
data-framer-hydrate-v2routeIds - Removes Framer noise — Strips "Made in Framer" badges, editor bars, and Framer branding precisely
- Fixes SPA routing — Updates nav links, deletes conflicting directories, generates a custom
server.jswith URL-to-HTML mapping
Usage
Export a live Framer site
/framer-export https://example.framer.app
Export from local HTML files
/framer-export ./my-exported-site
Workflow
Step 1: Analyze the site
- If URL: download the HTML and scan for all external CDN URLs
- If local: scan all HTML files for CDN references
- Categorize correctly by checking file extensions using regexes (e.g.
/\.(js|mjs)(\?|$)/ifor JS,/\.css(\?|$)/ifor CSS,/\.(png|jpg|jpeg|webp|gif|svg|ico)(\?|$)/ifor images). This ensures files with query parameters (e.g.,?v=2) are not misclassified as media files. - Detect all page routes: Every
.htmlfile found represents a unique route (homepage/,/blogs,/pricing,/terms-conditions,/blogs/slug-title, etc.) - Each HTML file contains
data-framer-hydrate-v2="{routeId:...}"— this JSON determines which page renders on the client and is baked in at download time, so each route needs its own HTML file - Log all discovered routes
Step 2: Create local asset directories
Create js/, css/, images/, media/ directories alongside index.html.
Step 3: Download all external resources
Download all JS, CSS, images, and media files (video, PDF, audio, documents) to local directories. Skip fonts by default unless user requests them.
- Media Validation: Validate downloaded files. For videos (MP4, WebM, Ogg) and audio, read the first 12 bytes to verify magic bytes. MP4 contains
ftypat offset 4, WebM/MKV starts with\x1a\x45\xdf\xa3. Reject empty files.
Important: Extract dynamic import URLs from script_main.mjs. Framer's SPA router dynamically imports page modules. Construct full CDN URLs from the script_main base path, and download those dynamic modules too.
Step 4: Fix ES module imports in JS files
Many Framer exports have import statements referencing CDN filenames like 7zd_4hdYd8O.mjs. Rename these to short local names and update all import paths:
from "./7zd_4hdYd8O-dG7PZxJrnFUX2tGHHFGd1cKXxhsQWgA.B72Ql4Dm.mjs"→from "./site-home.mjs"- Also fix dynamic imports:
import(`./filename.mjs`) - Also fix
modulepreloadlinks.
Step 5: Update HTML references
Replace all CDN URLs in HTML files with absolute root-relative paths (starting with /) to ensure sub-pages and nested routes resolve correctly:
https://framer.com/bootstrap.js→/js/bootstrap.js- Images:
https://framerusercontent.com/images/xxx.png→/images/xxx.png(strip query params) - Media (video/PDF/audio):
https://framerusercontent.com/files/xxx.pdf→/media/xxx.pdf - Modulepreload links: Rewrite relative/CDN modulepreload href values to
/js/filename.mjsbut ignore any links that are already absolute (starting with/) or external (starting withhttp/https) to avoid double-prefixing.
Step 6: Remove Framer noise
Surgically remove Framer badge, editor bar, iframe, and related CSS/scripts. Update all HTML files, not just the homepage.
Step 7: Fix SPA routing
- Delete empty static HTML directories (blog/, support/, etc.) that override SPA routes — but ONLY if they contain no actual HTML files
- Update nav links from
.htmlpaths to SPA routes:href="blog/index.html"→href="/blog". Skip relative asset directory prefixes (js/,css/,images/,media/) and file extensions to avoid breaking asset loading. - Generate a custom
server.jsthat maps each discovered URL slug to its HTML file. - The
server.jstemplate must double-escape regexes (e.g.url.replace(/^\\//, '')in template string) to strip leading slashes correctly.
Step 8: Verify
- Run:
node server.js - Test all routes and test page refresh on sub-pages and nested pages to check for any blank screens or 404s.
- Check browser console for "Failed to fetch dynamically imported module" errors.
Important Framer Patterns
data-framer-hydrate-v2
Framer bakes data-framer-hydrate-v2="{routeId:...,...}" JSON into each HTML page. This routeId is set at download time — each unique URL needs its own HTML file because the routeId cannot be dynamically changed after download.
CDN import paths to fix
Framer uses hash-based filenames. Common patterns:
https://framer.com/bootstrap.[hash].js
https://app.framerstatic.com/chunk-[hash].mjs
https://framerusercontent.com/sites/[siteId]/[hash].mjs
Route modules
Framer SPAs define routes in site-script_main.mjs:
W = {
routeId: { page: () => import('./route-page.mjs'), path: '/path' },
...
}
The route .mjs files often import each other — must update ALL import paths recursively.
Dynamic imports in route files
Route files often import other modules dynamically:
page: E(() => import(`./some-file.mjs`))
These also need fixing.
Image URL variants
Framer URLs appear in multiple attributes:
src="https://framerusercontent.com/images/xxx.png?width=101&height=101"
srcset="https://framerusercontent.com/images/xxx.png?w=800 800w, ..."
href="https://framerusercontent.com/images/xxx.png?..." (favicon)
content="https://framerusercontent.com/images/xxx.png?..." (og:image)
Strip query parameters from all of these and map to images/.
Framer font files
framerusercontent.com/assets/*.woff2 custom fonts — these are design fonts with no Framer branding. It's acceptable to keep them as external references. Skip by default, offer --with-fonts to download.
Output Structure
project/
├── index.html (cleaned, local refs)
├── server.js (custom SPA server with URL→HTML mapping)
├── js/
│ ├── bootstrap.js
│ ├── site-script_main.mjs
│ ├── site-[name].mjs
│ ├── route-[page].mjs
│ └── ...
├── css/
│ └── editorbar.css
├── images/
│ └── [all images]
└── media/
└── [videos, PDFs, audio, documents, etc.]
Edge Cases
- Port conflicts: Kill existing processes on the port before starting server (
taskkill //F //IM node.exeon Windows) - Static
.htmlfiles: If nav links point to.htmlfiles that exist, update those files' CDN refs too - Empty dirs vs real dirs: blog/ with only empty subdirs → delete; blog/ with
index.html→ keep and clean - Blog post slugs: URLs like
/blogs/top-ai-toolsneed their ownblogs/top-ai-tools.htmlfile — extract fromdata-framer-hydrate-v2or from the SPA router config - Font files: Skip by default; no visible branding but adds significant export time
- Canvas sandbox iframe: Editor-only, safe to remove (already caught by noise removal)
From the file to a first result
The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.
View the source and supporting filesThis download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.
1. Download the file
Download SKILL.mdFrom the root of a test project, save the file as .skill-downloads/framer-exporter-mrx3xwu0/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.
Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.
mkdir -p '.skill-downloads/framer-exporter-mrx3xwu0' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/framer-exporter-mrx3xwu0/download' --output '.skill-downloads/framer-exporter-mrx3xwu0/SKILL.md.part' && mv '.skill-downloads/framer-exporter-mrx3xwu0/SKILL.md.part' '.skill-downloads/framer-exporter-mrx3xwu0/SKILL.md'2. Check prerequisites
Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.
Tools declared by the author (check availability in your agent): Bash, Read, Grep, Write, Edit, Glob, TaskCreate, TaskUpdate, TaskList, TaskGet
No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.
The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.
3. Load the skill
After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.
Claude Code
test -f '.skill-downloads/framer-exporter-mrx3xwu0/SKILL.md' && test -s '.skill-downloads/framer-exporter-mrx3xwu0/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/framer-export' && cp -R '.skill-downloads/framer-exporter-mrx3xwu0' '.claude/skills/framer-export'OpenSkills
OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.
Official OpenSkills installationopenskills install './.skill-downloads/framer-exporter-mrx3xwu0'openskills read 'framer-exporter-mrx3xwu0'Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.
For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.
openskills syncManual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.
4. Try a first task
Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:
Read .skill-downloads/framer-exporter-mrx3xwu0/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.
React Hook Form Best Practices
Development
Master React Hook Form: avoid anti-patterns, manage subscriptions, and handle reset, dirty state, and controlled inputs correctly.
Emotion to Mantine Migration
Development
Migrate Emotion styled-components to Mantine components with style props and CSS modules. Use when converting .styled.tsx files or removing @emotion imports.
Scope Creep Detector
Development
Analyzes git diffs against a stated intent to detect scope creep, unrelated files, broad PRs, and oversized changes, then suggests keep, split, or justify actions.