← All playbooks
Hosting migration

GitHub Pages → Vercel

Import the same GitHub repo into Vercel, fix base paths that Pages needed, and move the custom domain with the DNS records Vercel shows you. Pages has no redirect table. Put redirects in vercel.json.

Typical timeline2 to 5 days4 to 8 hours active work
Statusneeds review
Source profileGitHub Pages limits and getting-started docs reviewed 2026-11-06
Destination profileVercel domain and vercel.json redirect docs reviewed 2026-11-06
Documentation date
Review window
Evidence6 sources
This route needs review.Use it as a planning baseline, then verify the dated sources and test with representative data before production.
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

GitHub Pages

Reasons to stay
  • Repository-native static publishing is simple and inexpensive for documentation and project sites
  • Managed deployments reduce infrastructure and release-management work
Reasons to leave
  • Static-only hosting lacks server-side functions, edge bindings, and advanced application controls
  • Runtime assumptions, platform services, and pricing models shape the architecture
New platform

Vercel

What gets better
  • Exceptional frontend previews and framework integration make releases fast and polished
  • Managed deployments reduce infrastructure and release-management work
What gets worse
  • Costs and proprietary platform features can grow rapidly with traffic and complexity
  • Runtime assumptions, platform services, and pricing models shape the architecture
Best of the move

Vercel: Exceptional frontend previews and framework integration make releases fast and polished. This removes a major source-side concern: Static-only hosting lacks server-side functions, edge bindings, and advanced application controls.

Worst of the move

What you lose: Repository-native static publishing is simple and inexpensive for documentation and project sites. What you inherit: Costs and proprietary platform features can grow rapidly with traffic and complexity.

Jump to a section
01At a glance

Know the shape of the move.

Transfer outcome11 features audited
Transfer outcome distributionClean transfer: 1, Partial transfer: 4, Manual rebuild: 5, Not transferred: 1.
Clean1
Partial4
Manual5
Lost1
Mapping route8 of 9 fields have a destination path

This timeline assumes

  • One Pages site built from a GitHub repo, either a user site or a project site. You can import that repo into Vercel.
  • GitHub's limits still apply until you leave: published sites up to 1 GB, deploys that time out after 10 minutes, a soft 100 GB of bandwidth a month, and a soft 10 builds an hour unless you publish with your own Actions workflow.
  • The site already documents GitHub Pages → Netlify and GitHub Pages → Cloudflare Pages.
  • You want static hosting plus redirects. Serverless functions are new behavior, not something Pages had.
  • DNS changes wait until a Vercel preview matches the pages you care about.
