This starter gives you a working portfolio site with:
- A macOS-style UI (
index.html
) - Admin upload for your CV (PDF)
- Viewers can only view (no edit)
- Azure Functions API under
/api/*
- Cosmos DB for metadata, Blob Storage for files
- Download this repo (zip) and unzip locally.
- Install Azure CLI: https://learn.microsoft.com/cli/azure/install-azure-cli
- (Optional) Install SWA CLI:
npm i -g @azure/static-web-apps-cli
- Open a terminal in the project folder and run:
./provision.sh
.\provision.ps1
The script will:
- Log you into Azure (if needed)
- Create a resource group, storage account, and Cosmos DB (SQL)
- Create a private blob container
uploads
- Ask for your Static Web App name and set the required environment variables on it
If you haven't created the Static Web App yet, open the Azure Portal and create it (connect to your GitHub repo or deploy using
swa deploy
).
-
Using SWA CLI (local deploy):
swa deploy --env production --app-location . --api-location api
-
Using GitHub Actions: Create the SWA from the Azure Portal and connect your GitHub repo. The portal will add a workflow that deploys on every push. In that case, push this folder to GitHub and you're done.
- In the Azure Portal, open your Static Web App.
- Go to Roles / Role management and Invite yourself.
- Assign the role
admin
to your identity (GitHub/Google/Microsoft — whichever you will sign in with). - After you sign in on the site via the provider, the Admin icon and window appear.
COSMOS_CONNECTION
– Cosmos DB connection stringSTORAGE_ACCOUNT_NAME
– Storage account nameSTORAGE_ACCOUNT_KEY
– Storage account keyBLOB_CONTAINER
– usuallyuploads
The API reads these settings; the browser never sees them.
index.html
– frontend (includes an Admin window + CV upload)staticwebapp.config.json
– routes + auth rulesapi/
– Azure Functions:admin/files/sign-upload
– creates a write SAS for direct browser uploadadmin/files/commit
– saves file metadata to Cosmos DBfiles/[id]
– returns a read SAS for a file by idfiles/latest
– returns the newest published file (viewer link)
- The API functions have
authLevel: "anonymous"
on purpose; Static Web Apps enforces roles at the route level (seestaticwebapp.config.json
). The/api/admin/*
routes requireadmin
. - If you prefer Managed Identity instead of keys, assign the identity the roles “Storage Blob Data Contributor” on the storage account and use
DefaultAzureCredential
in the API code. - For articles + links, you can add more containers and functions using the same pattern.