I've had success using the browsable artifacts for this purpose. In your example, you would create a job for your develop branch and set the PUBLIC_URL to the path on gitlab.io where the job's artifacts are published:

develop:
    artifacts:
        paths:
          - public

    environment:
        name: Develop
        url: "https://$CI_PROJECT_NAMESPACE.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html"

    script: |
        # whatever

    stage: deploy

    variables:
        PUBLIC_URL: "/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public"

Setting the environment as indicated produces a »Review app« link in relevant merge requests, allowing you to get to the artifacts with a single click.

Note: if your repository is in a subgroup, you need to insert the subgroup name in two places above above between /-/ and $CI_PROJECT_NAME for the resulting URLs to work.

Answer from joki on Stack Overflow
Top answer
1 of 6
48

I've had success using the browsable artifacts for this purpose. In your example, you would create a job for your develop branch and set the PUBLIC_URL to the path on gitlab.io where the job's artifacts are published:

develop:
    artifacts:
        paths:
          - public

    environment:
        name: Develop
        url: "https://$CI_PROJECT_NAMESPACE.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html"

    script: |
        # whatever

    stage: deploy

    variables:
        PUBLIC_URL: "/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public"

Setting the environment as indicated produces a »Review app« link in relevant merge requests, allowing you to get to the artifacts with a single click.

Note: if your repository is in a subgroup, you need to insert the subgroup name in two places above above between /-/ and $CI_PROJECT_NAME for the resulting URLs to work.

2 of 6
35

It is possible to keep several pages published for different pipelines/branches.

To do that you need to copy your pages content (basically test report, or whatever needs to be published) to specific unique directory in public folder. For example, the name of the directory can be the id of pipeline (CI_PIPELINE_ID). So the path to pages sources would be like public/$CI_PIPELINE_ID/.

Then the whole public folder should be defined as artifacts with specific unique name (here again "$CI_PIPELINE_ID" can be used).

