Entwicklerdokumentation

Azure Static Web Apps

Von null zu einer Buchungsseite auf Azure Static Web Apps – die Seite, das Deployment per GitHub Actions, die Origin-Liste des Schlüssels und Ihre Domain.

Dieses Tutorial bringt einen Betrieb ganz ohne Website zu einer Buchungsseite unter https://www.your-venue.example, per HTTPS von Azure Static Web Apps ausgeliefert und bei jedem Push von GitHub Actions ausgerollt. Die Seite besteht aus drei Dateien; alles andere ist Konfiguration, die Sie einmal tippen.

Sie brauchen ein Azure-Abonnement, ein GitHub-Konto, die Azure CLI (2.29 oder neuer) und die GitHub CLI, beide angemeldet, eine Domain, deren DNS-Einträge Sie bearbeiten können, und ein BookDinePlay-Betreiberkonto mit einer Location.

Die Befehle verwenden durchgehend zwei Namen; wählen Sie eigene und behalten Sie sie in jedem Schritt bei:

RG=rg-your-venue-site
APP=your-venue-site

1. Static Web App anlegen

Eine Ressourcengruppe und die App im Free-Tarif. Der Standort entscheidet nur, wo die Konfiguration der App gespeichert wird – die Seite selbst kommt vom globalen Edge von Azure:

az login
az group create --name "$RG" --location westeurope
az staticwebapp create --name "$APP" --resource-group "$RG" --location westeurope --sku Free
az staticwebapp show --name "$APP" --resource-group "$RG" --query defaultHostname -o tsv

Der letzte Befehl gibt den generierten Hostnamen der App aus, endend auf azurestaticapps.net. Notieren Sie ihn: Er ist die erste Origin, die Ihr Schlüssel erlaubt, und später das Ziel Ihres DNS-Eintrags.

2. Veröffentlichbaren Schlüssel für beide Origins anlegen

Öffnen Sie in der Konsole Location → API-Schlüssel unter app.bookdineplay.com/operator/venue und legen Sie einen Schlüssel vom Typ Veröffentlichbar an. Tragen Sie unter Erlaubte Ursprünge jede Origin ein, von der die Seite ausgeliefert wird – den generierten Hostnamen aus Schritt 1, die eigene Domain aus Schritt 5 und localhost für die Vorschau – durch Kommas getrennt:

https://<hostname from step 1>, https://www.your-venue.example, http://localhost:*

Die Origin-Liste eines Schlüssels steht mit dem Anlegen fest – deshalb kommt die eigene Domain jetzt schon hinein, bevor sie auflöst. Um später eine Origin zu ergänzen, legen Sie einen neuen Schlüssel mit der vollständigen Liste an, rollen ihn aus und widerrufen dann den alten – Schlüssel rotieren. Kopieren Sie den bdp_pk_…-Schlüssel; er kommt im nächsten Schritt in die Seite, und dort ist er sicher, weil die Liste ihn schützt (Origins).

3. Die Seite schreiben

Legen Sie einen Ordner für das Repository an, darin einen Ordner site/ mit den drei Dateien unten:

mkdir -p your-venue-site/site && cd your-venue-site && git init -b main

site/index.html lädt das SDK vom CDN, festgelegt auf eine exakte Version mit ihrem Integritäts-Hash, und das kleine Script, das das Widget rendert:

<!doctype html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Tisch reservieren</title>
</head>
<body>
  <main>
    <h1>Reservieren Sie Ihren Tisch</h1>
    <div id="bookdineplay-widget"></div>
  </main>
  <script
    src="https://cdn.bookdineplay.com/sdk/0.8.0/bookdineplay.js"
    integrity="sha384-jWkVHY/3ODRIOP4AZxnLryBhQa58r73TbB8ZBp+1YGqTk++mutYPqmFp53yUIt9p"
    crossorigin="anonymous"></script>
  <script src="booking.js"></script>
</body>
</html>

Der integrity-Wert ist der Hash, der neben dieser Version veröffentlicht ist – prüfen Sie ihn selbst mit:

curl -s https://cdn.bookdineplay.com/sdk/0.8.0/sri.txt

Es ist eine sha384-…-Zeichenkette. Der Browser führt das Script nicht aus, wenn auch nur ein Byte abweicht – und weil sich der Pfad einer exakten Version nie ändert, wird das nie passieren (Eine exakte Version festlegen). Für ein späteres Upgrade ändern Sie Version in src und Hash zusammen.

site/booking.js rendert das Widget. Es ist eine eigene Datei statt eines Inline-<script>, damit die Content Security Policy unten streng bleiben kann:

