Deploy an Angular app to Azure Static Web Apps

An Angular application can be published as static browser assets, without running a Node.js server in production. Azure Static Web Apps hosts that output behind HTTPS, integrates with GitHub, and provides preview environments for pull requests. This guide covers a practical release path: build the Angular project, connect it to Azure, automate deployment, and configure the boundaries around client-side routing and APIs.

Several decisions determine whether the result behaves like a finished application rather than a collection of files. The build output path must match Angular's configuration, deep links must return the SPA shell, and secrets must remain outside the browser bundle. The workflow below also accounts for Australian hosting, privacy, currency, and distributed team schedules.

Prepare the Angular project for deployment

Begin with a production build that works on a clean checkout. Commit the package lock file, use the Node.js version supported by your Angular release, and run npm ci followed by npm run build. If the script only calls ng build, confirm that it produces the production configuration. Angular 17 and newer commonly write to dist/<project-name>/browser; older layouts may write directly to dist/<project-name>. Check angular.json rather than relying on the folder name.

Pure client-side rendering is the simplest fit for a static host. If you have enabled server-side rendering, Angular may also generate a server entry point, which Azure Static Web Apps cannot execute as an application server. Keep the browser build as the static deployment, or host the server runtime on suitable Azure compute. For a site served from the root of a custom domain, the normal / base href works without extra changes.

Treat configuration as part of the build contract. Angular's environment files are compiled into the application, so production URLs and feature flags must match the deployment that consumes them. Never place a database password, an API key intended for a server, or an Azure access token in an environment file that reaches the browser. Public identifiers can be supplied through GitHub Actions variables; credentials belong in GitHub secrets or an Azure secret store.

Connect Azure Static Web Apps to GitHub

In the Azure portal, create a Static Web Apps resource and choose the plan that matches your workload. A free plan is useful for an evaluation, while paid plans support broader organisational requirements and service options. Select GitHub as the deployment source, authorise the application, select your repository, and choose the branch that should produce production releases, normally main. The portal also generates a deployment token for the GitHub workflow.

The portal's build configuration should use Other for a custom Angular pipeline, with an app location of /. Set the output location to the directory confirmed in angular.json, such as dist/your-app/browser. Authentication can remain open or use a supported identity provider. Australian organisations already managing workforce access through Microsoft Entra ID may prefer that route, although GitHub-based authentication is also supported.

For an Australian audience, the Australia East region is a common choice for workloads serving Sydney and Melbourne, including applications used by teams in Brisbane and Adelaide. Region choice does not by itself settle data residency: if the system collects personal information, assess the Privacy Act 1988, the Australian Privacy Principles, and relevant Office of the Australian Information Commissioner guidance. Government workloads may also require controls aligned with Australian Signals Directorate guidance.

Automate the release with GitHub Actions

Copy the deployment token into the repository secret AZURE_STATIC_WEB_APPS_API_TOKEN. Treat it like a password: do not place it in the workflow file, expose it in build logs, or commit it to the repository. The following workflow builds the application, uploads the output, deploys approved changes, and closes the preview when a pull request is merged.

name: Azure Static Web Apps

on:
  push:
    branches: [main]
  pull_request:
    types: [opened, synchronize, reopened, closed]
  workflow_dispatch:

permissions:
  contents: read
  pull-requests: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: npm

      - run: npm ci
      - run: npm run build

      - uses: actions/upload-artifact@v4
        with:
          name: static-web-apps
          path: dist/your-app/browser

  deploy:
    if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Azure Static Web Apps
        uses: Azure/static-web-apps-deploy@v1.0.12
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          action: upload
          skip_app_build: true
          app_location: '/'
          output_location: 'dist/your-app/browser'

      - name: Close pull request
        if: github.event_name == 'pull_request'
        uses: Azure/static-web-apps-deploy@v1.0.12
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          action: close

Because the job builds the project itself, skip_app_build: true prevents the deployment action from running a second build. The uploaded artifact is the output Azure serves. A pull request receives a staging URL, while a push to main updates the production alias. Change the placeholder project directory if your Angular workspace uses another name, and align the Node.js version with your framework's requirements.

Before publishing, compare the planned topology against this static hosting reference to confirm that the hosting assumptions still fit. Keep the generated deployment workflow under source control so changes to the release process receive normal code review.

Configure routes, APIs, and environment values

Azure Static Web Apps can host an Azure Functions project under /api alongside the Angular output. Set api_location to the Functions directory and follow the platform's supported Functions build process so the API is routed independently of the Angular fallback. For an existing ASP.NET Core API, publish it separately to Azure App Service or Container Apps, then point the frontend at its HTTPS endpoint. A browser must never connect directly to SQL Server or receive a server connection string. Protect server-side calls with managed identity, Key Vault, and suitable network controls.

The SPA needs a fallback for routes such as /products/123; otherwise a refresh can produce a 404 even though the application works when navigation starts at /. A staticwebapp.config.json in the output can provide a catch-all route and rewrite unmatched navigation to index.html. Restrict sensitive paths to authenticated or custom roles rather than leaving them anonymous, and check that the fallback does not hide missing assets or intercept API calls.

Plan configuration changes carefully before promoting a release. Azure application settings are not automatically injected into an Angular browser build. If several environments must run the same compiled artifact, publish a separate runtime configuration file and load it during startup. Keep that file limited to public values, while API credentials stay in the server-side service. This separation prevents a production URL or key from being accidentally baked into a staging deployment.

Reliable deployment recommendations and next steps

After the first deployment, verify the production URL, a deep link, the custom domain, and every API route. Open the pull-request preview as well as the production alias, then inspect browser and platform logs for failed assets or stale content. For an Australian team, forecast the service and API usage in AUD, check the applicable GST treatment on your Microsoft invoice, and consider an enterprise agreement or Microsoft CSP arrangement available through the local market.

Distributed releases need an explicit operational routine. Store timestamps in UTC, but record the relevant Australian local time in incident notes; AEST and AEDT changes can make a schedule misleading during daylight-saving transitions. Teams in Perth, Melbourne, and Sydney can then follow the same runbook without guessing which build belongs to which release. For adjacent notes on software development and the developer journey, Kilt and Code provides a broader perspective.

Create the Azure resource, connect the Angular repository, and run this workflow for your next feature branch. Once the preview has passed its checks, merge to main, then publish the release URL and the name of the person responsible for follow-up.