Skip to content

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.

The web/ directory contains a static frontend with no build step:

FilePurpose
index.htmlMain HTML shell — loads app.js and styles.css
app.jsApplication logic — auth flow, API calls, rendering
styles.cssUI styling
config.template.jsConfiguration template with placeholders for Terraform outputs

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.

web/config.template.js
window.APP_CONFIG = {
apiEndpoint: "__API_ENDPOINT__",
cognitoPoolId: "__COGNITO_POOL_ID__",
cognitoClientId: "__COGNITO_CLIENT_ID__",
region: "__REGION__",
};

During terraform apply, the templatefile() function replaces placeholders with actual values:

main.tf
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.

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):

amplify.tf
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"
}

The scripts/deploy-web.sh script packages the web/ directory and uploads it to Amplify:

scripts/deploy-web.sh
#!/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:

deploy.tf
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.js content changes (infrastructure changes like a new API endpoint)

After deployment completes, get the app URL from Terraform outputs:

Terminal window
terraform output -raw app_url

Open the URL in a browser and sign in with your Cognito credentials (see Cognito Users).

Redeployment triggers automatically on the next terraform apply when:

  • You modify any file in the web/ directory
  • Infrastructure changes cause config.js to regenerate (e.g., new API Gateway stage, different region)

Force a redeployment without changing any source files:

Terminal window
terraform apply -replace=null_resource.deploy_web