02What transfers

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
The Git repo and the buildpartialcriticalVercel builds from the GitHub repo on push to the production branch. Pages may have been Jekyll, a static folder, or an Actions workflow. The build command has to be the one that actually produces the site.Set the framework and the output directory from the preview. Do not assume Vercel guesses a custom Actions build.
Project-site base pathmanualcriticalA project site is served under username.github.io/repo. Vercel serves the project at the domain root. A Next.js site that set output export, basePath, and unoptimized images for Pages needs those settings removed or the paths 404.Open the config, remove the Pages-only base path, and click through the preview.
Custom domainmanualcriticalPages stores the domain in the repo settings and often a CNAME file. Vercel wants the records from the project. Apex domains use an A record to the project IP Vercel shows. Subdomains use a CNAME to that project's target. Vercel says the DNS spec does not allow a CNAME on the apex, and it prefers www plus a redirect.Add the domain in Vercel first. Copy the records it shows. Remove the Pages custom domain so the two hosts do not fight over the certificate.
HTTPSpartialhighBoth hosts issue certificates after DNS is right. Enforcement on Pages does not carry over. Vercel provisions the certificate once the records verify.Request the main URLs over HTTPS after DNS. Do not turn off Pages until that works.
RedirectsmanualhighPages cannot host a server redirect table. Vercel reads a redirects array in vercel.json. permanent true is a 308. permanent false is a 307. Use statusCode when you need a 301.Put old paths in vercel.json and request them on the preview.
Jekyll plugins and ActionspartialhighPages builds Jekyll for you, with its plugin limits, unless you already switched to Actions. On Vercel you set the Jekyll build yourself. A 2025 first-person note from Kyle Kirwan described moving a Jekyll blog and writing vercel.json with help from a terminal tool.Run the same build locally, then set that command on the project.
GitHub-only URLsmanualhighusername.github.io keeps working until you disable Pages. If you have no custom domain, readers stay on the github.io host unless you leave a stub that points at the new URL.Decide whether github.io should remain, redirect, or go dark. Pages will not 301 for you.
Bandwidth and build limitspartialmediumPages' soft caps are 100 GB a month and 10 builds an hour, and a deploy dies at 10 minutes. Vercel has its own plan limits. You are not escaping limits. You are changing them.Look at the plan before you move a busy site. A 1 GB published site is already at GitHub's published-site cap.
Private sourcecleanlowFree Pages user sites are public. Vercel can build from a private GitHub repo on its hobby plan. That is a real reason some people move. It is not a content migration.Make the repo private only after the Pages site is no longer how you publish.
Environment and formsmanualmediumPages has no server env vars or form backend. Anything you add on Vercel is new, including functions.Do not turn on functions as part of the DNS cut. Ship the same static site first.
AnalyticslostlowPages does not give you a traffic product. Kirwan's note said Vercel analytics showed which posts were read, which he did not get from Pages. Old traffic is still wherever you had put a script.Keep the existing analytics snippet. Treat Vercel Analytics as optional and separate.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
GitHub repoVercel projectautomaticImport the repo. Push to the production branch deploys.
Jekyll or static buildBuild command and output directorymanualMatch what you already run.
baseurl or basePathRoot of the Vercel domaintransformRemove the /repo prefix unless you still want it.
CNAME file and Pages domain settingProject domain plus DNSmanualUse the A or CNAME Vercel shows for this project.
Apex domainA record to the project IPmanualVercel recommends www as the CNAME and a redirect from the apex.
Old pathsvercel.json redirectsmanual308 if permanent is true. Set statusCode for a 301.
Actions workflowVercel buildtransformDo not expect Vercel to run the Pages workflow as-is.
github.io URLLeave, stub, or disablemanualPages will not emit a 301 by itself.
Pages password or commerce featuresNo destinationunsupportedGitHub says Pages is not for commerce or SaaS. Do not add that during this move.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Keep the repo, the DNS records, and a copy of the live HTML before you change the domain.

  1. Confirm the default branch and that you can push.
  2. Write down the Pages source: branch, folder, or Actions.
  3. Export the DNS zone, including whatever points at GitHub.
  4. Save the CNAME file if it exists.
  5. Crawl the important URLs.

Proof to capture: The DNS export, the Pages source setting, and the URL list.

Transformation · Vercel project import

Import the repo and match the build

Get a .vercel.app preview that looks like the Pages site.

  1. Import the GitHub repository.
  2. Set the build command and output directory.
  3. Remove a project-site base path if the preview URLs 404 under the root.
  4. Click the pages you listed. Do not add the custom domain yet.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · vercel.json and the Domains screen

Add redirects and then the domain

Keep old paths and move DNS once, with the records from this project.

  1. Add redirects. Use statusCode 301 when a 301 is what you want. permanent true is 308.
  2. Add the domain in the project. Read the A record for the apex and the CNAME for www from that screen.
  3. Remove the custom domain from Pages, and the CNAME file, in the same change as DNS.
  4. Verify in Vercel. DNS can lag. Verification failing means the records are not the ones it asked for.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Preview

Base path 404s

criticallikely likelihood

Project sites live under /repo. Vercel does not.

Consequence
Every asset 404s on an otherwise successful deploy.
Mitigation
Fix base path on the preview before DNS.

