azure-static-web-apps
Azure Static Web Apps Skill
Deploy and manage static web applications with Azure Static Web Apps.
Triggers
Use this skill when you see:
- azure static web apps, swa, static site
- jamstack azure, spa deployment
- static web app api, serverless frontend
- swa cli, staticwebapp.config.json
Instructions
Create Static Web App
# Create from GitHub
az staticwebapp create \
--name mystaticwebapp \
--resource-group mygroup \
--source https://github.com/org/repo \
--location eastus2 \
--branch main \
--app-location "/" \
--api-location "api" \
--output-location "dist" \
--login-with-github
# Create from Azure DevOps
az staticwebapp create \
--name mystaticwebapp \
--resource-group mygroup \
--source https://dev.azure.com/org/project/_git/repo \
--location eastus2 \
--branch main \
--app-location "/" \
--api-location "api" \
--output-location "build"
Configuration File
// staticwebapp.config.json
{
"routes": [
{
"route": "/api/*",
"allowedRoles": ["authenticated"]
},
{
"route": "/admin/*",
"allowedRoles": ["admin"]
},
{
"route": "/login",
"rewrite": "/.auth/login/aad"
},
{
"route": "/logout",
"redirect": "/.auth/logout"
},
{
"route": "/*",
"serve": "/index.html",
"statusCode": 200
}
],
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/images/*.{png,jpg,gif}", "/css/*", "/api/*"]
},
"responseOverrides": {
"401": {
"redirect": "/login",
"statusCode": 302
},
"404": {
"rewrite": "/404.html"
}
},
"globalHeaders": {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Content-Security-Policy": "default-src 'self'"
},
"mimeTypes": {
".json": "application/json",
".wasm": "application/wasm"
},
"auth": {
"identityProviders": {
"azureActiveDirectory": {
"registration": {
"openIdIssuer": "https://login.microsoftonline.com/<tenant-id>/v2.0",
"clientIdSettingName": "AAD_CLIENT_ID",
"clientSecretSettingName": "AAD_CLIENT_SECRET"
}
},
"github": {
"registration": {
"clientIdSettingName": "GITHUB_CLIENT_ID",
"clientSecretSettingName": "GITHUB_CLIENT_SECRET"
}
}
}
},
"platform": {
"apiRuntime": "node:18"
}
}
API Functions
// api/hello/index.ts
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
const httpTrigger: AzureFunction = async function (
context: Context,
req: HttpRequest
): Promise<void> {
const name = req.query.name || req.body?.name || "World";
context.res = {
body: { message: `Hello, ${name}!` },
headers: { "Content-Type": "application/json" }
};
};
export default httpTrigger;
// api/hello/function.json
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"],
"route": "hello"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Authentication
// Frontend: Get user info
async function getUserInfo() {
const response = await fetch('/.auth/me');
const payload = await response.json();
const { clientPrincipal } = payload;
if (clientPrincipal) {
return {
userId: clientPrincipal.userId,
userRoles: clientPrincipal.userRoles,
claims: clientPrincipal.claims,
identityProvider: clientPrincipal.identityProvider
};
}
return null;
}
// Login links
const loginLinks = {
aad: '/.auth/login/aad',
github: '/.auth/login/github',
google: '/.auth/login/google',
twitter: '/.auth/login/twitter'
};
// Logout
const logoutLink = '/.auth/logout';
// API: Get user from request
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
interface ClientPrincipal {
userId: string;
userRoles: string[];
claims: { typ: string; val: string }[];
identityProvider: string;
userDetails: string;
}
function getUser(req: HttpRequest): ClientPrincipal | null {
const header = req.headers.get("x-ms-client-principal");
if (!header) return null;
const encoded = Buffer.from(header, "base64");
const decoded = encoded.toString("utf8");
return JSON.parse(decoded);
}
const httpTrigger: AzureFunction = async function (
context: Context,
req: HttpRequest
): Promise<void> {
const user = getUser(req);
if (!user) {
context.res = { status: 401, body: "Unauthorized" };
return;
}
context.res = {
body: { message: `Hello, ${user.userDetails}!` }
};
};
Custom Domains
# Add custom domain
az staticwebapp hostname set \
--name mystaticwebapp \
--resource-group mygroup \
--hostname www.example.com
# List hostnames
az staticwebapp hostname list \
--name mystaticwebapp \
--resource-group mygroup
# Delete hostname
az staticwebapp hostname delete \
--name mystaticwebapp \
--resource-group mygroup \
--hostname www.example.com
Environment Variables
# Set app settings
az staticwebapp appsettings set \
--name mystaticwebapp \
--resource-group mygroup \
--setting-names "API_KEY=value" "DATABASE_URL=connection-string"
# List app settings
az staticwebapp appsettings list \
--name mystaticwebapp \
--resource-group mygroup
# Delete app setting
az staticwebapp appsettings delete \
--name mystaticwebapp \
--resource-group mygroup \
--setting-names "API_KEY"
Staging Environments
# List environments
az staticwebapp environment list \
--name mystaticwebapp \
--resource-group mygroup
# Each PR creates a staging environment automatically
# Environment URL: https://<random>-<app-name>.azurestaticapps.net
# Delete environment
az staticwebapp environment delete \
--name mystaticwebapp \
--resource-group mygroup \
--environment-name <env-name>
SWA CLI (Local Development)
# Install SWA CLI
npm install -g @azure/static-web-apps-cli
# Start local development
swa start ./dist --api-location ./api
# Start with framework dev server
swa start http://localhost:3000 --api-location ./api
# Build and deploy
swa build
swa deploy --deployment-token <token>
# Login and deploy
swa login
swa deploy ./dist --api-location ./api
# Emulate authentication
swa start ./dist --api-location ./api --auth mock
GitHub Actions Workflow
# .github/workflows/azure-static-web-apps.yml
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: 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_pull_request:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Close Pull Request
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
action: "close"
Best Practices
- Configuration: Use staticwebapp.config.json for routing and security
- Authentication: Leverage built-in auth providers
- APIs: Keep API functions lightweight and stateless
- Staging: Use PR environments for testing
- Security: Add security headers via config
Common Workflows
Deploy Static Site
- Create Static Web App with GitHub integration
- Configure build settings in workflow
- Add staticwebapp.config.json for routing
- Set up custom domain
- Configure authentication if needed
Add API Backend
- Create api/ folder with Azure Functions
- Configure routes in staticwebapp.config.json
- Add environment variables for secrets
- Test locally with SWA CLI
- Deploy with CI/CD pipeline
More from housegarofalo/claude-code-base
mqtt-iot
Configure MQTT brokers (Mosquitto, EMQX) for IoT messaging, device communication, and smart home integration. Manage topics, QoS levels, authentication, and bridging. Use when setting up IoT messaging, smart home communication, or device-to-cloud connectivity. (project)
22devops-engineer-agent
Infrastructure and DevOps specialist. Manages Docker, Kubernetes, CI/CD pipelines, and cloud deployments. Expert in GitHub Actions, Azure DevOps, Terraform, and container orchestration. Use for deployment automation, infrastructure setup, or CI/CD optimization.
6postgresql
Design, optimize, and manage PostgreSQL databases. Covers indexing, pgvector for AI embeddings, JSON operations, full-text search, and query optimization. Use when working with PostgreSQL, database design, or building data-intensive applications.
6home-assistant
Ultimate Home Assistant skill - complete administration, wireless protocols (Zigbee/ZHA/Z2M, Z-Wave JS, Thread, Matter), ESPHome device building, advanced troubleshooting, performance optimization, security hardening, custom integration development, and professional dashboard design. Covers configuration, REST API, automation debugging, database optimization, SSL/TLS, Jinja2 templating, and HACS custom cards. Use for any HA task.
6testing
Comprehensive testing skill covering unit, integration, and E2E testing with pytest, Jest, Cypress, and Playwright. Use for writing tests, improving coverage, debugging test failures, and setting up testing infrastructure.
5react-typescript
Build modern React applications with TypeScript. Covers React 18+ patterns, hooks, component architecture, state management (Zustand, Redux Toolkit), server components, and best practices. Use for React development, TypeScript integration, component design, and frontend architecture.
5