Hosting your Flutter web app on GitLab Pages

(GitLab, not GitHub)

Danielle H
5 min readMar 29, 2024

You’ve got a great Flutter web app, that does something and does it well. It doesn’t need a server, you just want to host it somewhere, for free, so that all the world can revel in its goodness. You hear that it can be done in GitLab — what a coincidence, the code is already in GitLab! So you’re ready to go, right?

…Right?

I’ve seen so. Many. Tutorials on how to host a Flutter web app on GitHub pages, but the few I found on GitLab were out of date (though they were still useful! Thanks especially to

).

So here it is: The step by step tutorial on how to host your app in GitLab.

  • Create your app and run it locally
  • Create the gitlab-ci file
  • Run pipeline to create your site

Check out the repo here and the live site here.

Create your app

If you don’t already have an app, create it. For the purpose of this tutorial, you can use the default Flutter app.

Run it on your computer, being sure to choose “Chrome” as your device. It will open the app in Chrome. Make sure that it runs and works.

Push it to a GitLab repo.

Did you know that it’s really easy to create a repo in Gitlab by pushing a new project?

From within your root project directory:

First create your local repository

git init

git add *

git commit -m "initial commit"

And then push your local project in order to create a new project in GitLab:

git push --set-upstream git push --set-upstream https://gitlab.example.com/namespace/myproject.git master

Or in my case:

git push --set-upstream https://gitlab.com/dsavir/flutter-web-gitlab.git main

And to make it easier to push in the future:

git remote add origin  https://gitlab.com/dsavir/flutter-web-gitlab.git

Gitlab-ci

The magic happens here. The gitlab-ci.yml file is a file written in yml, with simple instructions for GitLab’s CI-CD framework (Continuous integration, continuous deployment). This is a framework for running automated tasks, like running tests and also publishing pages.

However, all these tasks are run on the cloud, in a container. A container is an environment that holds all that is necessary to run your web app, no more and no less. On the one hand, it sounds as though it’s simple. However, it has to include the entire flutter framework and all its dependencies, as well as your code.

Container with Flutter web app. Inspired by this awesome Kubernetes video.

Create a file called .gitlab-ci.yml(note the . at the beginning!). The file should be in the root folder of your project, next to pubspec.yaml.

A great environment is supplied by cirrus labs, so you don’t have to build the entire environment by yourself:

build_and_test_web_app:
stage: build
image: ghcr.io/cirruslabs/flutter:stable

Here we’ve defined a build stage called build_and_test_web_app. This build and tests the app without deploying it, just to make sure that error aren’t published. So far, all we’ve done is define the environment (which is important!)

Once we have defined the environment, we need to actually run the tasks to deploy our app.

Let’s add the building commands:

build_and_test_web_app:
stage: build
image: ghcr.io/cirruslabs/flutter:stable
before_script:
- flutter pub get
script:
- flutter test
- flutter build web

Gitlab will automatically add your code, so you don’t need to checkout the code. But you do need to run pub get to install all your packages before running tests and build.

Once that is done, you can proceed to run tests (if you have any) and build the app.

Assuming everything goes well, you want to tell GitLab what are the results you want to deploy:

build_and_test_web_app:
stage: build
image: ghcr.io/cirruslabs/flutter:stable
before_script:
- flutter pub get
script:
- flutter test
- flutter build web
artifacts:
paths:
- build/web

The above tells GitLab that we want to deploy the build/web folder.

Now to actually deploy it:

build_and_test_web_app:
stage: build
image: ghcr.io/cirruslabs/flutter:stable
before_script:
- flutter pub get
script:
- flutter build web
artifacts:
paths:
- build/web

pages:
stage: deploy
script:
- cp -r build/web public
artifacts:
paths:
- public

Here we’re creating a new deploy stage called pages. We tell GitLab to copy build/web into the public folder, and then publish the public folder.

As it is now, it will run every time anyone pushes any commit into any branch. To limit it to run only when someone pushes into a specific branch e.g. web, add the following:

build_and_test_web_app:
stage: build
image: ghcr.io/cirruslabs/flutter:stable
before_script:
- flutter pub get
script:
- flutter build web
artifacts:
paths:
- build/web

pages:
stage: deploy
script:
- cp -r build/web public
artifacts:
paths:
- public
only:
- web

Now commit and push the file into your repository.

You will see that the pipeline is run automatically (Build → Pipelines)

Where to find the Pipelines
See? Runs automatically. Doesn’t always pass though.

If everything runs as expected (does it ever really run as expected on the first try?) you can go to Deploy →Pages and find your page!

Hurray!

Troubleshooting

My pipeline doesn’t run at all

— Make sure that you are in the correct branch. The only statement can also have branch main, it doesn’t need to be a different branch than the main (or master).

— Make sure that you have pushed the .gitlab-ci.yml file into the repository.

— you can use the pipeline editor to check the syntax, visualize the pipeline and validate it.

My pipeline runs but fails

— Click on the “failed” button next to the pipeline. It will show you the stages of the pipeline (build and deploy). Click on the one that failed (usually the first one). It will show you the log output and show the exact error that caused it to fail (in my case, usually a failed test or the code wouldn’t compile). Fix the error or search for it on Stack Overflow.

Everything runs well but my page is blank

— This is usually a problem defining the root directory of the web page. In my case, it was because I followed old instructions, that instruct you to change the web/index.html file. Do not change anything in the file, leave as is. Especially make sure that base is defined:

<base href="$FLUTTER_BASE_HREF">

Good luck!

Full code here. See live web app here.

My heart grows heavier by the day. 174 days (almost 6 months!). #BringThemHomeNow.

Check out my free and open source online game Space Short. If you like my stories and site, you can also buy me a coffee.

--

--

Danielle H

I started programming in LabVIEW and Matlab, and quickly expanded to include Android, Swift, Flutter, Web(PHP, HTML, Javascript), Arduino and Processing.