Azure Static Web Apps
Configure an Azure Static Web Apps project from an existing frontend and optional API, use the SWA CLI for local emulation and deployment, and produce the exact commands and files needed.
When to invoke
- "Deploy this static site to Azure Static Web Apps."
- "Set up SWA local development with an API folder."
- "Configure staticwebapp.config.json routes and auth."
- "Add Azure Functions to my Static Web App."
- "Create a GitHub Actions workflow for Azure Static Web Apps."
Prerequisites and context
- Install the SWA CLI with
npm install -D @azure/static-web-apps-cli and verify with npx swa --version.
swa-cli.config.json is CLI settings and is created by swa init; never create it manually.
staticwebapp.config.json is runtime configuration for routes, auth, headers, navigation fallback, and API runtime; it can be created manually in the app source or output folder.
- Local SWA emulation defaults to
http://localhost:4280; common dev server URLs include http://localhost:3000.
Procedure
- Install the CLI:
npm install -D @azure/static-web-apps-cli.
- Run
npx swa init or npx swa init --yes before any swa start or swa deploy; this creates swa-cli.config.json with framework detection.
- Build the application with the existing project command such as
npm run build when needed.
- Run
npx swa start or a scoped swa start command to test locally.
- Authenticate with
npx swa login.
- Deploy with
npx swa deploy --env production or a preview deployment.
- Validate routing, API calls, auth, and deployment output.
Configuration files
| File |
Created by |
Purpose |
Key fields |
swa-cli.config.json |
swa init only |
CLI project settings. |
$schema, configurations, appLocation, apiLocation, outputLocation, appBuildCommand, apiBuildCommand, run, appDevserverUrl. |
staticwebapp.config.json |
Manually or framework output |
Runtime behavior. |
navigationFallback, rewrite, exclude, routes, allowedRoles, platform.apiRuntime, headers, auth. |
.github/workflows/azure-static-web-apps.yml |
Azure portal, Azure CLI, or manual |
CI/CD deployment. |
azure_static_web_apps_api_token, repo_token, action, app_location, api_location, output_location, skip_app_build, app_build_command. |
{
"$schema": "https://aka.ms/azure/static-web-apps-cli/schema",
"configurations": {
"app": {
"appLocation": ".",
"apiLocation": "api",
"outputLocation": "dist",
"appBuildCommand": "npm run build",
"run": "npm run dev",
"appDevserverUrl": "http://localhost:3000"
}
}
}
{
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/images/*", "/css/*"]
},
"routes": [
{ "route": "/api/*", "allowedRoles": ["authenticated"] }
],
"platform": { "apiRuntime": "node:20" }
}
Command reference
| Command |
Use |
Examples and flags |
swa login |
Authenticate with Azure for deployment. |
swa login, swa login --subscription-id <id>, swa login --clear-credentials; flags: --subscription-id, -S, --resource-group, -R, --tenant-id, -T, --client-id, -C, --client-secret, -CS, --app-name, -n. |
swa init |
Configure an existing frontend and optional API. |
swa init, swa init --yes. |
swa build |
Build frontend and/or API. |
swa build, swa build --auto, swa build myApp; flags: --app-location, -a, --api-location, -i, --output-location, -O, --app-build-command, -A, --api-build-command, -I. |
swa start |
Start local emulator. |
swa start, swa start ./dist, swa start http://localhost:3000, swa start ./dist --api-location ./api, swa start http://localhost:3000 --run "npm start"; flags: --port, -p, --api-location, -i, --api-port, -j, --run, -r, --open, -o, --ssl, -s. |
swa deploy |
Deploy to Azure Static Web Apps. |
swa deploy, swa deploy ./dist, swa deploy --env production, swa deploy --deployment-token <TOKEN>, swa deploy --dry-run, swa deploy --print-token; flags: --env, --deployment-token, -d, --app-name, -n. |
swa db |
Initialize database connections. |
swa db init --database-type mssql, swa db init --database-type postgresql, swa db init --database-type cosmosdb_nosql. |
| Framework |
Common port |
| React/Vue/Next.js |
3000 |
| Angular |
4200 |
| Vite |
5173 |
Deployment vocabulary
Preserve these SWA distinctions when writing commands or workflows: IMPORTANT, REQUIRED, auto-detects, auto-detection, auto-detected, auto-generated, preview, production, HTTPS, pre-built, and skip_app_build: true. Use preview for non-production environments and production only when deploying the live environment.
Azure Functions API
Create an API folder only when the app needs serverless endpoints.
mkdir api && cd api
func init --worker-runtime node --model V4
func new --name message --template "HTTP trigger"
api/src/functions/message.js:
const { app } = require('@azure/functions');
app.http('message', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request) => {
const name = request.query.get('name') || 'World';
return { jsonBody: { message: `Hello, ${name}!` } };
}
});
Set API runtime in staticwebapp.config.json and keep the CLI config generated by swa init aligned:
{ "platform": { "apiRuntime": "node:20" } }
Supported API runtimes are node:18, node:20, node:22, dotnet:8.0, dotnet-isolated:8.0, python:3.10, and python:3.11. Test with npx swa start ./dist --api-location ./api and access the API at http://localhost:4280/api/message.
GitHub Actions deployment
Use Azure portal or Azure CLI to create the Static Web App and copy the deployment token to the repository secret AZURE_STATIC_WEB_APPS_API_TOKEN. The action also uses GITHUB_TOKEN.
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@v3
- name: Build And Deploy
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: /
api_location: api
output_location: dist
close_pr:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
action: close
Get deployment tokens from Azure Portal → Static Web App → Manage deployment token, swa deploy --print-token, or SWA_CLI_DEPLOYMENT_TOKEN.
Troubleshooting
| Issue |
Solution |
| 404 on client routes |
Add navigationFallback with rewrite: "/index.html" to staticwebapp.config.json. |
| API returns 404 |
Verify api folder structure, platform.apiRuntime, and function exports. |
| Build output not found |
Verify output_location matches actual build output directory. |
| Auth not working locally |
Use /.auth/login/<provider> to access auth emulator UI. |
| CORS errors |
APIs under /api/* are same-origin; external APIs need CORS headers. |
| Deployment token expired |
Regenerate in Azure Portal → Static Web App → Manage deployment token. |
| Config not applied |
Ensure staticwebapp.config.json is in app_location or output_location. |
| Local API timeout |
Default is 45 seconds; optimize the function or check for blocking calls. |
Debug with swa start --verbose log, swa deploy --dry-run, and swa --print-config.
Output template
## Azure Static Web Apps result
**Status:** configured | deployed | blocked
**App location:** `<app_location>`
**API location:** `<api_location or none>`
**Output location:** `<output_location>`
### Commands
- `npm install -D @azure/static-web-apps-cli`
- `npx swa init` or `npx swa init --yes`
- `<build command>`
- `<swa start command>`
- `<swa deploy command>`
### Files
| File | Status | Notes |
| --- | --- | --- |
| `swa-cli.config.json` | generated by `swa init` | <key settings> |
| `staticwebapp.config.json` | created / updated / unchanged | <routes, auth, runtime> |
| `.github/workflows/azure-static-web-apps.yml` | created / updated / unchanged | <token secret and paths> |
### Validation
- Local emulator `http://localhost:4280`: pass | fail | not run
- API `http://localhost:4280/api/message`: pass | fail | not applicable
- Deployment: pass | fail | not run
Quality gate
References
1---2name: azure-static-web-apps3description: Create, configure, run, and deploy Azure Static Web Apps with the SWA CLI. Use when asked to deploy a static site to Azure, run SWA locally, configure staticwebapp.config.json, add Azure Functions APIs, set API runtimes, database connections, or GitHub Actions CI/CD for Static Web Apps.4---56<!-- Generated from harness/github-copilot/skills/azure-static-web-apps/SKILL.md by harness/claude-code/scripts/convert_from_copilot.py. Edit the source, not this file. -->78# Azure Static Web Apps910Configure an Azure Static Web Apps project from an existing frontend and optional API, use the SWA CLI for local emulation and deployment, and produce the exact commands and files needed.1112## When to invoke1314- "Deploy this static site to Azure Static Web Apps."15- "Set up SWA local development with an API folder."16- "Configure staticwebapp.config.json routes and auth."17- "Add Azure Functions to my Static Web App."18- "Create a GitHub Actions workflow for Azure Static Web Apps."1920## Prerequisites and context2122- Install the SWA CLI with `npm install -D @azure/static-web-apps-cli` and verify with `npx swa --version`.23- `swa-cli.config.json` is CLI settings and is created by `swa init`; never create it manually.24- `staticwebapp.config.json` is runtime configuration for routes, auth, headers, navigation fallback, and API runtime; it can be created manually in the app source or output folder.25- Local SWA emulation defaults to `http://localhost:4280`; common dev server URLs include `http://localhost:3000`.2627## Procedure28291. Install the CLI: `npm install -D @azure/static-web-apps-cli`.302. Run `npx swa init` or `npx swa init --yes` before any `swa start` or `swa deploy`; this creates `swa-cli.config.json` with framework detection.313. Build the application with the existing project command such as `npm run build` when needed.324. Run `npx swa start` or a scoped `swa start` command to test locally.335. Authenticate with `npx swa login`.346. Deploy with `npx swa deploy --env production` or a preview deployment.357. Validate routing, API calls, auth, and deployment output.3637## Configuration files3839| File | Created by | Purpose | Key fields |40| --- | --- | --- | --- |41| `swa-cli.config.json` | `swa init` only | CLI project settings. | `$schema`, `configurations`, `appLocation`, `apiLocation`, `outputLocation`, `appBuildCommand`, `apiBuildCommand`, `run`, `appDevserverUrl`. |42| `staticwebapp.config.json` | Manually or framework output | Runtime behavior. | `navigationFallback`, `rewrite`, `exclude`, `routes`, `allowedRoles`, `platform.apiRuntime`, headers, auth. |43| `.github/workflows/azure-static-web-apps.yml` | Azure portal, Azure CLI, or manual | CI/CD deployment. | `azure_static_web_apps_api_token`, `repo_token`, `action`, `app_location`, `api_location`, `output_location`, `skip_app_build`, `app_build_command`. |4445```json46{47 "$schema": "https://aka.ms/azure/static-web-apps-cli/schema",48 "configurations": {49 "app": {50 "appLocation": ".",51 "apiLocation": "api",52 "outputLocation": "dist",53 "appBuildCommand": "npm run build",54 "run": "npm run dev",55 "appDevserverUrl": "http://localhost:3000"56 }57 }58}59```6061```json62{63 "navigationFallback": {64 "rewrite": "/index.html",65 "exclude": ["/images/*", "/css/*"]66 },67 "routes": [68 { "route": "/api/*", "allowedRoles": ["authenticated"] }69 ],70 "platform": { "apiRuntime": "node:20" }71}72```7374## Command reference7576| Command | Use | Examples and flags |77| --- | --- | --- |78| `swa login` | Authenticate with Azure for deployment. | `swa login`, `swa login --subscription-id <id>`, `swa login --clear-credentials`; flags: `--subscription-id, -S`, `--resource-group, -R`, `--tenant-id, -T`, `--client-id, -C`, `--client-secret, -CS`, `--app-name, -n`. |79| `swa init` | Configure an existing frontend and optional API. | `swa init`, `swa init --yes`. |80| `swa build` | Build frontend and/or API. | `swa build`, `swa build --auto`, `swa build myApp`; flags: `--app-location, -a`, `--api-location, -i`, `--output-location, -O`, `--app-build-command, -A`, `--api-build-command, -I`. |81| `swa start` | Start local emulator. | `swa start`, `swa start ./dist`, `swa start http://localhost:3000`, `swa start ./dist --api-location ./api`, `swa start http://localhost:3000 --run "npm start"`; flags: `--port, -p`, `--api-location, -i`, `--api-port, -j`, `--run, -r`, `--open, -o`, `--ssl, -s`. |82| `swa deploy` | Deploy to Azure Static Web Apps. | `swa deploy`, `swa deploy ./dist`, `swa deploy --env production`, `swa deploy --deployment-token <TOKEN>`, `swa deploy --dry-run`, `swa deploy --print-token`; flags: `--env`, `--deployment-token, -d`, `--app-name, -n`. |83| `swa db` | Initialize database connections. | `swa db init --database-type mssql`, `swa db init --database-type postgresql`, `swa db init --database-type cosmosdb_nosql`. |8485| Framework | Common port |86| --- | --- |87| React/Vue/Next.js | 3000 |88| Angular | 4200 |89| Vite | 5173 |909192## Deployment vocabulary9394Preserve these SWA distinctions when writing commands or workflows: `IMPORTANT`, `REQUIRED`, `auto-detects`, `auto-detection`, `auto-detected`, `auto-generated`, `preview`, `production`, `HTTPS`, `pre-built`, and `skip_app_build: true`. Use `preview` for non-production environments and `production` only when deploying the live environment.9596## Azure Functions API9798Create an API folder only when the app needs serverless endpoints.99100```bash101mkdir api && cd api102func init --worker-runtime node --model V4103func new --name message --template "HTTP trigger"104```105106`api/src/functions/message.js`:107108```javascript109const { app } = require('@azure/functions');110111app.http('message', {112 methods: ['GET', 'POST'],113 authLevel: 'anonymous',114 handler: async (request) => {115 const name = request.query.get('name') || 'World';116 return { jsonBody: { message: `Hello, ${name}!` } };117 }118});119```120121Set API runtime in `staticwebapp.config.json` and keep the CLI config generated by `swa init` aligned:122123```json124{ "platform": { "apiRuntime": "node:20" } }125```126127Supported API runtimes are `node:18`, `node:20`, `node:22`, `dotnet:8.0`, `dotnet-isolated:8.0`, `python:3.10`, and `python:3.11`. Test with `npx swa start ./dist --api-location ./api` and access the API at `http://localhost:4280/api/message`.128129## GitHub Actions deployment130131Use Azure portal or Azure CLI to create the Static Web App and copy the deployment token to the repository secret `AZURE_STATIC_WEB_APPS_API_TOKEN`. The action also uses `GITHUB_TOKEN`.132133```yaml134name: Azure Static Web Apps CI/CD135on:136 push:137 branches: [main]138 pull_request:139 types: [opened, synchronize, reopened, closed]140 branches: [main]141jobs:142 build_and_deploy:143 if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')144 runs-on: ubuntu-latest145 steps:146 - uses: actions/checkout@v3147 - name: Build And Deploy148 uses: Azure/static-web-apps-deploy@v1149 with:150 azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}151 repo_token: ${{ secrets.GITHUB_TOKEN }}152 action: upload153 app_location: /154 api_location: api155 output_location: dist156 close_pr:157 if: github.event_name == 'pull_request' && github.event.action == 'closed'158 runs-on: ubuntu-latest159 steps:160 - uses: Azure/static-web-apps-deploy@v1161 with:162 azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}163 action: close164```165166Get deployment tokens from Azure Portal → Static Web App → Manage deployment token, `swa deploy --print-token`, or `SWA_CLI_DEPLOYMENT_TOKEN`.167168## Troubleshooting169170| Issue | Solution |171| --- | --- |172| 404 on client routes | Add `navigationFallback` with `rewrite: "/index.html"` to `staticwebapp.config.json`. |173| API returns 404 | Verify `api` folder structure, `platform.apiRuntime`, and function exports. |174| Build output not found | Verify `output_location` matches actual build output directory. |175| Auth not working locally | Use `/.auth/login/<provider>` to access auth emulator UI. |176| CORS errors | APIs under `/api/*` are same-origin; external APIs need CORS headers. |177| Deployment token expired | Regenerate in Azure Portal → Static Web App → Manage deployment token. |178| Config not applied | Ensure `staticwebapp.config.json` is in `app_location` or `output_location`. |179| Local API timeout | Default is 45 seconds; optimize the function or check for blocking calls. |180181Debug with `swa start --verbose log`, `swa deploy --dry-run`, and `swa --print-config`.182183## Output template184185```markdown186## Azure Static Web Apps result187188**Status:** configured | deployed | blocked189**App location:** `<app_location>`190**API location:** `<api_location or none>`191**Output location:** `<output_location>`192193### Commands194- `npm install -D @azure/static-web-apps-cli`195- `npx swa init` or `npx swa init --yes`196- `<build command>`197- `<swa start command>`198- `<swa deploy command>`199200### Files201| File | Status | Notes |202| --- | --- | --- |203| `swa-cli.config.json` | generated by `swa init` | <key settings> |204| `staticwebapp.config.json` | created / updated / unchanged | <routes, auth, runtime> |205| `.github/workflows/azure-static-web-apps.yml` | created / updated / unchanged | <token secret and paths> |206207### Validation208- Local emulator `http://localhost:4280`: pass | fail | not run209- API `http://localhost:4280/api/message`: pass | fail | not applicable210- Deployment: pass | fail | not run211```212213## Quality gate214215- [ ] `swa init` is used to create `swa-cli.config.json`; the file is not manually invented.216- [ ] `staticwebapp.config.json` is placed in `app_location` or `output_location` when runtime config is needed.217- [ ] `output_location` matches the actual build output.218- [ ] API projects set a supported `platform.apiRuntime` and are tested through the SWA emulator.219- [ ] Deployment uses `AZURE_STATIC_WEB_APPS_API_TOKEN`, `SWA_CLI_DEPLOYMENT_TOKEN`, or an authenticated `swa login`; no token is committed.220- [ ] Client routing, auth, and `/api/*` behavior are validated locally or marked not run with a reason.221222## References223224- [SWA CLI schema](https://aka.ms/azure/static-web-apps-cli/schema)