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
-
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 -
STEP 02
Drop the path prefix
A project site served from/reponamecarries abaseurl(Jekyll),base(Vite, Astro) orbasePath(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: "" -
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) -
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/ -
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 thepages: write/id-token: writepermissions and thegithub-pagesenvironment block come out with them.before- uses: actions/configure-pages@v5 - uses: actions/upload-pages-artifact@v3 with: path: ./_site - uses: actions/deploy-pages@v4after- uses: one9x/pages-deploy@v1 with: site: mysite dir: _site token: ${{ secrets.ONE9X_TOKEN }} deploy: ${{ github.ref == 'refs/heads/main' }} comment: true -
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. -
STEP 07
Only now, turn Pages off
Delete theCNAMEfile 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..nojekyllcan 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.