For a small static or Jekyll site, GitHub Pages can provide staging and production without a separate hosting bill. The setup still needs careful boundaries. You need a source repository, a review site, a public site, a build workflow, and a clear promotion rule.
This site, jasonchance.com, is itself a Jekyll site published through GitHub Pages. The pattern here comes from working with a real static site workflow, not from an abstract deployment diagram.
A deployment workflow should make the safe action easy and the risky action deliberate.
The arrangement below uses GitHub Pages for both destinations and GitHub Actions to move generated output between repositories. It is practical for documentation sites, civic projects, small organization sites, and other static properties that do not need a server runtime.
Start With One Source Repository
Keep the Jekyll source in one repository. Use main as the staging and review branch, and use production as the public release branch.
The branch roles should be explicit:
main: The full site source used for development, review, and staging deployments.production: The source state approved for the public site.
Developers can work locally, run bundle exec jekyll serve, and push to main when outside feedback is useful. A pull request from main to production becomes the promotion step.
This is cleaner than maintaining two independent copies of the source. Templates, configuration, content, and dependency changes have one home. The production branch records which reviewed source state is public.
Use Separate Pages Repositories for the Built Sites
GitHub Pages publishes one site from a repository. A straightforward arrangement is:
example-site: the source repository containing the Jekyll project.example-staging: the deployment repository forstaging.example.com.example-production: the deployment repository forexample.com.
The source repository holds the code people review. The deployment repositories hold generated output. That separation prevents a staging build from becoming public simply because the build succeeded.
GitHub Pages supports custom workflows for static site generators, and Jekyll is supported as a static site generator [1] [2].
Make the Workflow Branch-Aware
The source repository can use one workflow with two branch paths.
On a push to main, the workflow should:
- Check out the source.
- Install the required Ruby and Jekyll dependencies.
- Build the site into
_site. - Publish
_siteto the deployment branch forexample-staging.
On a push to production, the workflow should repeat the build and publish the output to the deployment branch for example-production.
The result is easy to explain: main updates staging, and a merged promotion pull request updates production. GitHub’s Pages workflow documentation supports separate build and deployment jobs, which is useful when the build artifact and publishing target need to be treated as separate steps [1].
Promote With a Pull Request
Do not promote by copying generated files from one repository to another by hand. Open a pull request from main to production, review the source changes, merge it, and let the production branch trigger its deployment.
This gives the release a visible approval point. The pull request can include content review, link checks, accessibility checks, and a record of who approved the public change.
Use a Narrow Cross-Repository Credential
When the source workflow publishes to a separate deployment repository, it needs credentials that can write there. Store the credential as an Actions secret, never in the workflow file or generated site [3].
Use a fine-grained personal access token or GitHub App installation with access limited to the required deployment repository and permissions. A token that can write every repository in an account is too broad for a job that only needs to publish static files [4].
If the workflow only needs to publish staging from main, the staging credential should not also be the production credential. Separate access makes a mistaken branch condition less damaging.
Protect the Production Environment
Create a production environment and allow only the production branch to deploy to it. A job that references an environment must satisfy that environment’s protection rules before it can access environment secrets or continue [5].
This is a useful second line of defense. The workflow condition says which branch should run the production job. The environment policy says which branch is allowed to use the production deployment target.
Configure the Domain and HTTPS
GitHub Pages gives each deployment a default github.io address. A custom domain such as example.com or staging.example.com still needs DNS records and repository configuration. GitHub documents the required DNS and HTTPS steps, including domain verification [6].
DNS is part of the deployment. A workflow can publish files successfully while the public domain still points somewhere else, has a stale record, or is waiting for certificate provisioning. Test the default Pages address and the custom domain separately.
Understand the Free Plan Limits
This approach can avoid a separate hosting bill, but GitHub Pages is not private hosting and it is not an application server.
On GitHub Free, Pages is available from public repositories. The repository source and the published site should be treated as public. GitHub Pages does not provide built-in password protection for an ordinary public site. GitHub Pro includes Pages for private repositories, but private Pages publishing requires an organization using GitHub Enterprise Cloud [7].
There are also structural limits:
- one user or organization Pages site per account,
- one project Pages site per repository,
- a published site limit of 1 GB,
- a 10-minute deployment timeout,
- and soft bandwidth and build limits.
Custom workflows do not remove the storage, deployment, or bandwidth limits, although the standard 10-builds-per-hour limit does not apply when you build and publish with a custom Actions workflow [8].
GitHub Pro can be a good-value option when a small team needs Pages connected to private source repositories or expects to manage several simple public project sites. It does not turn a Pages site into a password-protected private application, and each site still needs its own repository and domain arrangement.
Know What Pages Cannot Run
GitHub Pages serves static output. It can host Jekyll-generated HTML, CSS, JavaScript, images, feeds, and other build artifacts. It cannot run server-side Ruby or PHP, hold a database connection, process private form submissions, or provide application sessions.
If the site needs those features, keep the static front end on Pages and put the server-side component on a service designed to run it. Do not treat a static deployment repository as a place to hide credentials or private data [9].
The Simpler Two-Repository Alternative
You can also keep separate source repositories:
example-staging-sourcefor review work,example-production-sourcefor the public site.
That model is easier to understand at first, but it creates two copies of the source. Content, layouts, dependencies, and configuration can drift. Every shared change has to be synchronized, and a production fix can be forgotten in staging or vice versa.
Two source repositories make sense when the sites are genuinely different products or need different ownership. For one site with two release states, one source repository with main and production branches is usually cleaner.
Questions to Ask Before You Build
Is the source repository allowed to be public? If not, GitHub Free is the wrong assumption for Pages.
Do we need a server runtime or database? If yes, Pages can host only the static portion.
Which branch is allowed to publish production? Write the rule into both the workflow and the environment policy.
What can the cross-repository credential write? Limit it to the deployment repository and the smallest useful permissions.
Do we need two source repositories? Use them only when the sites are truly separate products, not because staging and production need different URLs.
Bottom Line
GitHub Pages can provide a useful staging and production arrangement for a static or Jekyll site at little infrastructure cost. The reliable pattern is one source repository, a review branch, a production branch, separate deployment repositories, branch-aware Actions, and promotion through a pull request.
The free option has real limits. Public source, public sites, DNS work, no server-side runtime, and cross-repository credentials are all part of the decision. Once those constraints fit the project, the setup is straightforward and gives small teams a safer path from local development to public release.
Frequently Asked Questions
Yes. Use separate Pages repositories or sites, then have GitHub Actions build the source and publish the generated files to the appropriate deployment repository. The source branches determine whether the output is for review or public release.
No. GitHub Free supports Pages from public repositories. A public Pages site is public and does not provide built-in password protection. GitHub Pro supports Pages in private repositories, but private site access still requires the appropriate organization and Enterprise Cloud setup.
No. GitHub Pages hosts static output such as HTML, CSS, JavaScript, and generated Jekyll files. A site that needs a server runtime, private application logic, or a database needs a different hosting service for those parts.
References
- GitHub. (2026). Using Custom Workflows with GitHub Pages. GitHub. https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages
- GitHub. (2026). Setting Up a GitHub Pages Site with Jekyll. GitHub. https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll
- GitHub. (2026). Using Secrets in GitHub Actions. GitHub. https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets
- GitHub. (2026). Managing Your Personal Access Tokens. GitHub. https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
- GitHub. (2026). Managing Environments for Deployment. GitHub. https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments
- GitHub. (2026). Configuring a Custom Domain for Your GitHub Pages Site. GitHub. https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site
- GitHub. (2026). GitHub’s Plans. GitHub. https://docs.github.com/en/get-started/learning-about-github/githubs-plans
- GitHub. (2026). GitHub Pages Limits. GitHub. https://docs.github.com/en/pages/getting-started-with-github-pages/github-pages-limits
- GitHub. (2026). What Is GitHub Pages?. GitHub. https://docs.github.com/en/pages/getting-started-with-github-pages/what-is-github-pages





