Deployment Guide
This guide explains how to deploy SwallowKit applications to Azure.
Table of Contents
Prerequisites
- Azure account
- Azure CLI (
az) installed - GitHub account (for GitHub Actions)
- Azure DevOps account (for Azure Pipelines)
Quick Start
1. Initialize Project
npx swallowkit init my-app
cd my-appChoose CI/CD provider during initialization:
- GitHub Actions
- Azure Pipelines
2. Provision Azure Resources
npx swallowkit provision \
--resource-group my-app-rg \
--location japaneastThis creates using Bicep templates:
- Azure Static Web Apps
- Azure Functions (Consumption plan)
- Azure Cosmos DB (serverless)
- Managed Identity (secure service connections)
After provisioning completes, the terminal displays the secret values required for CI/CD:
=== CI/CD Secrets ===
AZURE_STATIC_WEB_APPS_API_TOKEN: <token-value>
AZURE_FUNCTIONAPP_PUBLISH_PROFILE: <profile-xml>Important: Copy these values — you will need them in step 4.
3. Push Code
Push your code to trigger the CI/CD workflow:
git add .
git commit -m "Initial deployment"
git push origin mainNote: This push will automatically trigger the CI/CD workflow, but it will fail because secrets are not registered yet. This is expected — proceed to the next step.
4. Cancel, Register Secrets, and Re-run
Step 4-1: Cancel the auto-triggered CI/CD run
The initial push triggers a CI/CD run that cannot succeed without secrets. Cancel it:
- GitHub Actions: Go to the Actions tab → click the running workflow → Cancel workflow
- Azure Pipelines: Go to Pipelines → click the running pipeline → Cancel
Step 4-2: Register the secrets displayed by provision
For GitHub Actions
- Go to your GitHub repository → Settings → Secrets and variables → Actions
- Add the following secrets using the values displayed after provisioning:
AZURE_STATIC_WEB_APPS_API_TOKENAZURE_FUNCTIONAPP_PUBLISH_PROFILE
For Azure Pipelines
- Azure DevOps → Pipelines → Library → Variable groups
- Create group named
azure-deployment - Add the following variables using the values displayed after provisioning:
AZURE_STATIC_WEB_APPS_API_TOKENAZURE_FUNCTIONAPP_PUBLISH_PROFILE
Step 4-3: Manually re-run the CI/CD workflow
- GitHub Actions: Actions tab → select the failed workflow → Re-run all jobs
- Azure Pipelines: Pipelines → select the failed pipeline → Run pipeline
Generated Resources
Azure Static Web Apps
- Purpose: Host Next.js application
- Mode: Standalone (optimized bundle size)
- Features:
- Global CDN
- Automatic HTTPS
- Custom domain support
Azure Functions
- Plan: Consumption (pay-per-execution)
- Runtime: Node.js 22
- Features:
- HTTP triggers
- Cosmos DB bindings
- Zod schema validation
Azure Cosmos DB
- Mode: Serverless
- Features:
- Automatic scaling
- Global distribution
- RBAC access control
Managed Identity
- Type: System-assigned managed identity
- Purpose: Secure service-to-service authentication without connection strings
- Permissions: Read/write access to Cosmos DB
CI/CD Workflows
Generated Files
.github/workflows/ # For GitHub Actions
├── static-web-app.yml # SWA deployment
└── azure-functions.yml # Functions deployment
pipelines/ # For Azure Pipelines
├── static-web-app.yml
└── azure-functions.ymlWorkflow Behavior
Static Web Apps Workflow:
- Triggers: Push to
main, changes inapp/**,components/**,lib/** - Steps:
- Build Next.js in standalone mode
- Deploy to Azure Static Web Apps
- Create preview environment (for PRs)
Azure Functions Workflow:
- Triggers: Push to
main, changes infunctions/** - Steps:
- Install dependencies
- Build TypeScript
- Deploy to Azure Functions
Path-Based Triggers
For efficient deployments, only relevant workflows run based on changed files:
- Frontend changes (
app/,components/,lib/) → Deploy SWA only - Backend changes (
functions/) → Deploy Functions only - Both changed → Deploy both
Environment Variables
Local Development (.env.local)
# Cosmos DB Emulator
COSMOS_DB_ENDPOINT=https://localhost:8081/
COSMOS_DB_KEY=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
# Azure Functions (local)
BACKEND_API_URL=http://localhost:7071Production (Azure)
# Azure Functions
BACKEND_API_URL=https://<function-app-name>.azurewebsites.net
# Cosmos DB (Managed Identity - no key needed)
COSMOS_DB_ENDPOINT=https://<cosmosdb-account-name>.documents.azure.com:443/Important: In production, COSMOS_DB_KEY is not needed. Managed Identity handles authentication automatically.
Setting Variables in Azure
Static Web Apps:
az staticwebapp appsettings set \
--name <swa-name> \
--setting-names \
BACKEND_API_URL=https://<function-name>.azurewebsites.net \
COSMOS_DB_ENDPOINT=https://<cosmosdb-name>.documents.azure.com:443/Azure Functions:
az functionapp config appsettings set \
--name <function-name> \
--resource-group my-app-rg \
--settings \
COSMOS_DB_ENDPOINT=https://<cosmosdb-name>.documents.azure.com:443/Customizing Infrastructure
Editing Bicep Files
infra/
├── main.bicep # Main orchestration
├── main.parameters.json # Parameters
└── modules/
├── staticwebapp.bicep # SWA resource
├── functions.bicep # Functions + Storage
└── cosmosdb.bicep # Cosmos DB + RBACApplying Changes
# After editing Bicep files
npx swallowkit provision \
--resource-group my-app-rg \
--location japaneastCommon Customizations
Change Cosmos DB to provisioned:
// infra/modules/cosmosdb.bicep
resource cosmosAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = {
properties: {
// serverless → provisioned
capabilities: []
}
}Troubleshooting
Deployment Fails
Symptom: CI/CD pipeline fails with errors
Solution:
- Check GitHub/Azure DevOps logs
- Verify secrets are correctly set
- Ensure Azure resources provisioned successfully
# Check resources
az resource list --resource-group my-app-rg --output tableCannot Connect to Functions
Symptom: BFF calls to Functions fail
Solution:
- Verify
BACKEND_API_URLis correctly set - Check CORS configuration
az functionapp cors show \
--name <function-name> \
--resource-group my-app-rg- Ensure Functions are running
az functionapp show \
--name <function-name> \
--resource-group my-app-rg \
--query "state" -o tsvCosmos DB Connection Error
Symptom: "Unauthorized" or connection errors
Solution:
- Verify Managed Identity is enabled
az functionapp identity show \
--name <function-name> \
--resource-group my-app-rg- Check RBAC role assignment
az cosmosdb sql role assignment list \
--account-name <cosmosdb-name> \
--resource-group my-app-rg- Verify endpoint URL is correct
Slow Builds
Symptom: Next.js build takes too long
Solution:
- Use
.nextcache
# .github/workflows/static-web-app.yml
- uses: actions/cache@v3
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}- Ensure
standalonemode is enabled (automatic)
Next Steps
- CLI Reference - All commands
- Scaffold Guide - CRUD code generation
