DEV Community

Nimblesite
Nimblesite

Posted on

Deploy a Flutter PWA on GitHub Pages (and Use a Custom Domain)

Flutter can build web apps that behave like native mobile apps, and you can deploy those Progressive Web Apps (PWAs) for free on GitHub Pages. You only need a few commands to get there. You can also buy a custom domain and hook it up so your app looks more professional. Here’s how to do it.


1. Create a Flutter Web Project

Make a new Flutter project or convert an existing one. If you don’t have Flutter installed, install it from the official Flutter docs.

flutter create my_pwa
cd my_pwa
Enter fullscreen mode Exit fullscreen mode

2. Enable Web Support

Flutter supports web out of the box now, but just double-check.

flutter config --enable-web
flutter doctor
Enter fullscreen mode Exit fullscreen mode

You should see Chrome, Edge, or other browsers listed under available devices.


3. Add PWA Assets

Flutter generates basic PWA support automatically when you run a web build. But if you want to customize icons or the manifest, look inside web/ and edit the manifest.json, favicon.png, etc.


4. Build for the Web

Run a release build for web:

flutter build web --release
Enter fullscreen mode Exit fullscreen mode

Flutter places the result in build/web. You can rename it if you want, but build/web works fine.

You can test your app by running this and then picking your browser.

flutter run
Enter fullscreen mode Exit fullscreen mode

5. Push to GitHub

Go to GitHub and create a new repo. Then, in your local project directory:

git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/your-username/my_pwa.git
git push -u origin master
Enter fullscreen mode Exit fullscreen mode

6. Deploy on GitHub Pages

GitHub Pages can serve any static files from a branch or a folder. A simple way:

  1. In your repo, go to Settings > Pages.
  2. Under Source, choose the branch (master or main) and set the folder to /docs or root.
  3. Move your build/web folder contents into a folder named docs (or whatever folder you picked).
   cd build/web
   cp -r * ../../docs
Enter fullscreen mode Exit fullscreen mode
  1. Commit and push again:
   cd ../../docs
   git add .
   git commit -m "Deploy PWA to GitHub Pages"
   git push
Enter fullscreen mode Exit fullscreen mode

Your app should appear at https://<your-username>.github.io/<repo-name>.


7. Hook Up a Custom Domain

You can purchase a domain from a registrar like Godaddy or Namecheap. In your repo’s Settings > Pages, you’ll see a section for Custom domain. Add your domain (like mycoolapp.com). Then create a CNAME file in your repo’s root (or docs folder) with the domain name inside.

Example CNAME file:

mycoolapp.com
Enter fullscreen mode Exit fullscreen mode

Follow the instructions from this GitHub documentation to configure the DNS settings in the registrar's DNS settings.


8. Verify Your PWA

Open your URL in Chrome and look in DevTools > Application. Check the Manifest and Service Worker sections. If everything looks right, your app can be installed like a native app.

You can install the app on your desktop as an icon by tapping the install button in the URL bar.


9. Check the Config

If you have any issues with deploying your app, you can see an existing example. The Flutter Material Design Seed Color picker is an app that helps you select a Material Design 3 seed color for your app. This is the example index.html

See the original here.

<!DOCTYPE html>
<html>
<head>
  <base href="$FLUTTER_BASE_HREF">

  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <meta name="description" content="A tool for time boxing with AI">

  <!-- iOS meta tags & icons -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="temporalo">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

  <!-- Favicon -->
  <link rel="icon" type="image/png" href="favicon.png" />

  <title>temporalo</title>
  <link rel="manifest" href="manifest.json">
</head>
<body>
  <script src="flutter_bootstrap.js" async></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  1. Deploy WebAssembly Version

You can go a step further build and deploy your app as a Wasm app. This improves the performance of the Flutter app

Here is an example Github Actions script. You can get the original here.

name: Deploy to GitHub Pages

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

permissions:
  contents: write
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          ref: ${{ github.ref }}
          fetch-depth: 0

      - name: Setup Flutter
        uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.29.0'
          channel: 'stable'
          architecture: x64

      - name: Enable WASM
        run: flutter config --enable-web

      - name: Get dependencies
        run: flutter pub get

      - name: Build WASM
        run: flutter build web --wasm --release --base-href "/${{ github.event.repository.name }}/"

      - name: Update COOP and COEP headers
        run: |
          echo '{
            "headers": [
              {
                "source": "**/*",
                "headers": [
                  {
                    "key": "Cross-Origin-Embedder-Policy",
                    "value": "credentialless"
                  },
                  {
                    "key": "Cross-Origin-Opener-Policy",
                    "value": "same-origin"
                  }
                ]
              }
            ]
          }' > build/web/_headers

      - name: Setup Pages
        uses: actions/configure-pages@v4

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: 'build/web'

      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

      - name: Get Version
        id: version
        run: |
          VERSION=$(grep 'version:' pubspec.yaml | sed 's/version: //')
          echo "VERSION=$VERSION" >> $GITHUB_ENV

      - name: Create GitHub Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Configure git
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          git config --global user.name "github-actions[bot]"

          # Create tag
          TAG_NAME="v${VERSION}"
          git tag "$TAG_NAME"
          git push origin "$TAG_NAME"

          # Create release
          gh release create "$TAG_NAME" \
            --title "v${VERSION} Web Release" \
            --notes "Web deployment v${VERSION}" \
            --target ${{ github.sha }} 
Enter fullscreen mode Exit fullscreen mode

See the live running sample app here. And, if you get stuck, you can see all the code and config for this app and here.

You now have a fully functional Flutter PWA on GitHub Pages. Anyone can hit this URL, and you don't have to pay anything. Pick up a custom domain if you want a professional URL. Then keep iterating, pushing commits, and adding features. Your PWA will update instantly, no extra steps needed.

If you're looking for a quality company to build your web app, please get in contact with Nimblesite.

Top comments (0)