A Netlify alternative for sites you already build yourself
Same atomic deploys, previews and rollback. No build system in the middle, and a price that is a number rather than a meter.
Netlify is a build platform. You connect a repository, it runs your build on its infrastructure, and the output is deployed — plus functions, forms, identity and an expanding surface around them. If you want a git push to turn into a built, server-rendered site without owning a pipeline, that is genuinely what it is for, and it is good at it.
One9x Pages starts one step later. Your build already ran — on your laptop, in CI, or inside an agent — and what you have is a folder. Pages takes the folder. That single decision is where every difference below comes from: there is no build queue to wait in, no build minutes to run out of, and no build image whose Node version you have to keep negotiating with.
Where the two actually differ
Structural differences only — what each product fundamentally is. No plan names and no prices for Netlify, because those change without telling us and a stale number here would mislead exactly the person who came to check one.
Who runs the build
One9x Pages
You do, wherever you already do — laptop, GitHub Actions, any CI, or an agent. We never see your source.
Netlify
Netlify does, on its infrastructure, from a connected repository.
What a deploy costs
One9x Pages
Nothing beyond your plan. There are no build minutes, because there is no build.
Netlify
Build time is a metered resource on top of the plan.
Bandwidth
One9x Pages
Not metered and not billed. The plan price is the price.
Netlify
Metered, with overage above the plan allowance.
Deploying without a repo
One9x Pages
First-class. Drag the folder onto the dashboard, or point the CLI at it.
Netlify
Possible via drop/CLI, but the product is built around the Git connection.
Push-to-deploy
One9x Pages
Our GitHub Action: build in Actions, stage a preview on every PR with the URL commented, publish on merge.
Netlify
Built in — the connected repo is the trigger.
Rollback
One9x Pages
A pointer flip to any kept release. Instant, no rebuild, no cache purge.
Netlify
Publish an earlier deploy — quick, though the platform still owns the artifact.
What you are buying
One9x Pages
Static hosting. One product, and the roadmap is published.
Netlify
A platform — functions, forms, identity, AI gateway, agent runners.
When to stay on Netlify
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.
- You want push-to-deploy with nothing to configure. Netlify connects to your repo in its own UI and builds from there. Ours is a workflow you add to the repo — a GitHub Action on GitHub, a few lines of shell on any other CI. That is a file you now maintain, and more so if your code is not on GitHub.
- You use Netlify Functions, Identity or Edge Functions. Pages serves static files: we have forms, but nowhere for you to put code that runs on a request.
- You need server-side rendering for Next.js, Nuxt or SvelteKit. We host the static export of those frameworks, which is not the same product.
Moving a site from Netlify
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 Netlify | Here |
|---|---|
netlify.toml → [build] publish | The directory you hand to the deploy. Nothing to declare. |
[build] command | Runs in your own CI. The GitHub Action workflow is where it goes. |
_redirects with /* /index.html 200 | --spa. The SPA fallback is the one redirect rule that has a direct equivalent. |
A 404.html Netlify picks up by convention | --error 404:/404.html, naming the exact path in your build. |
Netlify Forms (netlify attribute on a form) | Forms — define the fields in the dashboard and paste the HTML it generates. |
| Build environment variables | Repository secrets in your CI. They never reach us; the build happens before we see anything. |
| Deploy previews on pull requests | The Action stages a release per PR and comments the URL. |
| Files you did not want deployed | --exclude, repeatable, glob-matched. |
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.
- Redirect and rewrite rules. Anything in
_redirectsor[[redirects]]beyond the SPA fallback — vanity URLs, proxying a path to an API, country splits — has nothing to map to. Move them into your build as real files, or into your DNS/app, before you cut over. - Custom response headers. There is no
_headersequivalent. Caching is handled for you — content-addressed and immutable — but a CSP or a customX-header you set today will not survive the move. - Functions, Identity and Edge Functions. Static files only. Whatever they do has to live somewhere else before the domain moves.
The order to do it in
-
STEP 01
Read your config before you touch anything else
Opennetlify.toml,_redirectsand_headersand sort every rule into "maps to something" and "does not". The table above is the mapping. This is the step that decides whether the move is an afternoon or a rewrite, and doing it last is how people find out too late. -
STEP 02
Run the build yourself
Take the command out of[build]and run it locally. You should get the same publish directory Netlify would have deployed — if you do not, fix that here rather than in CI.locally$ npm ci && npm run build $ ls dist -
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 once by hand and open the preview
Add--spaonly if your_redirectshad the/* /index.html 200line. Without--deploythe release stages: fully uploaded, nothing live, its own URL. Click through it — especially any path that used to be a redirect.first deploy$ one9x pages release ./dist --site mysite --error 404:/404.html ✓ v1 staged → https://v1--mysite.one9x.app/ -
STEP 05
Swap the deploy step in CI
If you deploy through Netlify’s Git integration there is no workflow to change — you are writing your first one, and GitHub Actions has it in full. If you already deploy from Actions, it is one step out and one step in; your build steps do not move.before- uses: nwtgck/actions-netlify@v3 with: publish-dir: ./dist production-deploy: ${{ github.ref == 'refs/heads/main' }} env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}after- uses: one9x/pages-deploy@v1 with: site: mysite dir: dist token: ${{ secrets.ONE9X_TOKEN }} # the one line that decides preview vs live deploy: ${{ github.ref == 'refs/heads/main' }} comment: true -
STEP 06
Cut the domain over
Lower the TTL on the records you are about to change to 300, a day ahead — this is the step everyone skips and then waits four hours for. Then link the domain here, add the TXT and CNAME/ALIAS records we print, and wait for the certificate. Leave the Netlify site running until traffic is actually on us. -
STEP 07
Decommission
Once the domain is serving from here and you are happy, delete the Netlify site rather than leaving it to renew quietly. Removenetlify.toml,_redirectsand_headersfrom the repo in the same commit, so nobody later reads them as live configuration.
Your live site on Netlify 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.