window.BookDinePlay.renderBookingWidget({
  container: '#bookdineplay-widget',
  venueSlug: 'your-venue',
  apiBaseUrl: 'https://api.bookdineplay.com',
  publishableKey: 'bdp_pk_your_publishable_key',
  resourceTypes: ['RestaurantTable', 'BilliardTable', 'DartBoard']
});

site/staticwebapp.config.json ergänzt Antwort-Header für jede Datei, die die App ausliefert. Diese Policy erlaubt Scripts von Ihrer Seite und dem CDN, Anfragen nur an die BookDinePlay-API und die Inline-Styles, die das Widget in seine Shadow-Wurzel einfügt (Content Security Policy):

{
  "globalHeaders": {
    "Content-Security-Policy": "default-src 'self'; script-src 'self' https://cdn.bookdineplay.com; connect-src https://api.bookdineplay.com; style-src 'self' 'unsafe-inline'",
    "X-Content-Type-Options": "nosniff"
  }
}

Für eine Vorschau liefern Sie site/ über einen beliebigen lokalen Webserver aus und öffnen die Seite über http://localhost – der Schlüssel erlaubt jeden localhost-Port. Die Datei direkt zu öffnen (file://) sendet Origin: null und wird abgelehnt. Dann committen:

git add . && git commit -m "Booking page"

4. Aus GitHub Actions ausrollen

Legen Sie das Repository auf GitHub an, lesen Sie das Deployment-Token der App aus Azure und hinterlegen Sie es als Repository-Secret – es taucht nie im Repository selbst auf:

gh repo create your-venue-site --private --source . --push
az staticwebapp secrets list --name "$APP" --resource-group "$RG" --query "properties.apiKey" -o tsv \
  | gh secret set AZURE_STATIC_WEB_APPS_API_TOKEN

.github/workflows/deploy-site.yml lädt den Ordner site/ bei jedem Push auf main unverändert hoch:

name: Deploy venue site

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          action: upload
          app_location: site
          output_location: ""
          skip_app_build: true

skip_app_build: true weist die Action an, app_location unverändert hochzuladen, statt etwas zu bauen; output_location muss dann leer sein. Committen Sie den Workflow und pushen Sie; der Lauf dauert etwa eine Minute:

git add .github && git commit -m "Deploy to Azure Static Web Apps" && git push
gh run list --limit 1

Öffnen Sie dann https://<hostname from step 1> – das Widget ist auf dem generierten Hostnamen live.

5. Ihre Domain darauf zeigen lassen

Legen Sie bei Ihrem DNS-Anbieter einen CNAME-Eintrag für www an, dessen Wert der Hostname aus Schritt 1 ist. Registrieren Sie die Domain dann bei der App; Azure prüft den Eintrag und stellt das Zertifikat aus:

az staticwebapp hostname set --name "$APP" --resource-group "$RG" --hostname www.your-venue.example

Die Prüfung wartet, bis DNS sich verbreitet hat – meist Minuten, höchstens die TTL des Eintrags. Die nackte Domain (your-venue.example ohne www) kann keinen CNAME tragen; sie braucht eine TXT-Prüfung (--validation-method dns-txt-token, dann az staticwebapp hostname show … --query validationToken für den Wert des Eintrags) und einen ALIAS-Eintrag – folgen Sie Set up an apex domain. Denken Sie daran, dass die nackte Domain eine eigene Origin ist: Sie muss in Schritt 2 ebenfalls auf der Liste des Schlüssels gestanden haben.

6. Die Live-Seite prüfen

Öffnen Sie https://www.your-venue.example. Das Widget sollte laden und nach der Wahl eines Datums Zeiten auflisten. Falls nicht:

  • Das Widget rendert, aber jede Anfrage scheitert mit 403 origin-not-allowed – diese Origin steht nicht auf der Liste des Schlüssels. Legen Sie einen neuen Schlüssel mit ihr an (Schritt 2) und rollen Sie mit dem neuen Schlüssel aus.
  • Das Script lädt nicht und die Konsole erwähnt integrity – der Hash gehört nicht zur Version in src. Führen Sie das curl aus Schritt 3 für genau diese Version erneut aus.
  • Die Konsole meldet einen Verstoß gegen die Content Security Policy – in staticwebapp.config.json fehlt ein Host; die beiden BookDinePlay-Hosts sind cdn.bookdineplay.com für das Script und api.bookdineplay.com für Anfragen.
  • hostname set wartet endlos – der CNAME hat sich noch nicht verbreitet; dig www.your-venue.example CNAME (oder nslookup) muss den Hostnamen aus Schritt 1 liefern, bevor Azure ihn prüfen kann.

Nächste Schritte

  • Buchungsablauf – was die gerade ausgerollte Seite bei jedem Klick tut.
  • Theming – die Farben der Location auf dem Widget.
  • CDN – wie Sie Ihre festgelegte Version bewegen, wenn die nächste SDK-Version erscheint.