PRD Document · Savoy Signature Hotels — Multi-Site Headless Platform
Version: 1.0 · Date: 2026-03-04
Related docs: 01_General_Architecture.md, A05_Environment_Config.md
This document specifies the infrastructure services, environment topology, CI/CD pipelines, monitoring strategy, and operational procedures for the Savoy Signature multi-site platform.
All services are hosted on Microsoft Azure with Cloudflare as the edge/CDN layer.
Azure — Resource Group: rg-savoy-prod
Service SKU / Tier Purpose Notes App Service (Next.js) P1v3 or P2v3 Next.js SSR application Auto-scale based on CPU/memory; Node.js 20.9+ LTS App Service (Umbraco) P1v3 or P2v3 Umbraco 17 CMS (headless) .NET 10 LTS runtime; always-on enabled Azure SQL Database Standard S2 (50 DTU) or General Purpose Umbraco content database Geo-redundant backup; auto-tuning Blob Storage Standard GRS / Hot tier Media files (images, PDFs, videos) CDN-fronted; lifecycle policies for unused media Application Insights Pay-as-you-go APM for both apps Distributed tracing, custom metrics Log Analytics Pay-as-you-go Centralized logging KQL queries, alerts, dashboards Key Vault Standard Secrets management Connection strings, API keys, certificates Virtual Network — Network isolation Private endpoints for SQL and Blob
The platform uses 4 environments following a promotion pipeline:
Note: DEV and STAGE are internal WYcreative environments hosted under wycreative.com. STAGE may be shared with the client team during initial phases for testing and validation.
Environment Purpose Domain Pattern Azure Resource Group Cloudflare Auto-deploy DEV Active development, feature testing savoy-dev-*.wycreative.comrg-savoy-devEnabled (proxied, performance monitoring) PR from develop → deploy/dev (CI + 1 approver) STAGE QA, client review, UAT savoy.stage-*.wycreative.comrg-savoy-stageEnabled (test cache behavior) On PR merge to staging QA Pre-production validation, performance testing qa-*.savoysignature.comrg-savoy-qaEnabled (production-like) Manual promotion PROD Live production sites *.savoysignature.com / hotelnext.ptrg-savoy-prodEnabled (full caching) Manual promotion with approval
Site DEV Domain STAGE Domain Savoy Signature savoy-dev-signature.wycreative.comsavoy-stage-signature.wycreative.comSavoy Palace savoy-dev-palace.wycreative.comsavoy-stage-palace.wycreative.comRoyal Savoy savoy-dev-royal.wycreative.comsavoy-stage-royal.wycreative.comSaccharum savoy-dev-saccharum.wycreative.comsavoy-stage-saccharum.wycreative.comThe Reserve savoy-dev-reserve.wycreative.comsavoy-stage-reserve.wycreative.comCalheta Beach savoy-dev-calheta.wycreative.comsavoy-stage-calheta.wycreative.comGardens savoy-dev-gardens.wycreative.comsavoy-stage-gardens.wycreative.comHotel Next savoy-dev-next.wycreative.comsavoy-stage-next.wycreative.comUmbraco CMS savoy-dev-cms.wycreative.comsavoy-stage-cms.wycreative.com
Note: DEV domains use 1-level subdomains (savoy-dev-* not savoy.dev-*) because Cloudflare Universal SSL only covers *.wycreative.com (one level). All DEV domains are proxied via Cloudflare for performance monitoring (Observatory + GraphQL Analytics).
Variable DEV STAGE QA PROD UMBRACO_API_URLhttps://savoy-dev-cms.wycreative.comhttps://savoy.stage-cms.wycreative.comhttps://qa-cms.savoysignature.comhttps://cms.savoysignature.comCLOUDFLARE_ZONE_IDZone ID Zone ID Zone ID Zone ID CLOUDFLARE_API_TOKENToken Token Token Token GATE_ENABLEDtruetruetruefalseGATE_SECRETSecret Secret Secret — GATE_COOKIE_DOMAIN.wycreative.com.wycreative.com— — NODE_ENVdevelopmentstagingproductionproductionREVALIDATE_SECRETdev-secret stage-secret qa-secret prod-secret NEXT_PUBLIC_GA_ID— — — G-XXXXXXXXXXAPPINSIGHTS_KEYKey Key Key Key
Full configuration reference in A05_Environment_Config.md
│ ├── feature/SAVOY-123-hero-module
│ ├── feature/SAVOY-456-booking-bar
│ └── fix/SAVOY-789-cache-headers
Branch Environment Trigger Protection feature/*, fix/*Local / Preview — — developIntegration PR merge (no CI, merge freely) — deploy/devDEV PR from develop 1 approval, CI pass, squash merge stagingSTAGE → QA PR merge from develop 2 approvals, CI pass mainPROD PR merge from staging 2 approvals, QA sign-off, CI pass
The pipeline includes a unique AI QA Agent step between CI and CD. This agent runs on a local Mac using openClaw (Agentic AI) and performs comprehensive automated quality assurance before any deployment.
CD — On Merge (if AI QA passes)
AI QA — openClaw Agent on Local Mac
Visual Regression (Pixel Perfect)
The openClaw AI QA Agent runs on a dedicated local Mac and acts as an automated quality gate between CI and CD:
Step Description Tools / Metrics PR Pickup Monitors the Git repository for new PRs targeting develop, staging, or main GitHub/Azure DevOps API Performance Tests Runs Lighthouse CI on all changed pages, checks Core Web Vitals thresholds Lighthouse CI (LCP < 2.5s, FID < 100ms, CLS < 0.1) Accessibility Audit Full WCAG 2.1 AA audit on all changed components and pages axe-core, Playwright accessibility testing Visual Regression Pixel-perfect comparison against Figma designs and baseline screenshots Chromatic / Percy / custom screenshot diffing UI/UX Validation Validates responsive behavior, interaction states, navigation flows Playwright E2E tests across viewports Comment & Report Posts detailed review comments on the PR (GitHub/Azure DevOps) and updates the corresponding task in Zoho Project API integrations Gate Decision If all checks pass → PR is approved for merge → CD proceeds. If any check fails → PR is blocked with detailed feedback Automated approval/rejection
Important: The AI QA Agent does NOT replace human code review. It runs in parallel with human review, providing automated quality assurance feedback. The PR still requires human approval per branch protection rules.
Full testing strategy and AI QA Agent specification in 18_QA_and_Testing.md
# Pseudo-pipeline definition (Azure DevOps / GitHub Actions)
branches : [ develop , staging , main ]
- uses : actions/checkout@v4
- uses : pnpm/action-setup@v4
- run : pnpm install --frozen-lockfile
- run : pnpm test --coverage
- run : pnpm test:e2e # Playwright
- run : pnpm build:storybook
# AI QA Agent (openClaw) picks up the PR after CI passes
# Runs on local Mac — not part of the cloud CI/CD pipeline
# See section 4.3 for details
if : github.event_name == 'push' && ai_qa_approved == true
- run : # Deploy to target environment
- run : # Purge Cloudflare cache (STAGE/PROD only)
Umbraco deployments are separate from frontend deployments:
Aspect Approach Schema Changes Umbraco Deploy or manual migration scripts Content Not deployed — lives in database, managed by editors Code Changes .NET build + deploy to App Service via CI/CD Database Migrations EF Core migrations, run automatically on startup
Tool Purpose Scope Azure Application Insights APM, request tracing, exceptions, custom metrics Next.js + Umbraco Azure Log Analytics Centralized log aggregation, KQL queries All Azure resources Cloudflare Analytics Edge traffic, cache hit rate, WAF events CDN layer Azure Monitor Alerts Proactive alerting on thresholds All services Uptime Robot / Azure Availability Tests Uptime monitoring for all 8 sites External
Metric Threshold Alert Response Time (P95) > 2s Warning Response Time (P95) > 5s Critical Error Rate (5xx) > 1% Critical Cache Hit Rate < 80% Warning CPU Usage (App Service) > 85% for 5min Warning Memory Usage > 90% Critical SQL DTU Usage > 80% Warning Blob Storage Size > 80% capacity Warning SSL Certificate Expiry < 30 days Warning
Layer Log Destination Retention Next.js Application Insights + stdout 90 days Umbraco Application Insights + Umbraco logs 90 days Cloudflare Cloudflare Logs (Pro — via Logpush or API) 30 days Azure SQL Azure Diagnostics 30 days CI/CD Pipeline logs 90 days
Component Strategy Next.js Azure App Service auto-scale: min 2, max 6 instances based on CPU > 70% Umbraco Single instance (headless API, low traffic — most requests served from edge cache) SQL Elastic pool or scale up DTUs as needed
Scenario Action Sustained CPU > 85% Upgrade App Service plan tier Frequent SQL timeouts Upgrade SQL tier or add read replica Blob throughput limits Enable CDN for blob, premium tier
Aspect Strategy RTO RPO Database Azure SQL geo-replication + point-in-time restore 1h 5min Blob Storage GRS (Geo-Redundant Storage) — automatic failover 1h 0 App Services Deploy from CI/CD to secondary region 2h 0 (code in Git) Cloudflare Global anycast — inherent redundancy — — Configuration Key Vault with backup enabled 1h 0
Resource Frequency Retention Azure SQL Continuous (PITR) 35 days Blob Storage GRS replication Continuous App Service Config Key Vault snapshots 90 days Git Repository GitHub / Azure DevOps Indefinite
Measure Implementation Network Isolation VNet integration for App Services; private endpoints for SQL and Blob Secrets Azure Key Vault for all secrets; no secrets in source code (local dev uses .env.local, CI uses GitHub Actions Secrets, Azure uses Key Vault) SSL/TLS Cloudflare Full (Strict); TLS 1.2 minimum Backoffice Access IP whitelist + Azure AD / MFA WAF Cloudflare managed rules + custom rules for bot protection DDoS Cloudflare DDoS protection (included)
Full security specification in 15_Security.md
Service Monthly Estimate (EUR) Notes App Service (Next.js) × 4 envs ~€200–400 P1v3 for PROD, B1 for DEV/STAGE App Service (Umbraco) × 4 envs ~€200–400 P1v3 for PROD, B1 for DEV/STAGE Azure SQL × 4 envs ~€150–300 S2 for PROD, Basic for DEV Blob Storage ~€20–50 Depends on media volume Application Insights ~€50–100 Based on data ingestion Key Vault ~€5 Minimal Cloudflare ~€0–200 Pro or Business plan Total ~€625–1,450/mo Varies by tier selection
These are estimates. Actual costs depend on traffic, media volume, and scaling.
Next document: 03_MultiSite_and_Domains.md