Azure 7 min read

Getting Started with Azure Static Web Apps: A Complete Deployment Guide

Suresh Suresh

Azure Static Web Apps is Microsoft’s purpose-built hosting service for modern static websites and single-page applications. It offers an incredibly generous free tier, seamless GitHub integration, and enterprise-grade features that make it an excellent choice for blogs, documentation sites, portfolios, and web applications built with frameworks like Astro, Next.js, React, Vue, and more.

In this comprehensive guide, we’ll walk through deploying a static website to Azure Static Web Apps from scratch, covering everything from creating your site to configuring custom domains and adding serverless APIs.

What Are Azure Static Web Apps?

Azure Static Web Apps (SWA) is a service that automatically builds and deploys full-stack web applications to Azure from a GitHub or Azure DevOps repository. When you push code changes, Azure automatically triggers a build and deploys the updated site to a globally distributed CDN.

Key characteristics include:

  • Static content hosting — HTML, CSS, JavaScript, and media files served from points of presence worldwide
  • Integrated API support — Serverless Azure Functions for backend logic
  • Built-in authentication — Support for Azure AD, GitHub, Twitter, and custom providers
  • Staging environments — Automatic preview deployments for pull requests
  • Custom domains with free SSL — Automatic HTTPS certificate provisioning and renewal

Benefits of Azure Static Web Apps

Free Tier Highlights

The free plan is surprisingly generous and includes:

  • 100 GB bandwidth per month
  • 2 custom domains
  • 0.5 GB storage
  • Built-in authentication
  • Staging environments for pull requests
  • Global CDN distribution
  • Free SSL certificates

For personal blogs, portfolios, and small business sites, the free tier is more than sufficient.

Why Choose Azure SWA Over Other Platforms?

  • GitHub Actions integration — CI/CD is configured automatically with zero effort
  • Global CDN — Your site is served from the nearest Azure edge location worldwide
  • Automatic SSL — Free certificates are provisioned and renewed automatically
  • Preview environments — Every pull request gets its own staging URL for testing
  • Serverless APIs — Add backend functionality without managing servers
  • Enterprise-ready — Easy upgrade path for organizations already using Azure

Prerequisites

Before you begin, you’ll need:

  1. An Azure accountSign up for free to get $200 in credits and 12 months of free services
  2. A GitHub account — For source code hosting and CI/CD integration
  3. Node.js 18+ — Installed on your local machine
  4. Git — For version control
  5. Azure CLI (optional) — For command-line deployment

Verify your Node.js installation:

node --version
npm --version

Step 1: Create a Simple Static Site

Let’s create a simple static website that we’ll deploy to Azure. For this tutorial, we’ll build a minimal site, but the same process works for Astro, React, Vue, Next.js, or any static site generator.

Create a new project directory and initialize it:

mkdir my-azure-site
cd my-azure-site
npm init -y

Create the project structure:

mkdir -p src/css src/js

Create src/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Azure Static Web App</title>
    <link rel="stylesheet" href="/css/style.css">
</head>
<body>
    <header>
        <nav>
            <a href="/" class="logo">MyApp</a>
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/about.html">About</a></li>
            </ul>
        </nav>
    </header>

    <main>
        <section class="hero">
            <h1>Welcome to My Azure Static Web App</h1>
            <p>This site is hosted on Azure Static Web Apps with a global CDN, free SSL, and automatic deployments from GitHub.</p>
            <button id="api-button">Call API</button>
            <p id="api-response"></p>
        </section>
    </main>

    <footer>
        <p>&copy; 2025 MyApp. Powered by Azure Static Web Apps.</p>
    </footer>

    <script src="/js/app.js"></script>
</body>
</html>

Create src/css/style.css:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', system-ui, sans-serif;
    line-height: 1.6;
    color: #1e293b;
}

header {
    background: #2563eb;
    padding: 1rem 2rem;
}

nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1200px;
    margin: 0 auto;
}

.logo {
    color: white;
    font-size: 1.5rem;
    font-weight: bold;
    text-decoration: none;
}

nav ul {
    list-style: none;
    display: flex;
    gap: 1.5rem;
}

nav a {
    color: white;
    text-decoration: none;
}

.hero {
    max-width: 800px;
    margin: 4rem auto;
    padding: 2rem;
    text-align: center;
}

.hero h1 {
    font-size: 2.5rem;
    margin-bottom: 1rem;
}

