LayerPort

Guide · Deploy

How to self-host a Framer website.

Self-hosting is three decisions: get the files, pick a host, move the domain. The first is the hard one and it is solved by a proper capture. This guide is the other two, with real limits and the exact files you will find in the export.

In brief

  1. You need files, not a plan

    Framer's plans differ in bandwidth and pages, not in whether you can leave. A capture with localized assets is the piece self-hosting needs.

  2. Pick a host by bandwidth and build model

    Vercel Hobby includes 100 GB a month; Netlify Free is a 300-credit monthly budget in which a GB costs 20; Cloudflare Pages does not meter bandwidth. All three import a static folder with no build step.

  3. The export already has the configs

    vercel.json, netlify.toml and _headers ship in the ZIP. Nothing to write before the first deploy.

  4. Prove it stands alone before DNS

    Serve the folder locally, go offline, walk every route. If anything still points at Framer you will see it in the network panel.

  5. Move the domain last

    Deploy, verify on the host's preview URL, then repoint DNS. Keep the Framer site published until the TTL passes.

What self-hosting actually requires

Framer's plans differ in pages and bandwidth (1 GB on Free, 50 GB on Basic, 100 GB on Pro before overage) but not in whether you can take the site elsewhere -- none of them hand you files. Self-hosting therefore starts with a capture that localizes every asset: stylesheets, the module graph behind the animations, fonts, and every srcset variant of every image. If you have not done that yet, start with the export guide.

Once you have the folder, the rest is ordinary static hosting. There is no server-side code in a captured Framer site; it is HTML, CSS, JavaScript and assets, and anything that serves files with the right MIME types will serve it. That includes a small VPS with Nginx, which is worth remembering when a hosting comparison starts to feel like a religion.

Free tiers, as listed on 28 Sep 2026

Enough for most portfolios and marketing sites. Vercel's Hobby plan is for non-commercial use; a client site belongs on Pro. Numbers move -- the sources are linked.
HostFree bandwidth / monthBuilds or deploysCustom domain + HTTPSReads from the export
Vercel (Hobby)100 GB100 deploys / dayYesvercel.json
Netlify (Free)Up to 15 GB (300 credits, 20 per GB)15 credits per production deployYesnetlify.toml, _headers
Cloudflare Pages (Free)Unmetered500 builds / monthYes_headers
Your own Nginx / CaddyWhatever the box hasYou copy filesYou configure itNothing; it is a folder

Source: Vercel — Hobby plan · Netlify — Pricing · Cloudflare Pages — Limits · Cloudflare Pages

Bandwidth before you pay, in GB per month

ItemValue
Framer Free1 GB
Framer Basic50 GB
Framer Pro100 GB
Vercel Hobby100 GB
Netlify Free15 GB
Framer's tiers next to the static hosts' free tiers, as listed on 28 Sep 2026. Netlify's bar is the most its 300 free credits buy if nothing else spends them. Cloudflare Pages is not on the chart because it does not meter bandwidth on any plan.

Source: Framer — Pricing · Vercel — Hobby plan · Netlify — Pricing

What is in the export, so you do not write it twice

The sanitized ZIP holds the site with its mirrored hosts folded into assets/{css,js,img,fonts,media,data}, every reference rewritten to match, plus vercel.json (cleanUrls, no trailing slash), netlify.toml, a _headers file Netlify and Cloudflare Pages both read, and a README written for someone who has never deployed anything. Each host reads only its own file and ignores the others, and none of them declare a build step, because there is nothing to build.

The one thing worth knowing about the Vercel config is the cache policy. Captured assets are not content-hashed -- the pipeline names them into sequential slots like script-007.js -- so a header of immutable would leave returning visitors on stale JavaScript after a recapture. The export uses max-age=0, s-maxage=31536000, stale-while-revalidate instead: the edge caches for a year and a redeploy purges it, while the browser revalidates with a cheap 304. Same speed, no stale-forever failure mode.

vercel.json, as exported

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "cleanUrls": true,
  "trailingSlash": false
}
cleanUrls serves /about for about.html; trailingSlash: false keeps the URLs Framer had. Nothing else is required for a static import.

Source: Vercel — Project configuration (vercel.json)

Which file each host reads

Vercel
vercel.json — cleanUrls: true, trailingSlash: false
Netlify
netlify.toml and _headers
Cloudflare Pages
_headers — 20,000 files per site and 25 MiB per file on the free tier
Nginx, Caddy, S3
Nothing — it is a folder — Correct MIME types and a try_files rule are the whole configuration

All three ship in the same ZIP and none of them declares a build step. You are not choosing a host at export time; you are choosing one at import time.

Source: Vercel — Project configuration (vercel.json) · Cloudflare Pages — Limits · Cloudflare Pages