Unique name for artifacts is needed to not override the artifacts with the next pipeline execution (if name is not specified, the default name will be taken https://docs.gitlab.com/ee/ci/yaml/#artifactsname).

Then you can access the published report via the link:

https://yourGitlab/yourNamespace/yourProjectName/{CI_PIPELINE_ID}/index.html

, that means you can access all your saved reports by changing the pipeline id.

My example:

stages:
  - publish

cache:
  # Required to keep artifacts from old builds, e.g. from master
  paths:
    - public

pages:
  stage: publish
  script:
    - mkdir -p public/$CI_PIPELINE_ID
    - cp target/site/allure-maven-plugin/* public/$CI_PIPELINE_ID/ -R
  artifacts:
    name: "$CI_PIPELINE_ID"
    paths:
      - public
    expire_in: 5 days
  when: always
🌐
Reddit
reddit.com › r/gitlab › per-branch gitlab pages
r/gitlab on Reddit: Per-branch GitLab Pages
June 30, 2019 -

Hey, so I haven't actually been a HPC systems engineer in years so apologies if this is quite a basic question... :)

Does anyone have experience setting up GitLab Pages to deploy per branch? The use case would be preview builds for merge requests. I have Pages working in a GitLab CI script for a master branch in a test repo, and I have preview builds linked from GitLab MRs ('View app' button) deploying to an S3 bucket with Jenkins totally separately. It would be ideal if we could just use GitLab CI for everything.

Any help appreciated; apologies if I haven't been clear anywhere and happy to try to clarify if needed.

🌐
Reddit
reddit.com › r/gitlab › creating multiple gitlab pages for a project
r/gitlab on Reddit: Creating multiple GitLab pages for a project
July 25, 2024 -

I am currently working in a project hosted on the SaaS GitLab with the premium subscription.

For one project, we need to host multiple pages of documentation generated in the project.
I have looked into GitLab pages and been able to setup for the main branch, but I can't seem to find a way to make pages for multiple branches. There does not seem to be alot about it in the documentation and every Stackoverflow answer seems to be a very hacky way of achieving it (none of them have worked for me).

Is it currently possible to host multiple GitLab pages for a repository?

We also need to share the links to these pages and I can see it includes a long ID number in the URL.
Can this ID or the URL for the page change? If so, when would this happen?

🌐
DEV Community
dev.to › zenika › gitlab-pages-preview-the-no-compromise-hack-to-serve-per-branch-pages-5599
🦊 GitLab Pages per Branch: The No-Compromise Hack to Serve Preview Pages - DEV Community
March 20, 2026 - In this article, we will get around the limitation by taking advantage of the cache mechanism, and be able to display per-branch content, with the side benefit of obfuscating the path to ephemeral branches content, if desired. ... We assume you already have a way of generating your HTML static content, and just want to serve the files using GitLab Pages. For the code to work, your cache must be centralized, either by using gitlab.com runners, by having a single runner, or by sharing caches between multiple private runners.
🌐
GitLab
forum.gitlab.com › gitlab ci/cd
With GitLab Pages and CI/CD, how do you build different branches to different (sub-)directories? - GitLab CI/CD - GitLab Forum
August 6, 2020 - [This is a duplicate of https://stackoverflow.com/questions/63281252/with-gitlab-pages-and-ci-cd-how-do-you-build-different-branches-to-different-s, where I’ll also post the solution if one exists/materializes :grimacing…
🌐
GitLab
gitlab.com › gitlab.org › #16208
Multiple version Pages support (#16208) · Issues · GitLab.org / GitLab · GitLab
Description Is it possible to have multiple GitLab Pages generated based on branches or tags? For example, have the...
🌐
GitLab
forum.gitlab.com › gitlab ci/cd
Modfy the deployed GitlabPages in CI rather than replacing them - GitLab CI/CD - GitLab Forum
December 3, 2021 - I have a repo with testcases that are run using CI. The testreport (a static HTML Site) gets deployed to pages. Since the testcases differ on each branch I wanted to have reports for multiple branches availiable. I thought the runner automatically gets the currently deployed pages folder, so I used / by placing the site in subfolders inside the pages folder.
🌐
GitLab
docs.gitlab.com › gitlab docs › use gitlab › deploy and release your application › gitlab pages › parallel deployments
GitLab Pages parallel deployments | GitLab Docs
create-pages: stage: deploy script: - echo "Pages accessible through ${CI_PAGES_URL}" variables: PAGES_PREFIX: "" # no prefix by default (run on the default branch) pages: # specifies that this is a Pages job and publishes the default public directory path_prefix: "$PAGES_PREFIX" environment: name: "Pages ${PAGES_PREFIX}" url: $CI_PAGES_URL rules: - if: $CI_COMMIT_BRANCH == "staging" # ensure to run on the default branch (with default PAGES_PREFIX) variables: PAGES_PREFIX: '_stg' # prefix with _stg for the staging branch - if: $CI_PIPELINE_SOURCE == "merge_request_event" # conditionally change the prefix on Merge Requests when: manual # run pages manually on Merge Requests variables: PAGES_PREFIX: 'mr-$CI_MERGE_REQUEST_IID' # prefix with the mr-<iid>, like `mr-123`
🌐
GitLab
gitlab.com › gitlab.org › #23323
Is there any possibility to have multiple gitlab pages urls for single project? (#23323) · Issues · GitLab.org / GitLab · GitLab
Each user will have a gitlab CI yml file to build the job and create pages with static html code. This html page could be different for each user. So, Every time when user commit changes a pipeline job should be executed and pages will be created for each user. That way each user can view their own changes. ex: user1.pages.example.com , user2.pages.example.com, user3.pages.example.com ... When I am working, I am doing multiple commits and each time pages are getting overridden by latest one.
Find elsewhere
🌐
GitLab
forum.gitlab.com › how to use gitlab
Pages for branches - How to Use GitLab - GitLab Forum
March 24, 2017 - Hello, I developed a website and I put it on GitLab. Then I used a template name ‘HTML’ for my “.gitlab-ci.yml”. Now I create a branche from master. In this branche I would to try what I want and create a page but not t…
🌐
GitHub
gist.github.com › donaldpipowitch › 2590b20520b2cf6ae01aab4f7b55f8fa
Use GitLab Pages to deploy a Storybook per branch · GitHub
🥳 Every job needs a script, but this job was just created to configure an environment." environment: name: storybook/$CI_COMMIT_REF_SLUG url: https://your-orga.gitlab.io/your-group/your-project/$CI_COMMIT_REF_SLUG/storybook/ on_stop: remove STORYBOOK only: - branches remove-storybook: stage: deployment cache: key: 'my-storybook' paths: - public script: - rm -rf "public/$CI_COMMIT_REF_SLUG/storybook" when: manual variables: GIT_STRATEGY: none # needed to prevent "Couldn't find remote ref" error environment: name: storybook/$CI_COMMIT_REF_SLUG action: stop # stage: pages (the stage name is cu
🌐
GitLab
gitlab.com › gitlab.org › gitlab foss › #35141
Multiple version Pages support (#35141) · Issues · GitLab.org / GitLab FOSS · GitLab
October 16, 2016 - Description Is it possible to have multiple GitLab Pages generated based on branches or tags? For example, have the...
🌐
GitLab
gitlab.com › gitlab.org › #10914
GitLab Pages Parallel Deployments (#10914) · Epics · Epics · GitLab.org · GitLab
## Technical details - Add `prefix` ... for the site versioning: Add a `pages_multiple_versions_enable` to `ProjectSetting`, where the user can enable/disable the multiple version of GitLab Pages....
🌐
Gitlab
k33g.gitlab.io › articles › 2020-07-23-GITLAB-PAGES-EN.html
🇬🇧 Every GitLab Page deserves a real CI/CD | K33G's website
So, it means that you can deploy a GitLab Page from a feature branch, without impacting your production page, in a new temporary environment 🤩
Top answer
1 of 2
5

Interestingly, it is possible to post from any branch, just not from any job.

To do this, I needed to make two changes:

  1. I need to know the current state of the published data
  2. I need to change directory based on the current branch

GitLab has the ability to cache folders. Generally this is used to speed up builds by caching downloaded drivers. There is no reasons I could not use this to store the public folder. This way when I make changes to staging, I will remember the state of the root application:

cache:
  paths:
  - public

The next trick would be to publish pages to the appropriate folder, depending on current branch being built. To do this, we can look to GitLab CI/CD Environment Variables; in particular:

  • CI_COMMIT_REF_SLUG: The current branch
  • CI_DEFAULT_BRANCH: the default branch (master)

Knowing these two values, we can do a bit of bash to determine the correct place to write the content to.

pages:
  stage: deploy
  script:
  - dir="$CI_COMMIT_REF_SLUG"
  - if [ "$CI_COMMIT_REF_SLUG" == "$CI_DEFAULT_BRANCH" ]; then dir=""; fi;
  - dir="public/$dir"
  - echo "Deploying to $dir"
  - mkdir -p $dir
  - cp -r www $dir
  artifacts:
    paths:
    - public
  only:
  - staging
  - master

Don't forget to limit pages to only staging and master.

WARNING

I'm not satisfied with this.

I think it would be better to maintain the cache somewhere completely different and copy them in at a later stage, but completely re-writing the public folder each time.

The current solution will build cruft over time, but the basic idea is sound.

2 of 2
0

You can only publish changes to GitLab pages through your master branch, just as you describe. The only thing that GitLab pages does though, is to put files in the public folder in the job called pages. These files can be whatever files that you want though, as long as you manage to get them to this folder through the GitLab job.

You could try something like this:

pages:
  ...
  script:
    - mkdir -p public
    - cp -r www public
    - git checkout origin/staging
    - mkdir -p public/staging
    - cp -r www public/staging

I haven't tested this, so please let me know if it doesn't work!

If you run a GitLab job, it usually has all of the git history of your repo. There are settings that changes this though, both in git and in GitLab, so you have to make sure that you always get all of your git history to the pages job. If you have a folder that hasn't been added to git, like public, git should not change anything in it when you checkout another branch.

I think that you should also be able to set up the GitLab pages job with a schedule, so that the pages job is run even if only the staging branch has been updated, but not the master branch.

🌐
GitLab
about.gitlab.com › blog › product › gitlab pages features review apps and multiple website deployment
GitLab Pages features review apps and multiple website deployment
April 9, 2025 - create-pages-deployment: # This job will create a pages deployment without path_prefix # when there is a commit to the default branch stage: deploy script: - npm run build pages: publish: dist rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH create-pages-review-app: # This job will create a pages deployment with a path_prefix # when there a merge request is created or updated. stage: deploy script: - npm run build pages: publish: dist path_prefix: 'mr-$CI_MERGE_REQUEST_IID' # Prefix with the mr-<iid>, like `mr-123` rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH environment: name: "Pages Review MR ${CI_MERGE_REQUEST_IID}" url: $CI_PAGES_URL · Congratulations, you’ve now set up MR review apps for your Pages site. The Parallel Deployments feature is also a useful tool if you maintain the documentation of multiple versions of your software simultaneously.
🌐
GitLab
gitlab.com › gitlab.org › #1130
multiple version Pages support (#1130) · Issues · GitLab.org / GitLab · GitLab
October 16, 2016 - Not sure if this is an issue or feature. Description Is it possible to have multiple GitLab Pages generated...
🌐
GitLab
gitlab.com › gitlab.org › #33822
Document how to support multi versions for docs using environments (#33822) · Issues · GitLab.org / GitLab · GitLab
October 10, 2019 - Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
🌐
CodeGenes
codegenes.net › blog › deploying-gitlab-pages-for-different-branches
How to Deploy GitLab Pages for Different Branches of Your React App — codegenes.net
For other branches, GitLab Pages serves content under / - /<project-name>/<branch-name>, so we set PUBLIC_URL to that subpath. artifacts: paths: - build/ preserves the React build output for the deploy job.
Top answer
1 of 1
2

Only one site is supported on these platforms. You cannot have separate sites for separate branches.

The only way you might do this without some sort of cache/artifact retrieval (as you mentioned is another option in your question) is to build all your branches at once when publishing your Pages site.

How exactly you do that depends on a lot of factors, including what tool(s) you're using to build your site and if they are context-dependent -- but it might look something like this in GitLab

pages:
  # fetch the whole repo
  # this logic can change if you're on a detached head, like an MR
  # so we account for that here
  before_script: | 
        if [[ -n "$CI_COMMIT_BRANCH" ]]; then  # branch pipelines
            git remote set-url origin "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
            git fetch origin
            git checkout $CI_COMMIT_BRANCH
        fi
        if [[ -n "$CI_MERGE_REQUEST_IID" ]]; then  # MR pipelines
            git remote set-url origin "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_MERGE_REQUEST_SOURCE_PROJECT_PATH}.git"
            git fetch origin
        fi
  script: |
        mkdir public
        branches=()
        # ref: https://stackoverflow.com/a/3847586/5747944
        eval "$(git for-each-ref --shell --format='branches+=(%(refname))' refs/heads/)"
        for branch in "${branches[@]}"; do
            git checkout "$branch"
            # build each branch and output to public directory
            # YOU implement this
            make build "$branch" -o "public/${branch}"
        done
  artifacts:
    paths:
      - public
  environment: # ensure outdated jobs are skipped
    name: pages # https://docs.gitlab.com/ee/ci/environments/deployment_safety.html#skip-outdated-deployment-jobs