button {
    background: #2563eb;
    color: white;
    border: none;
    padding: 0.75rem 2rem;
    font-size: 1rem;
    border-radius: 0.5rem;
    cursor: pointer;
    margin-top: 1.5rem;
}

button:hover {
    background: #1d4ed8;
}

footer {
    text-align: center;
    padding: 2rem;
    color: #64748b;
    border-top: 1px solid #e2e8f0;
    margin-top: 4rem;
}

Create src/js/app.js:

document.getElementById('api-button').addEventListener('click', async () => {
    const responseEl = document.getElementById('api-response');
    try {
        const response = await fetch('/api/message');
        const data = await response.json();
        responseEl.textContent = data.message;
    } catch (error) {
        responseEl.textContent = 'API not configured yet. Deploy to Azure to enable APIs!';
    }
});

Step 2: Push to GitHub

Initialize a Git repository and push your code to GitHub:

git init
echo "node_modules/" > .gitignore
git add .
git commit -m "Initial commit: static site ready for Azure deployment"

Create a new repository on GitHub, then push your code:

git remote add origin https://github.com/YOUR_USERNAME/my-azure-site.git
git branch -M main
git push -u origin main

Step 3: Create a Static Web App in Azure Portal

  1. Sign in to the Azure Portal
  2. Click Create a resource and search for Static Web Apps
  3. Click Create and fill in the details:
SettingValue
SubscriptionYour Azure subscription
Resource GroupCreate new: my-site-rg
Namemy-azure-site
Plan typeFree
RegionSelect nearest to your audience
SourceGitHub
  1. Click Sign in with GitHub and authorize Azure
  2. Configure the build details:
SettingValue
OrganizationYour GitHub username
Repositorymy-azure-site
Branchmain
Build PresetsCustom
App location/src
API locationapi (leave blank if no API)
Output location“ (empty for plain HTML)
  1. Click Review + Create, then Create

Azure will automatically create a GitHub Actions workflow in your repository and trigger the first deployment.

Step 4: Understanding the GitHub Actions Workflow

Azure automatically generates a GitHub Actions workflow file in your repository at .github/workflows/. Here’s what a typical workflow looks like:

name: Azure Static Web Apps CI/CD

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

jobs:
  build_and_deploy_job:
    if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
    runs-on: ubuntu-latest
    name: Build and Deploy Job
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
          lfs: false

      - name: Build And Deploy
        id: builddeploy
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          action: "upload"
          app_location: "/src"
          api_location: "api"
          output_location: ""

  close_pull_request_job:
    if: github.event_name == 'pull_request' && github.event.action == 'closed'
    runs-on: ubuntu-latest
    name: Close Pull Request Job
    steps:
      - name: Close Pull Request
        id: closepullrequest
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          action: "close"

The AZURE_STATIC_WEB_APPS_API_TOKEN secret is automatically added to your GitHub repository by Azure during the setup process.

For an Astro site like FreeTechLearner.com, you would customize this workflow to run npm ci and npm run build before the deploy step, and set output_location to dist.

Step 5: Custom Domain Setup

Once your site is deployed, you’ll want to connect a custom domain:

  1. In the Azure Portal, navigate to your Static Web App
  2. Click Custom domains in the left menu
  3. Click Add and choose your method:

Using a Root Domain (example.com)

  1. Select Custom domain on other DNS
  2. Enter your domain name (e.g., example.com)
  3. Azure will provide an IP address
  4. Create an A record in your DNS provider pointing to this IP
  5. Create a TXT record for domain verification
  6. Click Validate and wait for DNS propagation (can take up to 48 hours)

Using a Subdomain (www.example.com)

  1. Select Custom domain on other DNS
  2. Enter the subdomain (e.g., www.example.com)
  3. Azure will provide a CNAME target
  4. Create a CNAME record in your DNS provider pointing to the Azure URL
  5. Click Validate

Azure automatically provisions and renews a free SSL certificate for your custom domain. No manual certificate management is needed.

Step 6: Environment Variables

For configuration that shouldn’t be committed to source control, use environment variables:

  1. In the Azure Portal, go to your Static Web App
  2. Click Configuration in the left menu under Settings
  3. Click Add to create new application settings

These variables are available to your Azure Functions API at runtime. For build-time variables used by your static site generator, add them to your GitHub Actions workflow:

- name: Build
  run: npm run build
  env:
    PUBLIC_SITE_URL: "https://www.example.com"
    PUBLIC_ANALYTICS_ID: "G-XXXXXXXXXX"