Deploying to each host, without a CLI

  1. Vercel

    Unzip, push the folder to a private GitHub repository (the web uploader is fine), then vercel.com/new → Import → Deploy with the defaults. The README in the ZIP walks this in eleven clicks. Every push to the repository redeploys.

  2. Netlify

    app.netlify.com → Sites → drag the unzipped folder onto the drop zone. netlify.toml sets publish = "." and an empty build command; _headers adds nosniff, a referrer policy and SAMEORIGIN framing.

  3. Cloudflare Pages

    Workers & Pages → Create → Pages → Upload assets, then drag the folder. Or connect the GitHub repository with no build command and / as the output directory. _headers is read as-is.

  4. Your own server

    Copy the folder to /var/www/site and use the Nginx block below. Caddy is two lines: root * /var/www/site and file_server. Either way, HTTPS is a certbot or automatic-TLS step you do once.

Nginx for a captured site

server {
  listen 443 ssl http2;
  server_name example.com;
  root /var/www/site;
  index index.html;

  location / {
    try_files $uri $uri.html $uri/ =404;
  }

  location /assets/ {
    add_header Cache-Control "public, max-age=0, s-maxage=31536000, stale-while-revalidate=86400";
  }

  gzip on;
  gzip_types text/css application/javascript image/svg+xml application/json;
}
try_files makes /about resolve to about.html the way cleanUrls does on Vercel. The asset block mirrors the export's edge policy: long cache on the CDN, cheap revalidation in the browser.

The domain moves last

The cutover, on a clock

  1. Lower the DNS TTL

    · Before anything — Drop the record's TTL to 300 seconds a day ahead. Everything else in this list is fast; DNS is the part that is not, and it is the part you cannot hurry once it has started.

  2. Deploy to the host's preview URL

    — Import the folder, let the host give you its own *.vercel.app or *.pages.dev, and walk every route there. This is the last moment a mistake costs nothing.

  3. Repoint the record

    · The switch — Change the A or CNAME record to the new host and let the certificate issue. Keep the Framer site published — you are changing where the domain points, not deleting anything.

  4. Verify from a network you do not control

    — A phone on mobile data, or any resolver that has not cached the old answer. Check the certificate, then walk the routes again.

  5. Unpublish the original

    · Only now — Once the old TTL has expired everywhere and the logs show traffic arriving at the new host. Until then the old site is your rollback, and a rollback you deleted is not one.

Prove it stands alone before you touch DNS

  • In the unzipped folder: python3 -m http.server 8080, open http://127.0.0.1:8080.
  • DevTools → Network → throttle Offline, then hard-reload. The page should render fully: images, fonts, styles.
  • Clear the throttle and filter the request list with -domain:127.0.0.1. Anything left is a dependency you still have on somebody else's server.
  • Walk every route from the sitemap, at 1280 / 1024 / 390 px.
  • Submit each form once on the deployed preview and confirm where it went.

Source: Chrome DevTools — Network reference

Updating it later

A self-hosted site is only a burden if every change is a migration. Two things keep it a chore instead: version history (every save is atomic, with a reachable version zero and named checkpoints, so a bad edit is a restore, not a rollback ritual) and Source Sync, which recaptures the Framer origin and reapplies your edits. After either, export again and redeploy the same way you did the first time.

Sources

  1. Vercel — Hobby plan — Included usage (100 GB Fast Data Transfer), 100 deployments a day, non-commercial use only. Read 28 Sep 2026.
  2. Netlify — Pricing — Credit-based plans: Free is 300 credits a month; bandwidth costs 20 credits per GB and a production deploy 15. Read 28 Sep 2026.
  3. Cloudflare Pages — Limits — Files per site, file size and builds per month (page updated 5 Sep 2026). Read 28 Sep 2026.
  4. Cloudflare Pages — “All plans come with unlimited sites, seats, requests, and bandwidth.” Read 28 Sep 2026.
  5. Framer — Pricing — Site plans, bandwidth and page limits as listed on 28 Sep 2026, yearly billing.
  6. Vercel — Project configuration (vercel.json) — cleanUrls, trailingSlash, headers. Read 28 Sep 2026.
  7. Chrome DevTools — Network reference — Filtering requests by domain, the Offline throttle.

FAQ

Can I move a Framer site to my own server?

Yes. The capture is portable static content -- HTML, CSS, JS and assets -- and the Nginx block on this page is all a VPS needs. Caddy is two lines.

Which free tier should I pick?

For a personal site any of the three. For a client site, Vercel's Hobby terms exclude commercial use, so use Vercel Pro, Netlify, or Cloudflare Pages, whose free plan does not meter bandwidth.

Will I lose the fonts or the mobile layout?

No. Fonts are localized under assets/fonts and the three breakpoints are captured as Framer serves them; the self-hosted copy matches the live responsive site.

Do I need to rebuild anything on the host?

No. None of the config files declare a build step. It is a finished static site; the host only has to serve it.

How do I update it later?

Edit in Live Edit or run Source Sync, then redeploy the same folder the same way.

Features · Workflow · Pricing · FAQ