diff --git a/app/README.md b/app/README.md
index 2fb12db7..52e34eec 100644
--- a/app/README.md
+++ b/app/README.md
@@ -1 +1,5 @@
-See https://github.com/GoogleCloudPlatform/avocano
+This application uses three containers images:
+
+ * `client`: https://github.com/GoogleCloudPlatform/avocano/tree/main/client
+ * `server`: https://github.com/GoogleCloudPlatform/avocano/tree/main/server
+ * `placeholder`: [placeholder/](placeholder/)
diff --git a/app/placeholder/Dockerfile b/app/placeholder/Dockerfile
new file mode 100644
index 00000000..cfce24d4
--- /dev/null
+++ b/app/placeholder/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Execute with "docker run --build-arg PROJECT_ID=$PROJECT_ID ..."
+ARG PROJECT_ID=YOURPROJECTID
+FROM gcr.io/$PROJECT_ID/firebase
+
+COPY . ./
+ENTRYPOINT ./placeholder-deploy.sh
diff --git a/app/placeholder/README.md b/app/placeholder/README.md
new file mode 100644
index 00000000..4717b828
--- /dev/null
+++ b/app/placeholder/README.md
@@ -0,0 +1,11 @@
+# Placeholder
+
+This folder is designed to hold a static page that can be deployed to Firebase as a placeholder until the real website is deployed.
+
+Features:
+
+ * replaces the Firebase Hosting "Site Not Found" 404 page with a placeholder
+ * page set to automatically refresh every 5 seconds
+ * uses embedded image (like the "Site Not Found" does) to prevent image loading flickering.
+
+This placeholder is built in `placeholder-image.cloudbuild.json`, automatically built and deployed using Cloud Build triggers for use in the Jump Start Solution terraform.
diff --git a/app/placeholder/dist/index.html b/app/placeholder/dist/index.html
new file mode 100644
index 00000000..c0455536
--- /dev/null
+++ b/app/placeholder/dist/index.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+

+
+
Your application is still deploying...
+
+
You can check the status of your deployment by checking your
+ Cloud Run jobs.
+
+
This page will refresh automatically.
+
+
+
+
+
+
diff --git a/app/placeholder/firebase.json b/app/placeholder/firebase.json
new file mode 100644
index 00000000..76683fd0
--- /dev/null
+++ b/app/placeholder/firebase.json
@@ -0,0 +1,5 @@
+{
+ "hosting": {
+ "public": "dist"
+ }
+}
diff --git a/app/placeholder/placeholder-deploy.sh b/app/placeholder/placeholder-deploy.sh
new file mode 100755
index 00000000..81fc7172
--- /dev/null
+++ b/app/placeholder/placeholder-deploy.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Script to assist in Dockerfile-based deployments.
+# any errors? exit immediately.
+set -e
+
+echo "Deploying placeholder to Firebase..."
+
+firebase deploy --project "$PROJECT_ID" --only hosting
diff --git a/app/placeholder/placeholder-image.cloudbuild.yaml b/app/placeholder/placeholder-image.cloudbuild.yaml
new file mode 100644
index 00000000..1c81882a
--- /dev/null
+++ b/app/placeholder/placeholder-image.cloudbuild.yaml
@@ -0,0 +1,38 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Build placeholder site code into container
+
+steps:
+ - id: build
+ name: "gcr.io/cloud-builders/docker"
+ dir: app/placeholder
+ args:
+ [
+ "build",
+ "--build-arg",
+ "PROJECT_ID=$PROJECT_ID",
+ "-t",
+ "gcr.io/$PROJECT_ID/$_IMAGE_NAME",
+ ".",
+ ]
+
+images:
+ - gcr.io/$PROJECT_ID/$_IMAGE_NAME
+
+substitutions:
+ _IMAGE_NAME: placeholder
+
+options:
+ dynamic_substitutions: true
diff --git a/infra/containers.tf b/infra/containers.tf
index 9e89732e..1fefdade 100644
--- a/infra/containers.tf
+++ b/infra/containers.tf
@@ -17,6 +17,7 @@
# Base images supplied pre-built.
locals {
- server_image = "gcr.io/${var.server_image_host}/server:${var.image_version}"
- client_image = "gcr.io/${var.client_image_host}/client:${var.image_version}"
+ server_image = "gcr.io/${var.server_image_host}/server:${var.image_version}"
+ client_image = "gcr.io/${var.client_image_host}/client:${var.image_version}"
+ placeholder_image = "gcr.io/hsa-public/avocano-placeholder:latest"
}
diff --git a/infra/jobs.tf b/infra/jobs.tf
index ae72982e..598513ef 100644
--- a/infra/jobs.tf
+++ b/infra/jobs.tf
@@ -136,3 +136,29 @@ resource "google_cloud_run_v2_job" "client" {
google_project_service.enabled
]
}
+
+
+resource "google_cloud_run_v2_job" "placeholder" {
+ name = var.random_suffix ? "placeholder-${random_id.suffix.hex}" : "placeholder"
+ location = var.region
+
+ labels = var.labels
+
+ template {
+ template {
+ service_account = google_service_account.client.email
+ containers {
+ image = local.placeholder_image
+ env {
+ name = "PROJECT_ID"
+ value = var.project_id
+ }
+
+ }
+ }
+ }
+
+ depends_on = [
+ google_project_service.enabled
+ ]
+}
diff --git a/infra/postdeployment.tf b/infra/postdeployment.tf
index 491f19d8..2007eb0a 100644
--- a/infra/postdeployment.tf
+++ b/infra/postdeployment.tf
@@ -51,7 +51,7 @@ resource "google_compute_instance" "gce_init" {
name = var.random_suffix ? "head-start-initialize-${random_id.suffix.hex}" : "head-start-initialize"
machine_type = "n1-standard-1"
zone = var.zone
- desired_status = "RUNNING"
+ desired_status = "RUNNING" # https://github.com/GoogleCloudPlatform/terraform-dynamic-python-webapp/pull/75#issuecomment-1547198414
allow_stopping_for_update = true
@@ -91,3 +91,49 @@ curl ${local.server_url}/api/products/?warmup
shutdown -h now
EOT
}
+
+
+resource "google_compute_instance" "placeholder_init" {
+ count = var.init ? 1 : 0
+
+ depends_on = [
+ google_project_service.enabled,
+ google_cloud_run_v2_job.placeholder,
+ ]
+
+ name = var.random_suffix ? "placeholder-initialize-${random_id.suffix.hex}" : "placeholder-initialize"
+ machine_type = "n1-standard-1"
+ zone = var.zone
+
+ allow_stopping_for_update = true
+
+ boot_disk {
+ initialize_params {
+ image = "debian-cloud/debian-11"
+ }
+ }
+
+ network_interface {
+ network = google_compute_network.gce_init[0].self_link
+ subnetwork = google_compute_subnetwork.gce_init[0].self_link
+
+ access_config {
+ // Ephemeral public IP
+ }
+ }
+
+ service_account {
+ email = google_service_account.compute[0].email
+ scopes = ["cloud-platform"] # TODO: Restrict??
+ }
+
+ metadata_startup_script = <