Advanced Features

Adding an API with Azure Functions

Azure Static Web Apps support serverless APIs through Azure Functions. Create an api directory in your project root:

mkdir -p api/message

Create api/message/index.js:

module.exports = async function (context, req) {
    context.res = {
        status: 200,
        headers: {
            'Content-Type': 'application/json'
        },
        body: {
            message: 'Hello from Azure Functions!',
            timestamp: new Date().toISOString()
        }
    };
};

Create api/message/function.json:

{
    "bindings": [
        {
            "authLevel": "anonymous",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": ["get"]
        },
        {
            "type": "http",
            "direction": "out",
            "name": "res"
        }
    ]
}

Your API will be available at /api/message when deployed.

Authentication

Azure Static Web Apps includes built-in authentication with several providers. Add route rules to your staticwebapp.config.json:

{
    "routes": [
        {
            "route": "/admin/*",
            "allowedRoles": ["authenticated"]
        }
    ],
    "responseOverrides": {
        "401": {
            "statusCode": 302,
            "redirect": "/.auth/login/github"
        }
    }
}

Built-in auth providers include:

  • GitHub: /.auth/login/github
  • Azure AD: /.auth/login/aad
  • Twitter: /.auth/login/twitter

Users can log out via /.auth/logout.

Fallback Routes and Navigation

For single-page applications, configure a navigation fallback in staticwebapp.config.json:

{
    "navigationFallback": {
        "rewrite": "/index.html",
        "exclude": ["/images/*.{png,jpg,gif,svg}", "/css/*", "/*.{js,json}"]
    }
}

Pricing Overview

Azure Static Web Apps offers two tiers:

FeatureFreeStandard ($9/month)
Bandwidth100 GB/month100 GB included
Storage0.5 GB2 GB
Custom domains25
SSL certificatesFreeFree
Staging environments310
Azure FunctionsManagedBring your own
SLANone99.95%
AuthenticationBuilt-inBuilt-in + Custom
Private endpointsNoYes

For most personal projects and small business sites, the free tier provides everything you need.

Deploying an Astro Site

If you’re deploying an Astro site (like this blog), the configuration differs slightly. Here’s what your GitHub Actions workflow should look like:

name: Azure Static Web Apps CI/CD

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

jobs:
  build_and_deploy:
    if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build Astro site
        run: npm run build

      - name: Deploy to Azure
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          action: 'upload'
          app_location: '/'
          output_location: 'dist'
          skip_app_build: true

The key settings for Astro are:

  • app_location: '/' — The root of your project
  • output_location: 'dist' — Astro’s default build output directory
  • skip_app_build: true — We’ve already built the site in a previous step, so Azure doesn’t need to build it again

Troubleshooting Common Issues

Build Failures

Check the GitHub Actions logs for detailed error messages. Common causes include missing dependencies, incorrect Node.js versions, or wrong app/output locations.

404 Errors After Deployment

Ensure your output_location in the workflow matches your framework’s build output directory. For Astro, it’s dist. For Next.js, it’s out (with static export). For plain HTML, leave it empty.

Custom Domain Not Working

DNS propagation can take up to 48 hours. Verify your DNS records are correct using:

dig your-domain.com
nslookup your-domain.com

API Routes Not Found

Ensure your api directory is at the root of your repository and that the api_location in your workflow configuration matches.

Conclusion

Azure Static Web Apps provides an excellent hosting solution for modern static websites. The combination of a generous free tier, automatic CI/CD through GitHub Actions, global CDN distribution, free SSL certificates, and built-in authentication makes it hard to beat for personal projects and small to medium websites.

Whether you’re deploying a personal blog built with Astro, a documentation site, or a React single-page application, Azure Static Web Apps handles the infrastructure so you can focus on creating great content and experiences.

The key steps to remember are:

  1. Create your static site and push it to GitHub
  2. Connect your repository to Azure Static Web Apps
  3. Let the automatic CI/CD pipeline handle builds and deployments
  4. Configure your custom domain for a professional touch
  5. Add serverless APIs with Azure Functions as your needs grow

Happy deploying! If you have questions about deploying your specific framework or need help with advanced configuration, feel free to leave a comment below.

Suresh

Written by Suresh

A passionate technology enthusiast, blogger, and self-taught developer. I write about Linux, Open Source, Cloud Computing, and emerging technologies to help students and beginners learn tech for free.