switching from GitHub Pages

A GitHub Pages alternative for when the site is not a repo

Free, HTTPS, custom domains — but the site is a folder you deploy, not a branch you push.

GitHub Pages is hard to beat on price and it is where an enormous number of docs sites and portfolios live, deservedly. If your site is already a repository and you are happy with that, there is no problem here to solve.

The friction shows up at the edges. The site is a branch, so deploying means committing, and rolling back means reverting and waiting for a rebuild. Anything you would rather not publish — a client preview, an internal handbook — has to live in a repository whose visibility you may not control. And a folder that came out of a design tool or an AI agent has to be given a repo before it can be given a URL.

Where the two actually differ

Structural differences only — what each product fundamentally is. No plan names and no prices for GitHub Pages, because those change without telling us and a stale number here would mislead exactly the person who came to check one.

What you deploy

One9x Pages
A folder. From the dashboard, the CLI, CI, or an agent.

GitHub Pages
A branch or a workflow artifact in a repository.

Needing Git at all

One9x Pages
No. Git is one way in, not the way in.

GitHub Pages
Required — the repository is the deployment mechanism.

Rollback

One9x Pages
Pick an earlier release, flip the pointer. Instant, no rebuild.

GitHub Pages
Revert the commit and wait for the build to run again.

Seeing a change before it is live

One9x Pages
Every release gets its own preview URL, commented on the pull request by the GitHub Action, before you publish it.

GitHub Pages
No preview step — publishing is the merge.

Sites you do not want public

One9x Pages
A site is not a repository, so its source is not a visibility setting.

GitHub Pages
Tied to repository visibility and plan.

Deploy size and rate

One9x Pages
Per-plan limits, published on the limits page, checked before upload.

GitHub Pages
Soft site-size and build-frequency limits in the terms.

When to stay on GitHub Pages

Three cases where moving would cost you something we cannot give back. If one of them is yours, this is the wrong product and you should not have to read to the bottom of a sales page to find that out.

  • Your site is a Jekyll build that GitHub compiles for you. We do not build — you would add a workflow that runs Jekyll and deploys the output. That is a few lines with our GitHub Action, but it is a few lines you did not have before.
  • You are on the free plan, public, and happy. GitHub Pages costs nothing and our free plan is not cheaper than nothing.
  • Everything you publish belongs in the repo next to the code it documents. That is a good reason to keep it there.

Moving a site from GitHub Pages

What your configuration maps to, what has no equivalent at all, and the order to do it in. The middle one is the part that decides whether this is an afternoon.

What maps to what

On GitHub Pages Here
The gh-pages branch or /docs folder Nothing — you deploy a directory, not a branch.
Jekyll building your site for you A jekyll build step in your workflow, then deploy _site.
The CNAME file The domain is linked in the dashboard, not committed to the repo. Delete the file after you cut over.
.nojekyll Not needed. Nothing here processes your files.
baseurl / project-site path prefix Every site is served at the root of its own host, so the prefix comes out of your config.
A 404.html at the root --error 404:/404.html.
Deploying on push The GitHub Action — the repo stays where it is.
Repository visibility as the privacy control A site is not a repository. What you deploy is independent of who can see the source.

What has no equivalent

Handle these before you move DNS, not after. Pages serves files: it has an SPA fallback, custom error pages and an exclude list, and it has no redirect table and no custom response headers.

  • Jekyll running on the host. This is the real work of the move: the build becomes yours to run. For a default Jekyll site that is a handful of workflow lines; for a heavily plugin-dependent one, check it builds locally first.
  • The repo-is-the-site model. Anything that assumed committing publishes — a CMS writing to the branch, a bot opening content PRs — needs to route through the build instead.
  • Redirect rules and custom headers. Neither exists here; GitHub Pages has little of either, so this is usually a non-issue on this particular move.

The order to do it in

  1. STEP 01

    Get the build running outside GitHub Pages

    If GitHub was building Jekyll for you, that build becomes yours. Run it locally once and confirm the output — a site leaning on plugins the GitHub build whitelisted is better discovered now than in CI.
    locally
    $ bundle exec jekyll build
    $ ls _site
  2. STEP 02

    Drop the path prefix

    A project site served from /reponame carries a baseurl (Jekyll), base (Vite, Astro) or basePath (Next.js). Here the site is at the root of its own host, so that setting comes out — otherwise every asset URL keeps a directory that no longer exists.
    _config.yml
    -baseurl: "/reponame"
    +baseurl: ""
  3. STEP 03

    Create the site and a CI token

    A site has to exist before anything can deploy to it — the action will not create one, so a typo fails instead of quietly publishing to a new address. Do both from the dashboard if you prefer.
    once
    $ one9x pages create mysite
    ✓ created mysite → https://mysite.one9x.app/
    $ one9x tokens create "github actions"
    one9x_tok_7Kd…  (shown once)
  4. STEP 04

    Deploy the output folder

    Same folder GitHub was publishing, handed over directly. The release stages first, with its own URL, so you can compare it against the live Pages site side by side.
    first deploy
    $ one9x pages release ./_site --site mysite --error 404:/404.html
    ✓ v1 staged → https://v1--mysite.one9x.app/
  5. STEP 05

    Swap the deploy step in CI

    This is the whole change for most GitHub Pages sites. The repo does not move; only where it deploys to. Three official Pages steps become one, and the pages: write / id-token: write permissions and the github-pages environment block come out with them.
    before
    - uses: actions/configure-pages@v5
    - uses: actions/upload-pages-artifact@v3
      with:
        path: ./_site
    - uses: actions/deploy-pages@v4
    after
    - uses: one9x/pages-deploy@v1
      with:
        site: mysite
        dir: _site
        token: ${{ secrets.ONE9X_TOKEN }}
        deploy: ${{ github.ref == 'refs/heads/main' }}
        comment: true
  6. STEP 06

    Cut the domain over

    Lower the TTL a day ahead, link the domain here, publish the records we print, wait for the certificate. Do not touch the repo yet.
  7. STEP 07

    Only now, turn Pages off

    Delete the CNAME file and disable Pages in repository settings — in that order, and only after the domain is serving from here. Reversed, the domain is briefly claimed by two hosts and one of them wins at random. .nojekyll can go too; nothing here processes your files.

Your live site on GitHub Pages keeps serving throughout — nothing here touches it until you move DNS, and the free plan is enough to do the whole rehearsal first.

Try it with one site

The free plan takes three sites, no card, and does not expire. Deploy the folder you already have and see what it looks like before anything moves.