Stop if: CSS or posts 404 on .vercel.app.

DNS

Two hosts claim the domain

criticalpossible likelihood

A CNAME file and Pages custom-domain setting keep GitHub in the loop.

Consequence
The certificate or the site flaps between hosts.
Mitigation
Remove the Pages domain when you change DNS. Keep the old records written down.

Stop if: HTTPS fails after the change and you cannot say which host answered.

Routing

Redirects are 308 and you promised 301

mediumpossible likelihood

Vercel documents permanent true as 308.

Consequence
A checker flags the status you did not expect.
Mitigation
Set statusCode if you need 301. Test with a header request.

Stop if: A high-value URL returns a status you did not choose.

URLs

github.io still looks canonical

highlikely likelihood

Disabling nothing means both sites stay up.

Consequence
Search keeps the github.io URLs.
Mitigation
Decide, and if you cannot redirect, say so on the old home page.

Stop if: You needed a 301 and Pages is still the only host for those paths.

06Precise timeline

Do the work in this order.

Estimate forOne repo, one domain, a preview before DNS
Total elapsed2 to 5 days
Active work4 to 8 hours
BufferDNS and certificate checks can sit overnight. Do the preview on day one anyway.
01
Day 1Write down Pages and DNS1 day
02
Day 2Preview on vercel.app1 day
03
Day 3Add vercel.json redirects1 day
04
Day 4Attach the domain without switching DNS yet1 day
05
Day 5Change DNS and disable Pages1 day
  1. Day 1 · inventory

    Write down Pages and DNS

    1 hour active1 day elapsedNone waiting
    • Note the Pages source and the CNAME file.
    • Export DNS.
    • List the URLs that must keep working.
    Stop / go checkpoint

    Can you put DNS back?

    Go when: The current records are saved.

    Stop when: Nobody can edit DNS.

  2. Day 2 · preview

    Preview on vercel.app

    2 to 4 hours active1 day elapsedThe first build waiting
    • Import the repo.
    • Fix the build and the base path.
    • Click the URL list on the preview host.

    Depends on: inventory

    Stop / go checkpoint

    Does the preview match?

    Go when: The URL list returns the right pages and assets.

    Stop when: The build is red or assets 404.

  3. Day 3 · redirects

    Add vercel.json redirects

    1 hour active1 day elapsedA second deploy waiting
    • Add the redirects you listed.
    • Request them on the preview.
    • Confirm the status code.

    Depends on: preview

    Stop / go checkpoint

    Are the codes the ones you wanted?

    Go when: Each tested path redirects once, with the status you set.

    Stop when: A path loops.

  4. Day 4 · domain

    Attach the domain without switching DNS yet

    1 hour active1 day elapsedVercel shows the records waiting
    • Add the domain to the project.
    • Copy the A and CNAME it displays.
    • Do not change the live zone until the next phase.

    Depends on: redirects

    Stop / go checkpoint

    Do you have the project-specific records?

    Go when: The values are copied from this project, not from a blog post.

    Stop when: The domain is already attached to another Vercel account and you cannot verify it.

  5. Day 5 · cutover

    Change DNS and disable Pages

    1 hour active1 day elapsedDNS and the certificate waiting
    • Update DNS.
    • Remove the Pages custom domain and the CNAME file.
    • Request HTTPS on the real host.
    • Leave the repo in place.

    Depends on: domain

    Stop / go checkpoint

    Is Vercel the host?

    Go when: The domain verifies and the URL list passes on it.

    Stop when: HTTPS fails or Pages still answers the domain.

07The point of change

Cut over with a way back.

Go live

Cutover

Serve the custom domain from Vercel, with Pages no longer claiming that domain.

Recommended window: After the preview passes, with the DNS login in hand. Not during a launch if the site is the launch.

  1. Re-deploy the preview if the repo moved since you tested it.
  2. Change the live DNS records to the values on the Vercel domain screen.
  3. Remove the custom domain in Pages and delete the CNAME file in the same window.
  4. Run vercel domains verify, or use the dashboard, until it is valid.
  5. Request the URL list over HTTPS.

