Web UI
The briefing app ships a single-page application in the web/ directory, hosted on AWS Amplify
AWS Amplify — a managed hosting service for static web applications. Used to host the briefing UI SPA. . Terraform handles config injection and deployment automatically — you only need to run terraform apply.
SPA structure
Section titled “SPA structure”The web/ directory contains a static frontend with no build step:
| File | Purpose |
|---|---|
index.html | Main HTML shell — loads app.js and styles.css |
app.js | Application logic — auth flow, API calls, rendering |
styles.css | UI styling |
config.template.js | Configuration template with placeholders for Terraform outputs |
Config injection
Section titled “Config injection”The SPA needs runtime values (API endpoint, Cognito
Amazon Cognito — a user authentication service providing user pools, JWT tokens, and group-based authorization. pool ID, etc.) that only exist after Terraform
HashiCorp Terraform — infrastructure-as-code tool used to provision all AWS resources in this demo. provisions the infrastructure. A template file bridges this gap.
Template placeholders
Section titled “Template placeholders”window.APP_CONFIG = { apiEndpoint: "__API_ENDPOINT__", cognitoPoolId: "__COGNITO_POOL_ID__", cognitoClientId: "__COGNITO_CLIENT_ID__", region: "__REGION__",};Generated config
Section titled “Generated config”During terraform apply, the templatefile() function replaces placeholders with actual values:
resource "local_file" "web_config" { content = templatefile("${path.module}/web/config.template.js", { __API_ENDPOINT__ = aws_apigatewayv2_stage.api.invoke_url __COGNITO_POOL_ID__ = aws_cognito_user_pool.pool.id __COGNITO_CLIENT_ID__ = aws_cognito_user_pool_client.client.id __REGION__ = var.region }) filename = "${path.module}/web/config.js"}The resulting config.js is a plain JavaScript file that the SPA loads at runtime — no environment variables or build-time bundling needed.
Amplify hosting
Section titled “Amplify hosting”Terraform provisions the Amplify
AWS Amplify — a managed hosting service for static web applications. Used to host the briefing UI SPA. app and branch for manual deployment (no auto-build from the repository):
resource "aws_amplify_app" "web" { name = "${var.project_name}-web"}
resource "aws_amplify_branch" "main" { app_id = aws_amplify_app.web.id branch_name = "main"}Deploy script
Section titled “Deploy script”The scripts/deploy-web.sh script packages the web/ directory and uploads it to Amplify:
#!/bin/bash# 1. Create a zip archive of web/ contents (including generated config.js)# 2. Start a new Amplify deployment# 3. Upload the zip to the deployment URL# 4. Wait for deployment to complete
APP_ID="$1"BRANCH_NAME="$2"
cd web/zip -r /tmp/web-deploy.zip .
DEPLOY_URL=$(aws amplify create-deployment \ --app-id "$APP_ID" \ --branch-name "$BRANCH_NAME" \ --query 'zipUploadUrl' --output text)
curl -T /tmp/web-deploy.zip "$DEPLOY_URL"Terraform invokes this script via a null_resource:
resource "null_resource" "deploy_web" { triggers = { web_hash = sha256(join("", [for f in fileset("web/", "**") : filesha256("web/${f}")])) config_hash = sha256(local_file.web_config.content) }
provisioner "local-exec" { command = "bash scripts/deploy-web.sh ${aws_amplify_app.web.id} main" }
depends_on = [local_file.web_config]}The triggers block re-runs the script whenever:
- Any file in
web/changes (source code updates) - The generated
config.jscontent changes (infrastructure changes like a new API endpoint)
Accessing the UI
Section titled “Accessing the UI”After deployment completes, get the app URL from Terraform outputs:
terraform output -raw app_urlOpen the URL in a browser and sign in with your Cognito credentials (see Cognito Users).
Redeployment
Section titled “Redeployment”Automatic
Section titled “Automatic”Redeployment triggers automatically on the next terraform apply when:
- You modify any file in the
web/directory - Infrastructure changes cause
config.jsto regenerate (e.g., new API Gateway stage, different region)
Manual
Section titled “Manual”Force a redeployment without changing any source files:
terraform apply -replace=null_resource.deploy_web