Proof to capture: Before and after DNS, the verify result, and the URL list on the real host.

Return to safety

Rollback

Point the domain back at GitHub Pages if the Vercel build or certificate is wrong.

Deadline: As soon as you see a bad host. DNS is the switch. The repo did not have to change.

  1. Restore the saved DNS records.
  2. Put the custom domain and the CNAME file back on Pages.
  3. Wait for GitHub's certificate again.
  4. Leave the Vercel project. It is not serving the domain.
  5. Fix the preview before you try DNS again.

Proof to capture: The domain serves Pages and HTTPS works there.

Rollback immediately when
  • The preview was never green and someone changed DNS anyway.
  • Assets 404 because of a base path.
  • Verify stays failed after the records you intended are in place.
  • A redirect loops on a URL you need.
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
BLD-01BlockingPreview deployOpen the latest production deploy on .vercel.app.The build is green and the home page renders.The deploy URL.
PATH-01BlockingNo /repo prefixRequest a post and a CSS file at the root.Both return 200.The two URLs.
URL-01BlockingURL listRequest the list you crawled from Pages.Each URL matches the old page or a redirect you listed.Status codes.
RED-01BlockingStatus codeRequest headers for two redirects.The code is the one you set, once, with no loop.The header output.
DNS-01BlockingRecords match the projectCompare the live zone with the Vercel domain screen.Apex and www match what that project asked for.Both copies of the records.
TLS-01BlockingCertificateOpen the real domain over HTTPS.The certificate is valid and the host is Vercel.The browser or curl result.
PGS-01BlockingPages released the domainRead the Pages custom-domain setting and the CNAME file.The domain is not still assigned to Pages.The setting.
GH-01Old host decisionRequest the github.io URL.It matches the decision you wrote: still up, stubbed, or disabled.The response.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: The custom domain has served Vercel for a few days and the URL list still passes.

  1. Keep the DNS export with the notes.
  2. Disable the Pages site if github.io should go dark.
  3. Leave the GitHub repo. Vercel is building it.
  4. Remove any Pages-only GitHub Actions workflow once you are sure you will not roll back.
  5. Set the next review date.
10Experiences from the field

When the plan met reality.

First-hand accounts are preferred. Vendor case studies are labeled, and every note below is an editorial paraphrase—follow the link for the full context.

First-person accountKyle Kirwan · Kyle Kirwan

Using Warp to move a Jekyll blog to Vercel2025

Kyle Kirwan says he moved his blog from GitHub Pages to Vercel a few weeks before 1 June 2025. He describes himself as not a developer, and says a terminal assistant set up vercel.json, ran the Jekyll build, handled the deploy, and walked through DNS while he watched each step. He reports that Vercel builds felt faster and more reliable, and that Vercel showed which posts were read, which he did not get from GitHub Pages. The post says it was written with that assistant's help.

What they recommend
  • Treat a Jekyll build command and vercel.json as the real work, even when a tool drafts them.
  • Check the preview before DNS. His note is about finishing the move, not about a redirect map.
Worth noticing
  • A small Jekyll site can leave GitHub Pages for Vercel in an afternoon once the build and DNS are clear.
  • He wanted analytics Pages did not provide, and he says the post itself was written with the same tool.
Sources and evidence

Verify against the primary material.

Platform behavior changes. Check these sources and the review dates above before executing a production migration.

  1. GitHub Pages: limitsAccessed 2026-11-06
  2. GitHub Pages: create a siteAccessed 2026-11-06
  3. GitHub Pages: manage a custom domainAccessed 2026-11-06
  4. Vercel: set up a custom domainAccessed 2026-11-06
  5. Vercel: redirects in vercel.jsonAccessed 2026-11-06
  6. Kyle Kirwan: moving a Jekyll blog from GitHub Pages to VercelAccessed 2026-11-06