diff --git a/site/app/styles/_overrides.scss b/site/app/styles/_overrides.scss
index 89712aabd..8ac3f609c 100644
--- a/site/app/styles/_overrides.scss
+++ b/site/app/styles/_overrides.scss
@@ -32,6 +32,7 @@ $color-architecture-patterns: #097e89;
$color-data-applications: #282A72;
$color-data-exchange: #282A72;
@include codelab-card(['getting-started'], $color-getting-started, '');
+@include codelab-card(['cybersecurity'], $color-getting-started, '');
@include codelab-card(['resource-optimization'], $color-resource-optimization, '');
@include codelab-card(['architecture-patterns'], $color-architecture-patterns, '');
@include codelab-card(['demos'], $color-demos, '');
diff --git a/site/sfguides/src/_template/markdown.template b/site/sfguides/src/_template/markdown.template
index 01805479f..d108064cc 100644
--- a/site/sfguides/src/_template/markdown.template
+++ b/site/sfguides/src/_template/markdown.template
@@ -1,7 +1,7 @@
author: AUTHOR_NAME
id: SFGUIDE_NAME
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/a_faster_path_to_operational_ai_with_continual_and_snowflake/a_faster_path_to_operational_ai_with_continual_and_snowflake.md b/site/sfguides/src/a_faster_path_to_operational_ai_with_continual_and_snowflake/a_faster_path_to_operational_ai_with_continual_and_snowflake.md
index 24cb7f90f..8694839ab 100644
--- a/site/sfguides/src/a_faster_path_to_operational_ai_with_continual_and_snowflake/a_faster_path_to_operational_ai_with_continual_and_snowflake.md
+++ b/site/sfguides/src/a_faster_path_to_operational_ai_with_continual_and_snowflake/a_faster_path_to_operational_ai_with_continual_and_snowflake.md
@@ -1,7 +1,7 @@
author: b-mckenna
id: A Faster Path to Operational AI with Continual and Snowflake
summary: Build an operational, continually updating predictive model for customer churn with Snowflake and Continual
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/a_postman_tutorial_for_snowflake_sql_api/a_postman_tutorial_for_snowflake_sql_api.md b/site/sfguides/src/a_postman_tutorial_for_snowflake_sql_api/a_postman_tutorial_for_snowflake_sql_api.md
index fd9a545ac..92cd08520 100644
--- a/site/sfguides/src/a_postman_tutorial_for_snowflake_sql_api/a_postman_tutorial_for_snowflake_sql_api.md
+++ b/site/sfguides/src/a_postman_tutorial_for_snowflake_sql_api/a_postman_tutorial_for_snowflake_sql_api.md
@@ -1,7 +1,7 @@
author: Joyce
id: a_postman_tutorial_for_snowflake_sql_api
summary: Explore the Snowflake SQL API with Postman
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/loopDelicious/sfquickstarts
diff --git a/site/sfguides/src/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab.md b/site/sfguides/src/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab.md
index 1c2af25d1..608148895 100644
--- a/site/sfguides/src/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab.md
+++ b/site/sfguides/src/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab.md
@@ -1,7 +1,7 @@
authors: Bobby Birstock, Amy Chen
id: accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab
summary: Build a dbt project and data pipeline with dbt Cloud and Snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/attaining_consumer_insights_with_snowflake_microsoft_power_bi/attaining_consumer_insights_with_snowflake_microsoft_power_bi.md b/site/sfguides/src/attaining_consumer_insights_with_snowflake_microsoft_power_bi/attaining_consumer_insights_with_snowflake_microsoft_power_bi.md
index f99cb67a7..1fdfbf864 100644
--- a/site/sfguides/src/attaining_consumer_insights_with_snowflake_microsoft_power_bi/attaining_consumer_insights_with_snowflake_microsoft_power_bi.md
+++ b/site/sfguides/src/attaining_consumer_insights_with_snowflake_microsoft_power_bi/attaining_consumer_insights_with_snowflake_microsoft_power_bi.md
@@ -1,6 +1,6 @@
summary: In this lab, you’ll learn how to access all relevant data from a single source and turn data into insights through the Microsoft PowerBI integration.
id: attaining_consumer_insights_with_snowflake_and_microsoft_power_bi
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/automated_machine_learning_with_snowflake_and_datarobot/automl_with_snowflake_and_datarobot.md b/site/sfguides/src/automated_machine_learning_with_snowflake_and_datarobot/automl_with_snowflake_and_datarobot.md
index 67f3749c7..c900b8b85 100644
--- a/site/sfguides/src/automated_machine_learning_with_snowflake_and_datarobot/automl_with_snowflake_and_datarobot.md
+++ b/site/sfguides/src/automated_machine_learning_with_snowflake_and_datarobot/automl_with_snowflake_and_datarobot.md
@@ -1,7 +1,7 @@
author: miles.adkins@snowflake.com
id: automl_with_snowflake_and_datarobot
summary: This lab will walk you through how to use Snowflake and DataRobot to perform supervised machine learning.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/build_2021_journey_to_processing_pii/build_2021_journey_to_processing_pii.md b/site/sfguides/src/build_2021_journey_to_processing_pii/build_2021_journey_to_processing_pii.md
index bba0b1e2a..ed48d9497 100644
--- a/site/sfguides/src/build_2021_journey_to_processing_pii/build_2021_journey_to_processing_pii.md
+++ b/site/sfguides/src/build_2021_journey_to_processing_pii/build_2021_journey_to_processing_pii.md
@@ -1,7 +1,7 @@
author: sanderiam
id: getting_started_with_pii
summary: Learn how to process PII data using Snowflake RBAC, DAC, Row Access Policies, and Column Level Security
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/build_a_custom_api_in_java_on_aws/build_a_custom_api_in_java_on_aws.md b/site/sfguides/src/build_a_custom_api_in_java_on_aws/build_a_custom_api_in_java_on_aws.md
index acefc1322..89b3eca03 100644
--- a/site/sfguides/src/build_a_custom_api_in_java_on_aws/build_a_custom_api_in_java_on_aws.md
+++ b/site/sfguides/src/build_a_custom_api_in_java_on_aws/build_a_custom_api_in_java_on_aws.md
@@ -1,7 +1,7 @@
author: Brad Culberson
id: build_a_custom_api_in_java_on_aws
summary: A guide to building and running a custom API (in Java) Powered by Snowflake and AWS
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/build_a_custom_api_in_python_on_aws/build_a_custom_api_in_python_on_aws.md b/site/sfguides/src/build_a_custom_api_in_python_on_aws/build_a_custom_api_in_python_on_aws.md
index 32b3a1677..8aa0e0536 100644
--- a/site/sfguides/src/build_a_custom_api_in_python_on_aws/build_a_custom_api_in_python_on_aws.md
+++ b/site/sfguides/src/build_a_custom_api_in_python_on_aws/build_a_custom_api_in_python_on_aws.md
@@ -1,7 +1,7 @@
author: Brad Culberson
id: build_a_custom_api_in_python_on_aws
summary: A guide to building and running a custom API (in Python) Powered by Snowflake and AWS
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/build_an_ad_tag_in_python_on_aws/build_an_ad_tag_in_python_on_aws.md b/site/sfguides/src/build_an_ad_tag_in_python_on_aws/build_an_ad_tag_in_python_on_aws.md
index ab58c2222..4983b56a8 100644
--- a/site/sfguides/src/build_an_ad_tag_in_python_on_aws/build_an_ad_tag_in_python_on_aws.md
+++ b/site/sfguides/src/build_an_ad_tag_in_python_on_aws/build_an_ad_tag_in_python_on_aws.md
@@ -1,7 +1,7 @@
author: Jim Warner
id: build_an_ad_tag_in_python_on_aws
summary: A guide to building and running a simple ad tag (in Python) Powered by Snowflake and AWS
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/cloud_native_data_engineering_with_matillion_and_snowflake/cloud_native_data_engineering_with_matillion_and_snowflake.md b/site/sfguides/src/cloud_native_data_engineering_with_matillion_and_snowflake/cloud_native_data_engineering_with_matillion_and_snowflake.md
index 92c053169..7eefdd029 100644
--- a/site/sfguides/src/cloud_native_data_engineering_with_matillion_and_snowflake/cloud_native_data_engineering_with_matillion_and_snowflake.md
+++ b/site/sfguides/src/cloud_native_data_engineering_with_matillion_and_snowflake/cloud_native_data_engineering_with_matillion_and_snowflake.md
@@ -1,6 +1,6 @@
author: Ripu Jain, Yaser Najafi
id: cloud_native_data_engineering_with_matillion_and_snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/cross_cloud_business_continuity/cross_cloud_business_continuity.md b/site/sfguides/src/cross_cloud_business_continuity/cross_cloud_business_continuity.md
index 643a78d4d..f0e19e565 100644
--- a/site/sfguides/src/cross_cloud_business_continuity/cross_cloud_business_continuity.md
+++ b/site/sfguides/src/cross_cloud_business_continuity/cross_cloud_business_continuity.md
@@ -1,7 +1,7 @@
author: Prateek Parashar
id: cross_cloud_business_continuity
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_app/data_app.md b/site/sfguides/src/data_app/data_app.md
index bd0dd3648..ebacca8f8 100644
--- a/site/sfguides/src/data_app/data_app.md
+++ b/site/sfguides/src/data_app/data_app.md
@@ -1,6 +1,6 @@
summary: Building a Single-Page Data Application on Snowflake
id: data_app
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_apps_summit_lab/data_apps_summit_lab.md b/site/sfguides/src/data_apps_summit_lab/data_apps_summit_lab.md
index 2ff60bf77..afc69d994 100644
--- a/site/sfguides/src/data_apps_summit_lab/data_apps_summit_lab.md
+++ b/site/sfguides/src/data_apps_summit_lab/data_apps_summit_lab.md
@@ -1,7 +1,7 @@
author:
id: data_apps_summit_lab
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_engineering_with_apache_airflow/data_engineering_with_apache_airflow.md b/site/sfguides/src/data_engineering_with_apache_airflow/data_engineering_with_apache_airflow.md
index 7e56be270..e6db736af 100644
--- a/site/sfguides/src/data_engineering_with_apache_airflow/data_engineering_with_apache_airflow.md
+++ b/site/sfguides/src/data_engineering_with_apache_airflow/data_engineering_with_apache_airflow.md
@@ -1,7 +1,7 @@
author: Adrian Lee
id: data_engineering_with_apache_airflow
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_science_with_dataiku/data_science_with_dataiku.md b/site/sfguides/src/data_science_with_dataiku/data_science_with_dataiku.md
index 0ba649cae..0ecc24a24 100644
--- a/site/sfguides/src/data_science_with_dataiku/data_science_with_dataiku.md
+++ b/site/sfguides/src/data_science_with_dataiku/data_science_with_dataiku.md
@@ -1,6 +1,6 @@
summary: Accelerating Data Science with Snowflake and Dataiku
id: data_science_with_dataiku
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
Feedback Link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_science_with_dataiku_kr/data_science_with_dataiku_kr.md b/site/sfguides/src/data_science_with_dataiku_kr/data_science_with_dataiku_kr.md
index 1a4967adb..882fc1778 100644
--- a/site/sfguides/src/data_science_with_dataiku_kr/data_science_with_dataiku_kr.md
+++ b/site/sfguides/src/data_science_with_dataiku_kr/data_science_with_dataiku_kr.md
@@ -1,6 +1,6 @@
summary: Snowflake 및 Dataiku로 데이터 과학 가속화
id: data_science_with_dataiku_kr
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
Feedback Link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_teams_with_dbt_cloud/data_teams_with_dbt_cloud.md b/site/sfguides/src/data_teams_with_dbt_cloud/data_teams_with_dbt_cloud.md
index b648ebcd4..97d07bf5c 100644
--- a/site/sfguides/src/data_teams_with_dbt_cloud/data_teams_with_dbt_cloud.md
+++ b/site/sfguides/src/data_teams_with_dbt_cloud/data_teams_with_dbt_cloud.md
@@ -1,6 +1,6 @@
id: data_teams_with_dbt_cloud
summary: Build your data pipeline with dbt Cloud & Snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/data_teams_with_dbt_core/data_teams_with_dbt_core.md b/site/sfguides/src/data_teams_with_dbt_core/data_teams_with_dbt_core.md
index 320f8ab32..cc081a8fc 100644
--- a/site/sfguides/src/data_teams_with_dbt_core/data_teams_with_dbt_core.md
+++ b/site/sfguides/src/data_teams_with_dbt_core/data_teams_with_dbt_core.md
@@ -1,6 +1,6 @@
id: data_teams_with_dbt_core
summary: Build your data pipeline with dbt Core & Snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/database_modeling_with_sqldbm/database_modeling_with_SqlDBM.md b/site/sfguides/src/database_modeling_with_sqldbm/database_modeling_with_SqlDBM.md
index b466f7dab..8ead1e411 100644
--- a/site/sfguides/src/database_modeling_with_sqldbm/database_modeling_with_SqlDBM.md
+++ b/site/sfguides/src/database_modeling_with_sqldbm/database_modeling_with_SqlDBM.md
@@ -1,6 +1,6 @@
summary: Begin modeling your Snowflake database online with SqlDBM
id: database_modeling_with_sqldbm
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/determining_warehouse_size/determining_warehouse_size.md b/site/sfguides/src/determining_warehouse_size/determining_warehouse_size.md
index 6f5012683..e4c465200 100644
--- a/site/sfguides/src/determining_warehouse_size/determining_warehouse_size.md
+++ b/site/sfguides/src/determining_warehouse_size/determining_warehouse_size.md
@@ -1,7 +1,7 @@
author: Lorena Diaconescu
id: determining_warehouse_size
summary: Determine the best warehouse size to use for your query
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/dota2_game_replay_parser/dota2_game_replay_parser.md b/site/sfguides/src/dota2_game_replay_parser/dota2_game_replay_parser.md
index a84ff64a9..25ddd8b3d 100644
--- a/site/sfguides/src/dota2_game_replay_parser/dota2_game_replay_parser.md
+++ b/site/sfguides/src/dota2_game_replay_parser/dota2_game_replay_parser.md
@@ -1,6 +1,6 @@
summary: Parse a Dota 2 game replay
id: dota2_game_replay_parser
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.html b/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.html
index ee937e259..46f9cd0c4 100644
--- a/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.html
+++ b/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.html
@@ -1,374 +1,374 @@
-
-
-
author: Prash Medirattaa
id: end_to_end_machine_learning_with_dataiku
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
@@ -1102,6 +1102,6 @@
Conclusion and Next Steps
Bonus Material - Snowpark -Python
Duration: 5
To be added soon
-
-
-
+
+
+
diff --git a/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.md b/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.md
index 54de3b758..379ab6edb 100644
--- a/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.md
+++ b/site/sfguides/src/end_to_end_machine_learning_with_dataiku/end_to_end_machine_learning_with_dataiku.md
@@ -1,7 +1,7 @@
author: Prash Medirattaa
id: end_to_end_machine_learning_with_dataiku
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/external-functions-aws/external-functions-aws.md b/site/sfguides/src/external-functions-aws/external-functions-aws.md
index aeaae15a9..9bb4babce 100644
--- a/site/sfguides/src/external-functions-aws/external-functions-aws.md
+++ b/site/sfguides/src/external-functions-aws/external-functions-aws.md
@@ -1,6 +1,6 @@
summary: Getting Started With External Functions on AWS
id: getting_started_external_functions_aws
-categories: Getting Started
+categories: Getting-Started
status: Published
Feedback Link: https://github.com/Snowflake-Labs/sfguides/issues
tags: Getting Started, SQL, Data Engineering, AWS, External Functions
diff --git a/site/sfguides/src/getting_started_datameer/lab_index.md b/site/sfguides/src/getting_started_datameer/lab_index.md
index b41f9916d..02b8adc82 100644
--- a/site/sfguides/src/getting_started_datameer/lab_index.md
+++ b/site/sfguides/src/getting_started_datameer/lab_index.md
@@ -1,7 +1,7 @@
author: seb_froh
id: getting_started_datameer
summary: This is a broad introduction of Datameer and covers how to start, load and transform data, and share insights.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_external_functions_azure/getting_started_external_functions_azure.md b/site/sfguides/src/getting_started_external_functions_azure/getting_started_external_functions_azure.md
index e24950efa..59410c5fa 100644
--- a/site/sfguides/src/getting_started_external_functions_azure/getting_started_external_functions_azure.md
+++ b/site/sfguides/src/getting_started_external_functions_azure/getting_started_external_functions_azure.md
@@ -1,6 +1,6 @@
id: getting_started_external_functions_azure
summary: Getting Started With External Functions on Azure
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_external_functions_gcc/getting_started_external_functions_gcc.md b/site/sfguides/src/getting_started_external_functions_gcc/getting_started_external_functions_gcc.md
index 503cbfbae..a2521a39d 100644
--- a/site/sfguides/src/getting_started_external_functions_gcc/getting_started_external_functions_gcc.md
+++ b/site/sfguides/src/getting_started_external_functions_gcc/getting_started_external_functions_gcc.md
@@ -1,6 +1,6 @@
summary: Getting Started With External Functions Using the Google Cloud Console
id: getting_started_external_functions_gcc
-categories: Getting Started
+categories: Getting-Started
status: Published
Feedback Link: https://github.com/Snowflake-Labs/sfguides/issues
tags: Getting Started, SQL, Data Engineering, GCC, External Functions
diff --git a/site/sfguides/src/getting_started_snowflake_sql_api/getting_started_snowflake_sql_api.md b/site/sfguides/src/getting_started_snowflake_sql_api/getting_started_snowflake_sql_api.md
index 23ae0dda9..955a0ef68 100644
--- a/site/sfguides/src/getting_started_snowflake_sql_api/getting_started_snowflake_sql_api.md
+++ b/site/sfguides/src/getting_started_snowflake_sql_api/getting_started_snowflake_sql_api.md
@@ -1,6 +1,6 @@
summary: Getting Started With Snowflake SQL API
id: getting_started_snowflake_sql_api
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Draft
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_snowflake_sql_api_kr/getting_started_snowflake_sql_api_kr.md b/site/sfguides/src/getting_started_snowflake_sql_api_kr/getting_started_snowflake_sql_api_kr.md
index 666ad2915..ab1ba3f44 100644
--- a/site/sfguides/src/getting_started_snowflake_sql_api_kr/getting_started_snowflake_sql_api_kr.md
+++ b/site/sfguides/src/getting_started_snowflake_sql_api_kr/getting_started_snowflake_sql_api_kr.md
@@ -1,6 +1,6 @@
id: getting_started_snowflake_sql_api_kr
summary: Snowflake SQL API 시작하기
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_snowpark_python_machine_learning/machine_learning_with_snowpark_credit_card_approval_prediction.md b/site/sfguides/src/getting_started_snowpark_python_machine_learning/machine_learning_with_snowpark_credit_card_approval_prediction.md
index 9beb4d234..a6059bff1 100644
--- a/site/sfguides/src/getting_started_snowpark_python_machine_learning/machine_learning_with_snowpark_credit_card_approval_prediction.md
+++ b/site/sfguides/src/getting_started_snowpark_python_machine_learning/machine_learning_with_snowpark_credit_card_approval_prediction.md
@@ -1,7 +1,7 @@
author: Michael Gorkow
id: getting_started_snowpark_machine_learning
summary: Machine Learning with Snowpark Python for Credit Card Approval Prediction
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_thoughtspot/getting_started_thoughtspot.md b/site/sfguides/src/getting_started_thoughtspot/getting_started_thoughtspot.md
index 1f4f0df00..d2b0c0881 100644
--- a/site/sfguides/src/getting_started_thoughtspot/getting_started_thoughtspot.md
+++ b/site/sfguides/src/getting_started_thoughtspot/getting_started_thoughtspot.md
@@ -1,7 +1,7 @@
author: Thoughtspot
id: getting_started_thoughtspot
summary: Build an interactive react app with ThoughtSpot and Snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_alation/getting_started_with_alation.md b/site/sfguides/src/getting_started_with_alation/getting_started_with_alation.md
index 5f1a1a4e9..40ee956f1 100644
--- a/site/sfguides/src/getting_started_with_alation/getting_started_with_alation.md
+++ b/site/sfguides/src/getting_started_with_alation/getting_started_with_alation.md
@@ -1,7 +1,7 @@
author: Michael Meyer
id: getting_started_with_alation
summary: This guide is used to help with the installation of the Alation Data Intelligence Platform. The walk-through consists of being able to find & trust data in your organization, how to actively govern data, and how Alation can help with when migrating data to Snowflake.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_geospatial_geography/getting_started_with_geospatial_geography.md b/site/sfguides/src/getting_started_with_geospatial_geography/getting_started_with_geospatial_geography.md
index a7ae0b067..53588aca1 100644
--- a/site/sfguides/src/getting_started_with_geospatial_geography/getting_started_with_geospatial_geography.md
+++ b/site/sfguides/src/getting_started_with_geospatial_geography/getting_started_with_geospatial_geography.md
@@ -1,7 +1,7 @@
author: Kevin McGinley
id: getting_started_with_geospatial_geography
summary: Getting Started with Geospatial - Geography
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_geospatial_geography_kr/getting_started_with_geospatial_geography_kr.md b/site/sfguides/src/getting_started_with_geospatial_geography_kr/getting_started_with_geospatial_geography_kr.md
index 2cf2e0522..31f8a9e8d 100644
--- a/site/sfguides/src/getting_started_with_geospatial_geography_kr/getting_started_with_geospatial_geography_kr.md
+++ b/site/sfguides/src/getting_started_with_geospatial_geography_kr/getting_started_with_geospatial_geography_kr.md
@@ -1,6 +1,6 @@
summary: 지리 공간 데이터 활용기
id: getting_started_with_geospatial_geography_kr
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_python/getting_started_with_python.md b/site/sfguides/src/getting_started_with_python/getting_started_with_python.md
index 39b47e69f..efba0a3eb 100644
--- a/site/sfguides/src/getting_started_with_python/getting_started_with_python.md
+++ b/site/sfguides/src/getting_started_with_python/getting_started_with_python.md
@@ -1,6 +1,6 @@
summary: Getting Started with Python
id: getting_started_with_python
-categories: Getting Started
+categories: Getting-Started
tags: python
status: Published
Feedback Link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_python_kr/getting_started_with_python_kr.md b/site/sfguides/src/getting_started_with_python_kr/getting_started_with_python_kr.md
index 310fa84f0..92d255922 100644
--- a/site/sfguides/src/getting_started_with_python_kr/getting_started_with_python_kr.md
+++ b/site/sfguides/src/getting_started_with_python_kr/getting_started_with_python_kr.md
@@ -1,6 +1,6 @@
summary: Python 시작하기
id: getting_started_with_python_kr
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_search_optimization/getting_started_with_search_optimization.md b/site/sfguides/src/getting_started_with_search_optimization/getting_started_with_search_optimization.md
index cd009947a..3bfaecbb2 100644
--- a/site/sfguides/src/getting_started_with_search_optimization/getting_started_with_search_optimization.md
+++ b/site/sfguides/src/getting_started_with_search_optimization/getting_started_with_search_optimization.md
@@ -1,7 +1,7 @@
author: Yogitha Chilukuri
id: getting_started_with_search_optimization
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_sigma/getting_started_with_sigma.md b/site/sfguides/src/getting_started_with_sigma/getting_started_with_sigma.md
index a2bcd0db6..789fe0510 100644
--- a/site/sfguides/src/getting_started_with_sigma/getting_started_with_sigma.md
+++ b/site/sfguides/src/getting_started_with_sigma/getting_started_with_sigma.md
@@ -1,7 +1,7 @@
author: Sigma Computing -- Shawn Namdar, Partner Engineer
id: getting_started_with_sigma
summary: This is a guide to setting up Sigma on top of Snowflake and visualizing some sample data.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowflake/getting_started_with_snowflake.md b/site/sfguides/src/getting_started_with_snowflake/getting_started_with_snowflake.md
index 6c8a66688..fda411efa 100644
--- a/site/sfguides/src/getting_started_with_snowflake/getting_started_with_snowflake.md
+++ b/site/sfguides/src/getting_started_with_snowflake/getting_started_with_snowflake.md
@@ -1,6 +1,6 @@
summary: This is a broad introduction of Snowflake and covers how to login, run queries, and load data.
id: getting_started_with_snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowflake_kr/getting_started_with_snowflake.md b/site/sfguides/src/getting_started_with_snowflake_kr/getting_started_with_snowflake.md
index 7c5e11cf3..37385e7a8 100644
--- a/site/sfguides/src/getting_started_with_snowflake_kr/getting_started_with_snowflake.md
+++ b/site/sfguides/src/getting_started_with_snowflake_kr/getting_started_with_snowflake.md
@@ -1,6 +1,6 @@
summary: This is a broad introduction of Snowflake and covers how to login, run queries, and load data.
id: getting_started_with_snowflake_kr
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowpark/getting_started_with_snowpark.md b/site/sfguides/src/getting_started_with_snowpark/getting_started_with_snowpark.md
index 6c3a68189..29d8dae0b 100644
--- a/site/sfguides/src/getting_started_with_snowpark/getting_started_with_snowpark.md
+++ b/site/sfguides/src/getting_started_with_snowpark/getting_started_with_snowpark.md
@@ -1,6 +1,6 @@
id: getting_started_with_snowpark_scala
summary: This guide provides the basic instructions for setting up a simple example using Snowpark.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowpark_dataframe_api/getting_started_with_snowpark_dataframe_api.md b/site/sfguides/src/getting_started_with_snowpark_dataframe_api/getting_started_with_snowpark_dataframe_api.md
index fb5fb0011..552a35518 100644
--- a/site/sfguides/src/getting_started_with_snowpark_dataframe_api/getting_started_with_snowpark_dataframe_api.md
+++ b/site/sfguides/src/getting_started_with_snowpark_dataframe_api/getting_started_with_snowpark_dataframe_api.md
@@ -1,6 +1,6 @@
summary: Learn how to get started with Jupyter Notebooks on Snowpark and use the DataFrame API.
id: getting_started_with_snowpark_dataframe_api
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowpark_dataframe_api_kr/getting_started_with_snowpark_dataframe_api_kr.md b/site/sfguides/src/getting_started_with_snowpark_dataframe_api_kr/getting_started_with_snowpark_dataframe_api_kr.md
index 756603c29..7c8544b90 100644
--- a/site/sfguides/src/getting_started_with_snowpark_dataframe_api_kr/getting_started_with_snowpark_dataframe_api_kr.md
+++ b/site/sfguides/src/getting_started_with_snowpark_dataframe_api_kr/getting_started_with_snowpark_dataframe_api_kr.md
@@ -1,6 +1,6 @@
id: getting_started_with_snowpark_dataframe_api_kr
summary: Snowpark에서 Jupyter Notebook을 시작하고 DataFrame API를 사용하는 방법을 알아보십시오.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowpark_kr/getting_started_with_snowpark_kr.md b/site/sfguides/src/getting_started_with_snowpark_kr/getting_started_with_snowpark_kr.md
index 67b1ab101..89321dea8 100644
--- a/site/sfguides/src/getting_started_with_snowpark_kr/getting_started_with_snowpark_kr.md
+++ b/site/sfguides/src/getting_started_with_snowpark_kr/getting_started_with_snowpark_kr.md
@@ -1,6 +1,6 @@
id: getting_started_with_snowpark_kr
summary: 이 가이드는 Snowpark를 사용하여 단순한 예시 설정을 위한 기본 지침을 제공합니다.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowpark_python_streamlit/getting_started_with_snowpark_for_python_streamlit.md b/site/sfguides/src/getting_started_with_snowpark_python_streamlit/getting_started_with_snowpark_for_python_streamlit.md
index c8d8fb8fb..31e759807 100644
--- a/site/sfguides/src/getting_started_with_snowpark_python_streamlit/getting_started_with_snowpark_for_python_streamlit.md
+++ b/site/sfguides/src/getting_started_with_snowpark_python_streamlit/getting_started_with_snowpark_for_python_streamlit.md
@@ -1,6 +1,6 @@
id: getting_started_with_snowpark_for_python_streamlit
summary: This guide provides the instructions for writing an application using Snowpark for Python and Streamlit.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link:
diff --git a/site/sfguides/src/getting_started_with_snowpipe/getting_started_with_snowpipe.md b/site/sfguides/src/getting_started_with_snowpipe/getting_started_with_snowpipe.md
index 773f13a88..0510e6085 100644
--- a/site/sfguides/src/getting_started_with_snowpipe/getting_started_with_snowpipe.md
+++ b/site/sfguides/src/getting_started_with_snowpipe/getting_started_with_snowpipe.md
@@ -1,6 +1,6 @@
summary: This guide will help you get started with Snowpipe.
id: getting_started_with_snowpipe
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowpipe_kr/getting_started_with_snowpipe_kr.md b/site/sfguides/src/getting_started_with_snowpipe_kr/getting_started_with_snowpipe_kr.md
index fe89cb0bf..b3f91700e 100644
--- a/site/sfguides/src/getting_started_with_snowpipe_kr/getting_started_with_snowpipe_kr.md
+++ b/site/sfguides/src/getting_started_with_snowpipe_kr/getting_started_with_snowpipe_kr.md
@@ -1,6 +1,6 @@
summary: 이 가이드는 Snowpipe를 시작하는 데 도움이 됩니다.
id: getting_started_with_snowpipe_kr
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowsql/getting_started_with_snowsql.md b/site/sfguides/src/getting_started_with_snowsql/getting_started_with_snowsql.md
index 8888b4b92..2e509ccc4 100644
--- a/site/sfguides/src/getting_started_with_snowsql/getting_started_with_snowsql.md
+++ b/site/sfguides/src/getting_started_with_snowsql/getting_started_with_snowsql.md
@@ -1,6 +1,6 @@
summary: Getting Started with SnowSQL
id:getting_started_with_snowsql
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_snowsql_kr/getting_started_with_snowsql_kr.md b/site/sfguides/src/getting_started_with_snowsql_kr/getting_started_with_snowsql_kr.md
index 0fcbca3ae..1c1ffbfd8 100644
--- a/site/sfguides/src/getting_started_with_snowsql_kr/getting_started_with_snowsql_kr.md
+++ b/site/sfguides/src/getting_started_with_snowsql_kr/getting_started_with_snowsql_kr.md
@@ -1,6 +1,6 @@
id:getting_started_with_snowsql_kr
summary: SnowSQL 시작하기
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_streams_and_tasks/getting_started_with_streams_and_tasks.md b/site/sfguides/src/getting_started_with_streams_and_tasks/getting_started_with_streams_and_tasks.md
index 564ca6c88..23f8db574 100644
--- a/site/sfguides/src/getting_started_with_streams_and_tasks/getting_started_with_streams_and_tasks.md
+++ b/site/sfguides/src/getting_started_with_streams_and_tasks/getting_started_with_streams_and_tasks.md
@@ -1,6 +1,6 @@
id: getting_started_with_streams_and_tasks
summary: Learn how to use streams and tasks with Snowflake.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_time_travel/getting_started_with_time_travel.md b/site/sfguides/src/getting_started_with_time_travel/getting_started_with_time_travel.md
index d24619eda..6789885c2 100644
--- a/site/sfguides/src/getting_started_with_time_travel/getting_started_with_time_travel.md
+++ b/site/sfguides/src/getting_started_with_time_travel/getting_started_with_time_travel.md
@@ -1,6 +1,6 @@
summary: Use Time Travel to query previous database states and undrop data.
Id: getting_started_with_time_travel
-categories: Getting Started, hello test
+categories: Getting-Started, hello test
environments: test, web, hello
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_time_travel_kr/getting_started_with_time_travel_kr.md b/site/sfguides/src/getting_started_with_time_travel_kr/getting_started_with_time_travel_kr.md
index 4cee88ddf..badd9eec6 100644
--- a/site/sfguides/src/getting_started_with_time_travel_kr/getting_started_with_time_travel_kr.md
+++ b/site/sfguides/src/getting_started_with_time_travel_kr/getting_started_with_time_travel_kr.md
@@ -1,6 +1,6 @@
id: getting_started_with_time_travel_kr
summary: Time Travel을 사용하여 이전 데이터베이스 상태를 쿼리하고 데이터를 복구합니다.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_unstructured_data/getting_started_with_unstructured_data.md b/site/sfguides/src/getting_started_with_unstructured_data/getting_started_with_unstructured_data.md
index 7fd75f3c3..36726764e 100644
--- a/site/sfguides/src/getting_started_with_unstructured_data/getting_started_with_unstructured_data.md
+++ b/site/sfguides/src/getting_started_with_unstructured_data/getting_started_with_unstructured_data.md
@@ -1,7 +1,7 @@
author: Scott Teal, Saurin Shah, Zohar Nissare-Houssen, Kesav Rayaprolu
id: getting_started_with_unstructured_data
summary: This is a guide to get familiar with Snowflake's support for unstructured data
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/getting_started_with_user_defined_sql_functions/getting_started_with_user_defined_sql_functions.md b/site/sfguides/src/getting_started_with_user_defined_sql_functions/getting_started_with_user_defined_sql_functions.md
index 34c8352e3..7a0ad4c16 100644
--- a/site/sfguides/src/getting_started_with_user_defined_sql_functions/getting_started_with_user_defined_sql_functions.md
+++ b/site/sfguides/src/getting_started_with_user_defined_sql_functions/getting_started_with_user_defined_sql_functions.md
@@ -1,6 +1,6 @@
summary: Guide to getting started with user-defined SQL functions
Id: getting_started_with_user_defined_sql_functions
-categories: Getting Started, UDF, UDTF
+categories: Getting-Started, UDF, UDTF
environments: Web
status: Published
feedback link: https://github.com/Snowflake-Labs/devlabs/issues
diff --git a/site/sfguides/src/getting_started_with_user_defined_sql_functions_kr/getting_started_with_user_defined_sql_functions_kr.md b/site/sfguides/src/getting_started_with_user_defined_sql_functions_kr/getting_started_with_user_defined_sql_functions_kr.md
index 52ad7b295..0ba0c7478 100644
--- a/site/sfguides/src/getting_started_with_user_defined_sql_functions_kr/getting_started_with_user_defined_sql_functions_kr.md
+++ b/site/sfguides/src/getting_started_with_user_defined_sql_functions_kr/getting_started_with_user_defined_sql_functions_kr.md
@@ -1,6 +1,6 @@
id: getting_started_with_user_defined_sql_functions
summary: 사용자 정의 SQL 함수 시작하기 가이드
-categories: Getting Started, UDF, UDTF
+categories: Getting-Started, UDF, UDTF
environments: Web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/devlabs/issues
diff --git a/site/sfguides/src/h2o/h2o.md b/site/sfguides/src/h2o/h2o.md
index 5968e9922..4e7b09156 100644
--- a/site/sfguides/src/h2o/h2o.md
+++ b/site/sfguides/src/h2o/h2o.md
@@ -1,7 +1,7 @@
author: miles.adkins@snowflake.com
id: automl_with_snowflake_and_h2o
summary: This lab will walk you through how to use Snowflake and H2O to perform supervised machine learning.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/harness_the_power_of_snowflake_with_informatica_idmc/harness_the_power_of_snowflake_with_informatica_idmc.md b/site/sfguides/src/harness_the_power_of_snowflake_with_informatica_idmc/harness_the_power_of_snowflake_with_informatica_idmc.md
index 18871a5a6..b745bd257 100644
--- a/site/sfguides/src/harness_the_power_of_snowflake_with_informatica_idmc/harness_the_power_of_snowflake_with_informatica_idmc.md
+++ b/site/sfguides/src/harness_the_power_of_snowflake_with_informatica_idmc/harness_the_power_of_snowflake_with_informatica_idmc.md
@@ -1,7 +1,7 @@
author: Eddy Widjaja
id: harness_the_power_of_snowflake_with_informatica_idmc
summary: This is a guide for getting started with Data Engineering using Informatica Data Management Cloud
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/hex/hex_vhol.md b/site/sfguides/src/hex/hex_vhol.md
index eabea06c0..81e49fd09 100644
--- a/site/sfguides/src/hex/hex_vhol.md
+++ b/site/sfguides/src/hex/hex_vhol.md
@@ -1,7 +1,7 @@
author: gflomo@hex.tech
id: hex
summary: This lab will walk you through how to use Snowflake and Hex.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/ingest_data_from_pubsub_to_snowflake_with_apache_beam/beam.md b/site/sfguides/src/ingest_data_from_pubsub_to_snowflake_with_apache_beam/beam.md
index 12bab3ac4..48b933a85 100644
--- a/site/sfguides/src/ingest_data_from_pubsub_to_snowflake_with_apache_beam/beam.md
+++ b/site/sfguides/src/ingest_data_from_pubsub_to_snowflake_with_apache_beam/beam.md
@@ -1,7 +1,7 @@
author: Kamil Bregula
id: ingest_data_from_pubsub_to_snowflake_with_apache_beam
summary: Ingest data from PubSub to Snowflake with Apache Beam
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/machine_learning_with_aws_autopilot/machine_learning_with_aws_autopilot.md b/site/sfguides/src/machine_learning_with_aws_autopilot/machine_learning_with_aws_autopilot.md
index 52f25094b..9bf209079 100644
--- a/site/sfguides/src/machine_learning_with_aws_autopilot/machine_learning_with_aws_autopilot.md
+++ b/site/sfguides/src/machine_learning_with_aws_autopilot/machine_learning_with_aws_autopilot.md
@@ -1,6 +1,6 @@
summary: Snowflake and Amazon SageMaker Autopilot Integration: Machine Learning with SQL
id: machine_learning_with_aws_autopilot
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/machine_learning_with_saturncloud/machine_learning_with_saturncloud.md b/site/sfguides/src/machine_learning_with_saturncloud/machine_learning_with_saturncloud.md
index e241bd160..281466a77 100644
--- a/site/sfguides/src/machine_learning_with_saturncloud/machine_learning_with_saturncloud.md
+++ b/site/sfguides/src/machine_learning_with_saturncloud/machine_learning_with_saturncloud.md
@@ -1,6 +1,6 @@
summary: Machine learning on unstructured data with Saturn Cloud and Snowflake
Id: machine_learning_with_saturncloud
-categories: Getting Started
+categories: Getting-Started
environments: Web
status: Published
feedback link: https://github.com/Snowflake-Labs/devlabs/issues
diff --git a/site/sfguides/src/processing_hl7_v2_messages_with_snowflake/processing_hl7_v2_messages_with_snowflake.md b/site/sfguides/src/processing_hl7_v2_messages_with_snowflake/processing_hl7_v2_messages_with_snowflake.md
index 970e1dbfd..8229705e1 100644
--- a/site/sfguides/src/processing_hl7_v2_messages_with_snowflake/processing_hl7_v2_messages_with_snowflake.md
+++ b/site/sfguides/src/processing_hl7_v2_messages_with_snowflake/processing_hl7_v2_messages_with_snowflake.md
@@ -1,7 +1,7 @@
author: Sreedhar Bolneni, Venkatesh Sekar, Tushar Sarde
id: processing_hl7_v2_messages_with_snowflake
summary: This is a guide to get familiarised with how to ingest and process HL7 V2.x messages using Snowflake Data Programmability features.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/python_camouflage/python_camouflage.md b/site/sfguides/src/python_camouflage/python_camouflage.md
index 7a934f4c2..4512f252f 100644
--- a/site/sfguides/src/python_camouflage/python_camouflage.md
+++ b/site/sfguides/src/python_camouflage/python_camouflage.md
@@ -2,7 +2,7 @@
author: Kevin Keller (https://github.com/kkellersnow)
id: python_camouflage
summary: Project Python Camouflage aims to give a working MVP for tokenization in Snowflake using Python. The problem this aims to solve is allowing customers to obfuscate (or “mask”) PII while at the same time not losing the ability to use that data in joins and other operations where the consistency of the data through operations is required. Python offers libraries to achieve this using encryption, and through the use of Snowflake Python UDFs we can apply that to information in Snowflake natively. As an MVP, this is not meant to offer a complete solution to the problem. Rather, this is a framework that others can embrace and extend.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/reach_and_frequency_queries/reach_and_frequency_queries.md b/site/sfguides/src/reach_and_frequency_queries/reach_and_frequency_queries.md
index 44524a83e..9748d0885 100644
--- a/site/sfguides/src/reach_and_frequency_queries/reach_and_frequency_queries.md
+++ b/site/sfguides/src/reach_and_frequency_queries/reach_and_frequency_queries.md
@@ -1,7 +1,7 @@
author: Jim Warner
id: reach_and_frequency_queries
summary: Shows common reach and frequency queries for advertising measurement
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/resource_optimization_billing_metrics/resource_optimization_billing_metrics.md b/site/sfguides/src/resource_optimization_billing_metrics/resource_optimization_billing_metrics.md
index 8e0ac87a5..276139b03 100644
--- a/site/sfguides/src/resource_optimization_billing_metrics/resource_optimization_billing_metrics.md
+++ b/site/sfguides/src/resource_optimization_billing_metrics/resource_optimization_billing_metrics.md
@@ -1,13 +1,13 @@
summary: This guide can be used to help customers setup and run queries pertaining to monitoring billing metrics that might help identify areas of over-consumption.
id: resource_optimization_billing_metrics
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
tags: Resource Optimization, Cost Optimization, Billing, Billing Metrics, Monitoring
authors: Matt Meredith
-#Resource Optimization: Billing Metrics
+# Resource Optimization: Billing Metrics
diff --git a/site/sfguides/src/resource_optimization_billing_metrics_kr/resource_optimization_billing_metrics_kr.md b/site/sfguides/src/resource_optimization_billing_metrics_kr/resource_optimization_billing_metrics_kr.md
index 3deeaa202..752d088e2 100644
--- a/site/sfguides/src/resource_optimization_billing_metrics_kr/resource_optimization_billing_metrics_kr.md
+++ b/site/sfguides/src/resource_optimization_billing_metrics_kr/resource_optimization_billing_metrics_kr.md
@@ -1,6 +1,6 @@
summary: 이 가이드는 고객이 과도한 소비가 발생하는 영역을 확인하는 데 도움이 될 수 있는 청구 메트릭을 모니터링하는 것과 관계된 쿼리를 설정 및 실행하는 데 도움을 주기 위해 사용할 수 있습니다.
id: resource_optimization_billing_metrics_kr
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/resource_optimization_performance_optimization/resource_optimization_performance_optimization.md b/site/sfguides/src/resource_optimization_performance_optimization/resource_optimization_performance_optimization.md
index 29af01efb..05f26c172 100644
--- a/site/sfguides/src/resource_optimization_performance_optimization/resource_optimization_performance_optimization.md
+++ b/site/sfguides/src/resource_optimization_performance_optimization/resource_optimization_performance_optimization.md
@@ -1,6 +1,6 @@
summary: This guide can be used to help customers setup and run queries pertaining to identifying areas where poor performance might be causing excess consumption, driven by a variety of factors.
id: resource_optimization_performance_optimization
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/resource_optimization_performance_optimization_kr/resource_optimization_performance_optimization_kr.md b/site/sfguides/src/resource_optimization_performance_optimization_kr/resource_optimization_performance_optimization_kr.md
index a058887da..762788e67 100644
--- a/site/sfguides/src/resource_optimization_performance_optimization_kr/resource_optimization_performance_optimization_kr.md
+++ b/site/sfguides/src/resource_optimization_performance_optimization_kr/resource_optimization_performance_optimization_kr.md
@@ -1,6 +1,6 @@
summary: 이 가이드는 고객이 다양한 요인으로 인한 낮은 성능이 과도한 소비를 초래할 수도 있는 영역을 확인하는 것과 관계된 쿼리를 설정 맟 실행하는 데 도움을 주기 위해 사용할 수 있습니다.
id: resource_optimization_performance_optimization_kr
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/resource_optimization_setup/resource_optimization_setup.md b/site/sfguides/src/resource_optimization_setup/resource_optimization_setup.md
index 58c9a4986..857e8e6fb 100644
--- a/site/sfguides/src/resource_optimization_setup/resource_optimization_setup.md
+++ b/site/sfguides/src/resource_optimization_setup/resource_optimization_setup.md
@@ -1,6 +1,6 @@
summary: This guide can be used to help customers setup and run queries pertaining to specific setup & configuration items that might be causing over-consumption.
id: resource_optimization_setup
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/resource_optimization_setup_kr/resource_optimization_setup_kr.md b/site/sfguides/src/resource_optimization_setup_kr/resource_optimization_setup_kr.md
index 966d672f6..3e91db3d1 100644
--- a/site/sfguides/src/resource_optimization_setup_kr/resource_optimization_setup_kr.md
+++ b/site/sfguides/src/resource_optimization_setup_kr/resource_optimization_setup_kr.md
@@ -1,6 +1,6 @@
summary: 이 가이드는 고객이 쿼리는 과도한 소비를 초래할 수도 있는 특정 설정 및 구성 항목과 관계된 쿼리를 설정 및 실행하는 데 도움을 주기 위해 사용할 수 있습니다.
id: resource_optimization_setup_kr
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/resource_optimization_usage_monitoring/resource_optimization_usage_monitoring.md b/site/sfguides/src/resource_optimization_usage_monitoring/resource_optimization_usage_monitoring.md
index 4be8e7ef2..3dcb00dd4 100644
--- a/site/sfguides/src/resource_optimization_usage_monitoring/resource_optimization_usage_monitoring.md
+++ b/site/sfguides/src/resource_optimization_usage_monitoring/resource_optimization_usage_monitoring.md
@@ -1,13 +1,13 @@
summary: This guide can be used to help customers setup and run queries pertaining to monitoring usage that might be causing over-consumption.
id: resource_optimization_usage_monitoring
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
tags: Resource Optimization, Cost Optimization, Consumption, Usage Monitoring, Usage, Monitoring
authors: Matt Meredith
-#Resource Optimization: Usage Monitoring
+# Resource Optimization: Usage Monitoring
diff --git a/site/sfguides/src/resource_optimization_usage_monitoring_kr/resource_optimization_usage_monitoring_kr.md b/site/sfguides/src/resource_optimization_usage_monitoring_kr/resource_optimization_usage_monitoring_kr.md
index 293e9d3a5..44343e45b 100644
--- a/site/sfguides/src/resource_optimization_usage_monitoring_kr/resource_optimization_usage_monitoring_kr.md
+++ b/site/sfguides/src/resource_optimization_usage_monitoring_kr/resource_optimization_usage_monitoring_kr.md
@@ -1,6 +1,6 @@
summary: 이 가이드는 고객이 과도한 소비를 초래할 수도 있는 사용량을 모니터링하는 것과 관계된 쿼리를 설정 및 실행하는 데 도움을 주기 위해 사용할 수 있습니다.
id: resource_optimization_usage_monitoring_kr
-categories: Resource Optimization
+categories: Resource-Optimization
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/sample/sample.md b/site/sfguides/src/sample/sample.md
index 2458dcccb..36740514c 100644
--- a/site/sfguides/src/sample/sample.md
+++ b/site/sfguides/src/sample/sample.md
@@ -1,6 +1,6 @@
summary: This is a sample Snowflake Guide
id: sample
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Hidden
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
@@ -110,17 +110,20 @@ for (statement 1; statement 2; statement 3) {
```
### Info Boxes
-Positive
-: This will appear in a positive info box.
+> aside positive
+>
+> This will appear in a positive info box.
-Negative
-: This will appear in a negative info box.
+
+
+> aside negative
+>
+> This will appear in a negative info box.
### Buttons
-
+
+
### Tables
diff --git a/site/sfguides/src/secure-crosswalks-for-advertising-measurement/secure-crosswalks-for-advertising-measurement.md b/site/sfguides/src/secure-crosswalks-for-advertising-measurement/secure-crosswalks-for-advertising-measurement.md
index c19b486b0..22087b68a 100644
--- a/site/sfguides/src/secure-crosswalks-for-advertising-measurement/secure-crosswalks-for-advertising-measurement.md
+++ b/site/sfguides/src/secure-crosswalks-for-advertising-measurement/secure-crosswalks-for-advertising-measurement.md
@@ -1,7 +1,7 @@
author: Jim Warner, Rachel Blum
id: secure-crosswalks-for-advertising-measurement
summary: Share ad exposure data without sharing PII for advertising measurement.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/secure_audience_overlaps/secure_audience_overlaps.md b/site/sfguides/src/secure_audience_overlaps/secure_audience_overlaps.md
index ca445cfed..be00b414d 100644
--- a/site/sfguides/src/secure_audience_overlaps/secure_audience_overlaps.md
+++ b/site/sfguides/src/secure_audience_overlaps/secure_audience_overlaps.md
@@ -1,7 +1,7 @@
author: Rachel Blum, Jim Warner
id: secure_audience_overlaps
summary: This Quickstart shows how to do a simple audience overlap with a partner before setting up a more permanent clean room.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/streamsets_hol/streamsets_hol.md b/site/sfguides/src/streamsets_hol/streamsets_hol.md
index 6fba06258..5f215e51f 100644
--- a/site/sfguides/src/streamsets_hol/streamsets_hol.md
+++ b/site/sfguides/src/streamsets_hol/streamsets_hol.md
@@ -1,7 +1,7 @@
author: Kate Guttridge, StreamSets
id: streamsets_transformer_for_snowflake_hol
summary: Hands on Lab for Transformer for Snowflake
-categories: getting started,data warehouse,data engineering
+categories: Getting-Started,data warehouse,data engineering
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/terraforming_snowflake/terraforming_snowflake.md b/site/sfguides/src/terraforming_snowflake/terraforming_snowflake.md
index 8192b6f09..b228c8147 100644
--- a/site/sfguides/src/terraforming_snowflake/terraforming_snowflake.md
+++ b/site/sfguides/src/terraforming_snowflake/terraforming_snowflake.md
@@ -1,6 +1,6 @@
summary: Learn how to manage Snowflake using Terraform
id: terraforming_snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/time_series_forecasting_with_zepl/time_series_forecasting_with_zepl.md b/site/sfguides/src/time_series_forecasting_with_zepl/time_series_forecasting_with_zepl.md
index 00fa47c1a..e4c72d4f0 100644
--- a/site/sfguides/src/time_series_forecasting_with_zepl/time_series_forecasting_with_zepl.md
+++ b/site/sfguides/src/time_series_forecasting_with_zepl/time_series_forecasting_with_zepl.md
@@ -1,6 +1,6 @@
summary: Time Series Forecasting with Zepl
id: time_series_forecasting_zepl
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/devlabs/issues
diff --git a/site/sfguides/src/vhol_data_lake/vhol_data_lake.md b/site/sfguides/src/vhol_data_lake/vhol_data_lake.md
index 878cf96fa..308fbe5d8 100644
--- a/site/sfguides/src/vhol_data_lake/vhol_data_lake.md
+++ b/site/sfguides/src/vhol_data_lake/vhol_data_lake.md
@@ -1,7 +1,7 @@
author: Scott Teal
id: vhol_data_lake
summary: This is the guide for the hands-on lab, Snowflake for Data Lake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/vhol_data_marketplace_app/assets/vhol_data_marketplace_app.md b/site/sfguides/src/vhol_data_marketplace_app/assets/vhol_data_marketplace_app.md
index 89ce2501f..018fc0a41 100644
--- a/site/sfguides/src/vhol_data_marketplace_app/assets/vhol_data_marketplace_app.md
+++ b/site/sfguides/src/vhol_data_marketplace_app/assets/vhol_data_marketplace_app.md
@@ -1,7 +1,7 @@
author: Bren Stokes
id: vhol_data_marketplace_app
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/vhol_data_marketplace_app/vhol_data_marketplace_app.md b/site/sfguides/src/vhol_data_marketplace_app/vhol_data_marketplace_app.md
index 751e83846..d090cd507 100644
--- a/site/sfguides/src/vhol_data_marketplace_app/vhol_data_marketplace_app.md
+++ b/site/sfguides/src/vhol_data_marketplace_app/vhol_data_marketplace_app.md
@@ -1,7 +1,7 @@
author: Bren Stokes
id: vhol_data_marketplace_app
summary: This is a sample Snowflake Guide
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/vhol_data_vault/vhol_data_vault.md b/site/sfguides/src/vhol_data_vault/vhol_data_vault.md
index a1044e1c9..f719de480 100644
--- a/site/sfguides/src/vhol_data_vault/vhol_data_vault.md
+++ b/site/sfguides/src/vhol_data_vault/vhol_data_vault.md
@@ -1,7 +1,7 @@
author: yarodmi
id: vhol_data_vault
summary: Building a Real-time Data Vault in Snowflake
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/vhol_fivetran/vhol_fivetran.md b/site/sfguides/src/vhol_fivetran/vhol_fivetran.md
index 98f26c0ae..fb0e2db14 100644
--- a/site/sfguides/src/vhol_fivetran/vhol_fivetran.md
+++ b/site/sfguides/src/vhol_fivetran/vhol_fivetran.md
@@ -1,6 +1,6 @@
summary: Automating Data Pipelines to Drive Marketing Analytics with Snowflake & Fivetran
id: vhol_fivetran
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/devlabs/issues
diff --git a/site/sfguides/src/vhol_salesforce_tcrm/vhol_snowflake_salesforce_tcrm.md b/site/sfguides/src/vhol_salesforce_tcrm/vhol_snowflake_salesforce_tcrm.md
index 6f0ac3283..f102ef706 100644
--- a/site/sfguides/src/vhol_salesforce_tcrm/vhol_snowflake_salesforce_tcrm.md
+++ b/site/sfguides/src/vhol_salesforce_tcrm/vhol_snowflake_salesforce_tcrm.md
@@ -1,7 +1,7 @@
author: andries.engelbrecht@snowflake.com
id: vhol_snowflake_salesforce_tcrm
summary: This lab will walk you through how to use Snowflake, Salesforce and Tableau CRM to integrate data, and deliver Customer 360.
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/vhol_snowflake_data_wrangler/vhol_snowflake_data_wrangler.md b/site/sfguides/src/vhol_snowflake_data_wrangler/vhol_snowflake_data_wrangler.md
index 929c5ae85..e0749e0f6 100644
--- a/site/sfguides/src/vhol_snowflake_data_wrangler/vhol_snowflake_data_wrangler.md
+++ b/site/sfguides/src/vhol_snowflake_data_wrangler/vhol_snowflake_data_wrangler.md
@@ -1,6 +1,6 @@
summary: This lab will walk you through how to apply a data-centric approach to Machine Learning with Snowflake and Amazon SageMaker.
id: vhol_snowflake_data_wrangler
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/site/sfguides/src/visual_analytics_powered_by_snowflake_and_tableau/visual_analytics_powered_by_snowflake_and_tableau.md b/site/sfguides/src/visual_analytics_powered_by_snowflake_and_tableau/visual_analytics_powered_by_snowflake_and_tableau.md
index b672c7201..a642e2913 100644
--- a/site/sfguides/src/visual_analytics_powered_by_snowflake_and_tableau/visual_analytics_powered_by_snowflake_and_tableau.md
+++ b/site/sfguides/src/visual_analytics_powered_by_snowflake_and_tableau/visual_analytics_powered_by_snowflake_and_tableau.md
@@ -1,7 +1,7 @@
author: Chandra Nayak & Bailey Ferrari
id: visual_analytics_powered_by_snowflake_and_tableau
summary: Visual Analytics Powered by Snowflake and Tableau
-categories: Getting Started
+categories: Getting-Started
environments: web
status: Published
feedback link: https://github.com/Snowflake-Labs/sfguides/issues
diff --git a/tmp/your-first-pwapp/codelab.json b/tmp/your-first-pwapp/codelab.json
new file mode 100644
index 000000000..c3dfd5480
--- /dev/null
+++ b/tmp/your-first-pwapp/codelab.json
@@ -0,0 +1,40 @@
+{
+ "environment": "web",
+ "format": "md",
+ "prefix": "https://storage.googleapis.com",
+ "mainga": "UA-49880327-14",
+ "updated": "2021-04-10T16:55:12Z",
+ "id": "your-first-pwapp",
+ "duration": 24,
+ "title": "Your First Progressive Web App",
+ "authors": "Pete LePage",
+ "summary": "In this codelab, you'll build an installable, Progressive Web App, which loads quickly, even on flaky networks, and when launched looks like any other installed app.",
+ "source": "https://docs.google.com/document/d/16KCCID9tVAFG3z5B-7nr22SpKk7GsF9Sw1EIfjY3CrI/edit?usp=sharing\u0026resourcekey=0-c_ujNSVZzb_3bNLkFKFA8g",
+ "theme": "web",
+ "status": [
+ "published"
+ ],
+ "category": [
+ "web"
+ ],
+ "tags": [
+ "cds17",
+ "chrome-dev-summit-2016",
+ "devfest18",
+ "gdd17",
+ "io2016",
+ "io2017",
+ "io2018",
+ "io2019",
+ "jsconfeu",
+ "kiosk",
+ "pwa-dev-summit",
+ "pwa-roadshow",
+ "tag-web",
+ "typtwd17",
+ "web"
+ ],
+ "feedback": "https://github.com/googlecodelabs/your-first-pwapp/issues",
+ "ga": "UA-52746336-1",
+ "url": "your-first-pwapp"
+}
diff --git a/tmp/your-first-pwapp/img/1db827d76bc0b359.png b/tmp/your-first-pwapp/img/1db827d76bc0b359.png
new file mode 100644
index 000000000..7cb2b9cfb
Binary files /dev/null and b/tmp/your-first-pwapp/img/1db827d76bc0b359.png differ
diff --git a/tmp/your-first-pwapp/img/398bbcd285e2c5dd.png b/tmp/your-first-pwapp/img/398bbcd285e2c5dd.png
new file mode 100644
index 000000000..c65dcc370
Binary files /dev/null and b/tmp/your-first-pwapp/img/398bbcd285e2c5dd.png differ
diff --git a/tmp/your-first-pwapp/img/44860840e2090bd8.png b/tmp/your-first-pwapp/img/44860840e2090bd8.png
new file mode 100644
index 000000000..89348faae
Binary files /dev/null and b/tmp/your-first-pwapp/img/44860840e2090bd8.png differ
diff --git a/tmp/your-first-pwapp/img/6302ad4ba8460944.png b/tmp/your-first-pwapp/img/6302ad4ba8460944.png
new file mode 100644
index 000000000..8b191f163
Binary files /dev/null and b/tmp/your-first-pwapp/img/6302ad4ba8460944.png differ
diff --git a/tmp/your-first-pwapp/img/69808e4bf3aee41b.png b/tmp/your-first-pwapp/img/69808e4bf3aee41b.png
new file mode 100644
index 000000000..280da043e
Binary files /dev/null and b/tmp/your-first-pwapp/img/69808e4bf3aee41b.png differ
diff --git a/tmp/your-first-pwapp/img/6ebb2681eb1f58cb.png b/tmp/your-first-pwapp/img/6ebb2681eb1f58cb.png
new file mode 100644
index 000000000..7491a8623
Binary files /dev/null and b/tmp/your-first-pwapp/img/6ebb2681eb1f58cb.png differ
diff --git a/tmp/your-first-pwapp/img/72ed77b1720512da.png b/tmp/your-first-pwapp/img/72ed77b1720512da.png
new file mode 100644
index 000000000..e80a04da4
Binary files /dev/null and b/tmp/your-first-pwapp/img/72ed77b1720512da.png differ
diff --git a/tmp/your-first-pwapp/img/731e91776cb6ef18.png b/tmp/your-first-pwapp/img/731e91776cb6ef18.png
new file mode 100644
index 000000000..627dce7ff
Binary files /dev/null and b/tmp/your-first-pwapp/img/731e91776cb6ef18.png differ
diff --git a/tmp/your-first-pwapp/img/8ac92dd483c689d3.png b/tmp/your-first-pwapp/img/8ac92dd483c689d3.png
new file mode 100644
index 000000000..fb2602ccb
Binary files /dev/null and b/tmp/your-first-pwapp/img/8ac92dd483c689d3.png differ
diff --git a/tmp/your-first-pwapp/img/95fe6f7fbeee5bb1.png b/tmp/your-first-pwapp/img/95fe6f7fbeee5bb1.png
new file mode 100644
index 000000000..19c9a1e48
Binary files /dev/null and b/tmp/your-first-pwapp/img/95fe6f7fbeee5bb1.png differ
diff --git a/tmp/your-first-pwapp/img/984b34dc2aa667a.png b/tmp/your-first-pwapp/img/984b34dc2aa667a.png
new file mode 100644
index 000000000..82885ab02
Binary files /dev/null and b/tmp/your-first-pwapp/img/984b34dc2aa667a.png differ
diff --git a/tmp/your-first-pwapp/img/af1a64a13725428e.png b/tmp/your-first-pwapp/img/af1a64a13725428e.png
new file mode 100644
index 000000000..d5a129719
Binary files /dev/null and b/tmp/your-first-pwapp/img/af1a64a13725428e.png differ
diff --git a/tmp/your-first-pwapp/img/b112675caafccef0.png b/tmp/your-first-pwapp/img/b112675caafccef0.png
new file mode 100644
index 000000000..711133be7
Binary files /dev/null and b/tmp/your-first-pwapp/img/b112675caafccef0.png differ
diff --git a/tmp/your-first-pwapp/img/b3aa37b67863fd03.png b/tmp/your-first-pwapp/img/b3aa37b67863fd03.png
new file mode 100644
index 000000000..dc223bccc
Binary files /dev/null and b/tmp/your-first-pwapp/img/b3aa37b67863fd03.png differ
diff --git a/tmp/your-first-pwapp/img/b921f5583fcddf03.png b/tmp/your-first-pwapp/img/b921f5583fcddf03.png
new file mode 100644
index 000000000..cd9db042c
Binary files /dev/null and b/tmp/your-first-pwapp/img/b921f5583fcddf03.png differ
diff --git a/tmp/your-first-pwapp/img/c462743e1bc26958.png b/tmp/your-first-pwapp/img/c462743e1bc26958.png
new file mode 100644
index 000000000..f679e5f32
Binary files /dev/null and b/tmp/your-first-pwapp/img/c462743e1bc26958.png differ
diff --git a/tmp/your-first-pwapp/img/c7ac93904f473a91.png b/tmp/your-first-pwapp/img/c7ac93904f473a91.png
new file mode 100644
index 000000000..8ff512ba2
Binary files /dev/null and b/tmp/your-first-pwapp/img/c7ac93904f473a91.png differ
diff --git a/tmp/your-first-pwapp/img/c80a2a2e93c1c3ee.png b/tmp/your-first-pwapp/img/c80a2a2e93c1c3ee.png
new file mode 100644
index 000000000..9e3099dd4
Binary files /dev/null and b/tmp/your-first-pwapp/img/c80a2a2e93c1c3ee.png differ
diff --git a/tmp/your-first-pwapp/img/d824e1712e46a1cc.png b/tmp/your-first-pwapp/img/d824e1712e46a1cc.png
new file mode 100644
index 000000000..4406e8951
Binary files /dev/null and b/tmp/your-first-pwapp/img/d824e1712e46a1cc.png differ
diff --git a/tmp/your-first-pwapp/img/f2e4ed8199d53a9d.png b/tmp/your-first-pwapp/img/f2e4ed8199d53a9d.png
new file mode 100644
index 000000000..1f5a0782e
Binary files /dev/null and b/tmp/your-first-pwapp/img/f2e4ed8199d53a9d.png differ
diff --git a/tmp/your-first-pwapp/index.md b/tmp/your-first-pwapp/index.md
new file mode 100644
index 000000000..8a50bf19c
--- /dev/null
+++ b/tmp/your-first-pwapp/index.md
@@ -0,0 +1,1067 @@
+---
+id: your-first-pwapp
+summary: In this codelab, you'll build an installable, Progressive Web App, which loads quickly, even on flaky networks, and when launched looks like any other installed app.
+status: [published]
+authors: Pete LePage
+categories: web
+tags: cds17,chrome-dev-summit-2016,devfest18,gdd17,io2016,io2017,io2018,io2019,jsconfeu,kiosk,pwa-dev-summit,pwa-roadshow,tag-web,typtwd17,web
+feedback_link: https://github.com/googlecodelabs/your-first-pwapp/issues
+analytics_account: UA-52746336-1
+source: https://docs.google.com/document/d/16KCCID9tVAFG3z5B-7nr22SpKk7GsF9Sw1EIfjY3CrI/edit?usp=sharing&resourcekey=0-c_ujNSVZzb_3bNLkFKFA8g
+duration: 24
+
+---
+
+# Your First Progressive Web App
+
+[Codelab Feedback](https://github.com/googlecodelabs/your-first-pwapp/issues)
+
+
+## Introduction
+
+
+
+
+
+**Last Updated:** 2019-04-30
+
+### **What makes a web app, a Progressive Web App?**
+
+Progressive Web Apps provide an installable, app-like experience on desktop and mobile that are built and delivered directly via the web. They're web apps that are fast and reliable. And most importantly, they're web apps that work in any browser. If you're building a web app today, you're already on the path towards building a Progressive Web App.
+
+#### **Fast & Reliable**
+
+Every web experience must be fast, and this is especially true for Progressive Web Apps. Fast refers to the time it takes to get meaningful content on screen, and provide an interactive experience in less than 5 seconds.
+
+And, it must be **reliably fast**. It's hard to stress enough how much better reliable performance is. Think of it this way: the first load of a native app is frustrating. It's gated by an app store and a huge download, but once you get to a point where the app is installed, that up-front cost is amortized across all app starts, and none of those starts have a variable delay. Each application start is as fast as the last, no variance. A Progressive Web App must deliver this reliable performance that users have come to expect from any installed experience.
+
+#### **Installable**
+
+Progressive Web Apps can run in a browser tab, but are also installable. Bookmarking a site just adds a shortcut, but an installed Progressive Web App looks and behaves like all of the other installed apps. It launches from the same place as other apps launch. You can control the launch experience, including a customized splash screen, icons and more. It runs as an app, in an app window without an address bar or other browser UI. And like all other installed apps, it's a top level app in the task switcher.
+
+Remember, it's critical that an installable PWA is fast and reliable. Users who install a PWA expect that their apps work, no matter what kind of network connection they're on. It's a baseline expectation that must be met by every installed app.
+
+#### **Mobile & Desktop**
+
+Using responsive design techniques, Progressive Web Apps work on both mobile **and** desktop, using a single code base between platforms. If you're considering writing a native app, take a look at the benefits that a PWA offers.
+
+### **What you'll build**
+
+In this codelab, you're going to build a weather web app using Progressive Web App techniques. Your app will:
+
+* Use responsive design, so it works on desktop or mobile.
+* Be fast, using a service worker to precache the app resources (HTML, CSS, JavaScript, images) needed to run, and cache the weather data at runtime to improve performance.
+* Be installable, using a web app manifest and the `beforeinstallprompt` event to notify the user it's installable.
+
+
+
+> aside negative
+>
+> **Note:** To simplify this codelab, and explain the fundamentals of providing an offline experience, we're using vanilla JavaScript. In a production app, we strongly recommend using tools like [Workbox](https://developers.google.com/web/tools/workbox/) to build your service worker. It removes many of the sharp edges and dark corners you may run into.
+
+### **What you'll learn**
+
+* How to create and add a web app manifest
+* How to provide a simple offline experience
+* How to provide a full offline experience
+* How to make your app installable
+
+This codelab is focused on Progressive Web Apps. Non-relevant concepts and code blocks are glossed over and are provided for you to simply copy and paste.
+
+### **What you'll need**
+
+* A recent version of Chrome (74 or later)
+PWAs are just web apps, and work in all browsers, but we'll be using a few features of the Chrome DevTools to better understand what's happening at the browser level, and use it to test the install experience.
+* Knowledge of HTML, CSS, JavaScript, and [Chrome DevTools](https://developer.chrome.com/devtools).
+
+
+## Getting set up
+Duration: 02:00
+
+
+### **Get a key for the Dark Sky API**
+
+Our weather data comes from the [Dark Sky API](https://darksky.net/dev). In order to use it, you'll need to request an API key. It's easy to use, and free for non-commercial projects.
+
+
+
+> aside positive
+>
+> **Note:** You can still complete this codelab without a Dark Sky API key. If our server is unable to get real data from the Dark Sky API, it will return fake data instead.
+
+#### **Verify your API key is working properly**
+
+To test that your API Key is working properly, make an HTTP request to the DarkSky API. Update the URL below to replace `DARKSKY_API_KEY` with your API key. If everything works, you should see the latest weather forecast for New York City.
+
+`https://api.darksky.net/forecast/DARKSKY_API_KEY/40.7720232,-73.9732319`
+
+> aside negative
+>
+> **Caution:** Protect you API Keys like you protect your passwords. You should **never** check your API Key into a source repository, post it online, or share it. If your API Key is used improperly, it may result in it being revoked, or more.
+
+### **Get the code**
+
+We've put everything you need for this project into a Git repo. To get started, you'll need to grab the code and open it in your favorite dev environment. For this codelab, we recommend using Glitch.
+
+#### **Strongly Recommended: Use Glitch to import the repo**
+
+Using Glitch is the recommended method for working through this codelab.
+
+1. Open a new browser tab and go to [https://glitch.com](https://glitch.com).
+2. If you don't have an account, you'll need to sign up.
+3. Click **New Project**, then **Clone from Git Repo.**
+4. Clone **https://github.com/googlecodelabs/your-first-pwapp.git** and click OK.
+5. Once the repo has loaded, edit the `.env` file, and update it with your DarkSky API key.
+6. Click the **Show Live** button to see the PWA in action.
+
+#### **Alternative: Download code & work locally**
+
+If you want to download the code and work locally, you'll need to have a recent version of Node, and code editor setup and ready to go.
+
+> aside negative
+>
+> **Caution:** If you work locally, some of the Lighthouse audits won't pass, and installation may not be available because the local server doesn't serve the content over a secure context.
+
+
+
+1. Unpack the downloaded zip file.
+2. Run `npm install` to install the dependencies required to run the server.
+3. Edit `server.js` and set your DarkSky API key.
+4. Run `node server.js` to start the server on port 8000.
+5. Open a browser tab to [http://localhost:8000](http://localhost:8000)
+
+
+## Establish a baseline
+Duration: 02:00
+
+
+### **What's our starting point?**
+
+Our starting point is a basic weather app designed for this codelab. The code has been overly simplified to show the concepts in this codelab, and it has little error handling. If you choose to reuse any of this code in a production app, make sure that you handle any errors and fully test all code.
+
+Some things to try...
+
+1. Add a new city with the blue plus button in the bottom right corner.
+2. Refresh the data with the refresh button in the upper right corner.
+3. Delete a city using the x on the upper right of each city card.
+4. See how it works on desktop and mobile.
+5. See what happens when you go offline.
+6. Using Chrome's Network panel, see what happens when the network is throttled to Slow 3G.
+7. Add a delay to the forecast server by changing `FORECAST_DELAY` in `server.js`
+
+### Audit with Lighthouse
+
+[Lighthouse](https://developers.google.com/web/tools/lighthouse/#devtools) is an easy to use tool to help improve the quality of your sites and pages. It has audits for performance, accessibility, progressive web apps, and more. Each audit has a reference doc explaining why the audit is important, as well as how to fix it.
+
+
+
+We'll use Lighthouse to audit our Weather app, and verify the changes we've made.
+
+> aside positive
+>
+> **Tip:** You can run Lighthouse in Chrome DevTools, from the command line, or as a Node module. Consider [adding Lighthouse](https://github.com/GoogleChromeLabs/lighthousebot) to your build process to make sure your web app doesn't regress.
+
+### Let's run Lighthouse
+
+1. Open your project in a new tab.
+2. Open Chrome DevTools and switch to the **Audits** tab, DevTools shows a list of audit categories, leave them all enabled.
+3. Click **Run audits**, after 60-90 seconds, Lighthouse gives you a report on the page.
+
+### **The Progressive Web App Audit**
+
+We're going to focus on the results of the Progressive Web App audit.
+
+
+
+And there's a lot of red to focus on:
+
+* **❗FAILED:** Current page does not respond with a 200 when offline.
+* **❗FAILED:** `start_url` does not respond with a 200 when offline.
+* **❗FAILED:** Does not register a service worker that controls page and `start_url.`
+* **❗FAILED:** Web app manifest does not meet the installability requirements.
+* **❗FAILED:** Is not configured for a custom splash screen.
+* **❗FAILED:** Does not set an address-bar theme color.
+
+Let's jump in and start fixing some of these issues!
+
+
+## Add a web app manifest
+Duration: 03:00
+
+
+By the end of this section, our weather app will pass the following audits:
+
+* Web app manifest does not meet the installability requirements.
+* Is not configured for a custom splash screen.
+* Does not set an address-bar theme color.
+
+### **Create the web app manifest**
+
+The [web app manifest](https://developers.google.com/web/fundamentals/web-app-manifest) is a simple JSON file that gives you, the developer, the ability to control how your app appears to the user.
+
+Using the web app manifest, your web app can:
+
+* Tell the browser you want your app to open in a standalone window (`display`).
+* Define what page is opened when the app is first launched (`start_url`).
+* Define what the app should look like on the dock or app launcher (`short_name`, `icons`).
+* Create a splash screen (`name`, `icons`, `colors`).
+* Tell the browser to open the window in landscape, or portrait mode (`orientation`).
+* And [plenty more](https://developer.mozilla.org/en-US/docs/Web/Manifest#Members).
+
+Create a file named `public/manifest.json` in your project and copy/paste the following contents:
+
+`public/manifest.json`
+
+```
+{
+ "name": "Weather",
+ "short_name": "Weather",
+ "icons": [{
+ "src": "/images/icons/icon-128x128.png",
+ "sizes": "128x128",
+ "type": "image/png"
+ }, {
+ "src": "/images/icons/icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image/png"
+ }, {
+ "src": "/images/icons/icon-152x152.png",
+ "sizes": "152x152",
+ "type": "image/png"
+ }, {
+ "src": "/images/icons/icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }, {
+ "src": "/images/icons/icon-256x256.png",
+ "sizes": "256x256",
+ "type": "image/png"
+ }, {
+ "src": "/images/icons/icon-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }],
+ "start_url": "/index.html",
+ "display": "standalone",
+ "background_color": "#3E4EB8",
+ "theme_color": "#2F3BA2"
+}
+```
+
+The manifest supports an array of icons, intended for different screen sizes. For this code lab, we've included a few others since we needed them for our iOS integration.
+
+> aside positive
+>
+> **TIP:** To be installable, Chrome requires that you provide at least a 192x192px icon and a 512x512px icon. But you can also provide other sizes. Chrome uses the icon closest to 48dp, for example, 96px on a 2x device or 144px for a 3x device.
+
+### **Add a link to the web app manifest**
+
+Next, we need to tell the browser about our manifest by adding a `<link rel="manifest"...` to each page in our app. Add the following line to the `<head>` element in your `index.html` file.
+
+#### [public/index.html](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/index.html#L30)
+
+```
+
+
+```
+
+#### **DevTools Detour**
+
+DevTools provides a quick, easy way to check your `manifest.json` file. Open up the **Manifest** pane on the **Application** panel. If you've added the manifest information correctly, you'll be able to see it parsed and displayed in a human-friendly format on this pane.
+
+
+
+### **Add iOS meta tags & icons**
+
+Safari on iOS doesn't support the web app manifest ( [yet](https://webkit.org/status/#specification-web-app-manifest)), so you'll need to add the [traditional `meta` tags](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html) to the `<head>` of your `index.html` file:
+
+#### [public/index.html](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/index.html#L31)
+
+```
+
+
+
+
+
+```
+
+### **Bonus: Easy Lighthouse fixes**
+
+Our Lighthouse audit called out a few other things that are pretty easy to fix, so let's take care of those while we're here.
+
+#### **Set the meta description**
+
+Under the SEO audit, Lighthouse noted our " [Document does not have a meta description.](https://developers.google.com/web/tools/lighthouse/audits/description)" Descriptions can be displayed in Google's search results. High-quality, unique descriptions can make your results more relevant to search users and can increase your search traffic.
+
+To add a description, add the following `meta` tag to the `<head>` of your document:
+
+#### [public/index.html](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/index.html#L32)
+
+```
+
+
+```
+
+#### **Set the address bar theme color**
+
+In the PWA audit, Lighthouse noted our app " [Does not set an address-bar theme color](https://developers.google.com/web/tools/lighthouse/audits/address-bar)". Theming the browser's address bar to match your brand's colors provides a more immersive user experience.
+
+To set the theme color on mobile, add the following `meta` tag to the `<head>` of your document:
+
+#### [public/index.html](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/index.html#L33)
+
+```
+
+
+```
+
+### **Verify changes with Lighthouse**
+
+Run Lighthouse again (by clicking on the + sign in the upper left corner of the Audits pane) and verify your changes.
+
+**SEO Audit**
+
+* **✅ PASSED:** Document has a meta description.
+
+**Progressive Web App Audit**
+
+* **❗FAILED:** Current page does not respond with a 200 when offline.
+* **❗FAILED:** `start_url` does not respond with a 200 when offline.
+* **❗FAILED:** Does not register a service worker that controls page and `start_url.`
+* **✅ PASSED:** Web app manifest meets the installability requirements.
+* **✅ PASSED:** Configured for a custom splash screen.
+* **✅ PASSED:** Sets an address-bar theme color.
+
+
+## Provide a basic offline experience
+Duration: 03:00
+
+
+There is an expectation from users that installed apps will always have a baseline experience if they're offline. That's why it's critical for installable web apps to never show Chrome's offline dinosaur. The offline experience can range from a simple, offline page, to a read-only experience with previously cached data, all the way to a fully functional offline experience that automatically syncs when the network connection is restored.
+
+In this section, we're going to add a simple offline page to our weather app. If the user tries to load the app while offline, it'll show our custom page, instead of the typical offline page that the browser shows. By the end of this section, our weather app will pass the following audits:
+
+* Current page does not respond with a 200 when offline.
+* `start_url` does not respond with a 200 when offline.
+* Does not register a service worker that controls page and `start_url.`
+
+In the next section, we'll replace our custom offline page with a full offline experience. This will improve the offline experience, but more importantly, it'll significantly improve our performance, because most of our assets (HTML, CSS and JavaScript) will be stored and served locally, eliminating the network as a potential bottleneck.
+
+### **Service workers to the rescue**
+
+If you're unfamiliar with service workers, you can get a basic understanding by reading [Introduction To Service Workers](https://developers.google.com/web/fundamentals/primers/service-worker/) about what they can do, how their lifecycle works and more. Once you've completed this code lab, be sure to check out the [Debugging Service Workers code lab](http://goo.gl/jhXCBy) for a more in-depth look at how to work with service workers.
+
+Features provided via service workers should be considered a progressive enhancement, and added only if supported by the browser. For example, with service workers you can cache the [app shell](https://developers.google.com/web/fundamentals/architecture/app-shell) and data for your app, so that it's available even when the network isn't. When service workers aren't supported, the offline code isn't called, and the user gets a basic experience. Using feature detection to provide progressive enhancement has little overhead and it won't break in older browsers that don't support that feature.
+
+> aside negative
+>
+> **Remember:** Service worker functionality is only available on pages that are accessed via HTTPS (http://localhost and equivalents will also work to facilitate testing).
+
+### **Register the service worker**
+
+The first step is to register the service worker. Add the following code to your `index.html` file:
+
+#### [public/index.html](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/index.html#L206)
+
+```
+// CODELAB: Register service worker.
+if ('serviceWorker' in navigator) {
+ window.addEventListener('load', () => {
+ navigator.serviceWorker.register('/service-worker.js')
+ .then((reg) => {
+ console.log('Service worker registered.', reg);
+ });
+ });
+}
+```
+
+This code checks to see if the service worker API is available, and if it is, the service worker at `/service-worker.js` is registered once the page is [loaded](https://developers.google.com/web/fundamentals/primers/service-workers/registration).
+
+Note, the service worker is served from the root directory, not from a `/scripts/` directory. This is the easiest way to set the **`scope`** of your service worker. The `scope` of the service worker determines which files the service worker controls, in other words, from which path the service worker will intercept requests. The default `scope` is the location of the service worker file, and extends to all directories below. So if `service-worker.js` is located in the root directory, the service worker will control requests from all web pages at this domain.
+
+### **Precache offline page**
+
+First, we need to tell the service worker what to cache. We've already created a simple [offline page](https://your-first-pwa.glitch.me/offline.html) (`public/offline.html`) that we'll display any time there's no network connection.
+
+In your `service-worker.js`, add `'/offline.html',` to the `FILES_TO_CACHE` array, the final result should look like this:
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L23)
+
+```
+// CODELAB: Update cache names any time any of the cached files change.
+const FILES_TO_CACHE = [
+ '/offline.html',
+];
+```
+
+Next, we need to update the `install` event to tell the service worker to pre-cache the offline page:
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L29)
+
+```
+// CODELAB: Precache static resources here.
+evt.waitUntil(
+ caches.open(CACHE_NAME).then((cache) => {
+ console.log('[ServiceWorker] Pre-caching offline page');
+ return cache.addAll(FILES_TO_CACHE);
+ })
+);
+```
+
+> aside positive
+>
+> **Note:** Service worker events and life cycle is covered in the next section.
+
+Our `install` event now opens the cache with `caches.open()` and provides a cache name. Providing a cache name allows us to version files, or separate data from the cached resources so that we can easily update one but not affect the other.
+
+Once the cache is open, we can then call `cache.addAll()`, which takes a list of URLs, fetches them from the server and adds the response to the cache. Note that `cache.addAll()` will reject if any of the individual requests fail. That means you're guaranteed that, if the install step succeeds, you cache will be in a consistent state. But, if it fails for some reason, it will automatically try again the next time the service worker starts up.
+
+#### **DevTools Detour**
+
+Let's take a look at how you can use DevTools to understand and debug service workers. Before reloading your page, open up DevTools, go the **Service Workers** pane on the **Application** panel. It should look like this:
+
+
+
+When you see a blank page like this, it means that the currently open page does not have any registered service workers.
+
+Now, reload your page. The Service Workers pane should now look like this:
+
+
+
+When you see information like this, it means the page has a service worker running.
+
+Next to the Status label, there's a number (*34251* in this case), keep an eye on that number as you're working with service workers. It's an easy way to tell if your service worker has been updated.
+
+### **Clean-up old offline pages**
+
+We'll use the `activate` event to clean up any old data in our cache. This code ensures that your service worker updates its cache whenever any of the app shell files change. In order for this to work, you'd need to increment the `CACHE_NAME` variable at the top of your service worker file.
+
+Add the following code to your `activate` event:
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L36)
+
+```
+// CODELAB: Remove previous cached data from disk.
+evt.waitUntil(
+ caches.keys().then((keyList) => {
+ return Promise.all(keyList.map((key) => {
+ if (key !== CACHE_NAME) {
+ console.log('[ServiceWorker] Removing old cache', key);
+ return caches.delete(key);
+ }
+ }));
+ })
+);
+```
+
+#### **DevTools Detour**
+
+With the Service Workers pane open, refresh the page, you'll see the new service worker installed, and the status number increment.
+
+
+
+The updated service worker takes control immediately because our `install` event finishes with [`self.skipWaiting()`](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#skip_the_waiting_phase), and the `activate` event finishes with [`self.clients.claim()`](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#clientsclaim). Without those, the old service worker would continue to control the page as long as there is a tab open to the page.
+
+### **Handle failed network requests**
+
+And finally, we need to handle `fetch` events. We're going to use a [network, falling back to cache strategy](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-falling-back-to-cache). The service worker will first try to fetch the resource from the network, if that fails, it will return the offline page from the cache.
+
+
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L43)
+
+```
+// CODELAB: Add fetch event handler here.
+if (evt.request.mode !== 'navigate') {
+ // Not a page navigation, bail.
+ return;
+}
+evt.respondWith(
+ fetch(evt.request)
+ .catch(() => {
+ return caches.open(CACHE_NAME)
+ .then((cache) => {
+ return cache.match('offline.html');
+ });
+ })
+);
+```
+
+The `fetch` handler only needs to handle page navigations, so other requests can be dumped out of the handler and will be dealt with normally by the browser. But, if the request `.mode` is `navigate`, use `fetch` to try to get the item from the network. If it fails, the `catch` handler opens the cache with `caches.open(CACHE_NAME)` and uses `cache.match('offline.html')` to get the precached offline page. The result is then passed back to the browser using `evt.respondWith()`.
+
+> aside positive
+>
+> Wrapping the `fetch` call in [`evt.respondWith()`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith) prevents the browsers default fetch handling and tells the browser we want to handle the response ourselves. If you don't call `evt.respondWith()` inside of a `fetch` handler, you'll just get the default network behavior.
+
+#### **DevTools Detour**
+
+Let's check to make sure everything works as we expect it. With the Service Workers pane open, refresh the page, you'll see the new service worker installed, and the status number increment.
+
+We can also check to see what's been cached. Go to the **Cache Storage** pane on the **Application** panel of DevTools. Right click **Cache Storage**, pick **Refresh Caches**, expand the section and you should see the name of your static cache listed on the left-hand side. Clicking on the cache name shows all of the files that are cached.
+
+
+
+Now, let's test out offline mode. Go back to the **Service Workers** pane of DevTools and check the **Offline** checkbox. After checking it, you should see a little yellow warning icon next to the **Network** panel tab. This indicates that you're offline.
+
+
+
+Reload your page and... it works! We get **our** offline panda, instead of Chrome's offline dino!
+
+### **Tips for testing service workers**
+
+Debugging service workers can be a challenge, and when it involves caching, things can become even more of a nightmare if the cache isn't updated when you expect it. Between the typical service worker lifecycle and a bug in your code, you may become quickly frustrated. **But don't.**
+
+#### **Use DevTools**
+
+In the Service Workers pane of the Application panel, there are a few checkboxes that will make your life much easier.
+
+
+
+* **Offline** - When checked simulates an offline experience and prevents any requests from going to the network.
+* **Update on reload** - When checked will get the latest service worker, install it, and immediately activate it.
+* **Bypass for network** - When checked requests bypass the service worker and are sent directly to the network.
+
+#### **Start Fresh**
+
+In some cases, you may find yourself loading cached data or that things aren't updated as you expect. To clear all saved data (localStorage, indexedDB data, cached files) and remove any service workers, use the Clear storage pane in the Application tab. Alternatively, you can also work in an Incognito window.
+
+
+
+Additional tips:
+
+* Once a service worker has been unregistered, it may remain listed until its containing browser window is closed.
+* If multiple windows to your app are open, a new service worker will not take effect until all windows have been reloaded and updated to the latest service worker.
+* Unregistering a service worker does not clear the cache!
+* If a service worker exists and a new service worker is registered, the new service worker won't take control until the page is reloaded, unless you [take immediate control](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#clientsclaim).
+
+### **Verify changes with Lighthouse**
+
+Run Lighthouse again and verify your changes. Don't forget to uncheck the Offline checkbox before you verify your changes!
+
+**SEO Audit**
+
+* **✅ PASSED:** Document has a meta description.
+
+**Progressive Web App Audit**
+
+* **✅ PASSED:** Current page responds with a 200 when offline.
+* **✅ PASSED:** `start_url` responds with a 200 when offline.
+* **✅ PASSED:** Registers a service worker that controls page and `start_url.`
+* **✅ PASSED:** Web app manifest meets the installability requirements.
+* **✅ PASSED:** Configured for a custom splash screen.
+* **✅ PASSED:** Sets an address-bar theme color.
+
+
+## Provide a full offline experience
+Duration: 09:00
+
+
+Take a moment and put your phone into airplane mode, and try running some of your favorite apps. In almost all cases, they provide a fairly robust offline experience. Users expect that robust experience from their apps. And the web should be no different. Progressive Web Apps should be designed with offline as a core scenario.
+
+> aside positive
+>
+> Designing for offline-first can drastically improve the performance of your web app by reducing the number of network requests made by your app, instead resources can be precached and served directly from the local cache. Even with the fastest network connection, serving from the local cache will be faster!
+
+### **Service worker life cycle**
+
+The life cycle of the service worker is the most complicated part. If you don't know what it's trying to do and what the benefits are, it can feel like it's fighting you. But once you know how it works, you can deliver seamless, unobtrusive updates to users, mixing the best of the web and native patterns.
+
+> aside positive
+>
+> **Dive Deeper:** This codelab only covers the very basics of the service worker life cycle. To dive deeper, refer to [The Service Worker Lifecycle](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle) article on WebFundamentals.
+
+#### `install` **event**
+
+The first event a service worker gets is `install`. It's triggered as soon as the worker executes, and it's only called once per service worker. **If you alter your service worker script the browser considers it a different service worker**, and it'll get its own `install` event.
+
+
+
+Typically the `install` event is used to cache everything you need for your app to run.
+
+#### `activate` **event**
+
+The service worker will receive an `activate` event every time it starts up. The main purpose of the `activate` event is to configure the service worker's behavior, clean up any resources left behind from previous runs (e.g. old caches), and get the service worker ready to handle network requests (for example the `fetch` event described below).
+
+#### `fetch` **event**
+
+The fetch event allows the service worker to intercept any network requests and handle requests. It can go to the network to get the resource, it can pull it from its own cache, generate a custom response or any number of different options. Check out the [Offline Cookbook](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/) for different strategies that you can use.
+
+#### **Updating a service worker**
+
+The browser checks to see if there is a new version of your service worker on each page load. If it finds a new version, the new version is downloaded and installed in the background, but it is not activated. It's sits in a waiting state, until there are no longer any pages open that use the old service worker. Once all windows using the old service worker are closed, the new service worker is activated and can take control. Refer to the [Updating the service worker](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#updates) section of the Service Worker Lifecycle doc for further details.
+
+### **Choosing the right caching strategy**
+
+Choosing the right [caching strategy](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/) depends on the type of resource you're trying to cache and how you might need it later. For our weather app, we'll split the resources we need to cache into two categories: resources we want to precache and the data that we'll cache at runtime.
+
+#### **Caching static resources**
+
+Precaching your resources is a similar concept to what happens when a user installs a desktop or mobile app. The key resources needed for the app to run are installed, or cached on the device so that they can be loaded later whether there's a network connection or not.
+
+For our app, we'll precache all of our static resources when our service worker is installed so that everything we need to run our app is stored on the user's device. To ensure our app loads lightning fast, we'll use the [cache-first](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network) strategy; instead of going to the network to get the resources, they're pulled from the local cache; only if it's not available there will we try to get it from the network.
+
+
+
+Pulling from the local cache eliminates any network variability. No matter what kind of network the user is on (WiFi, 5G, 3G, or even 2G), the key resources we need to run are available almost immediately.
+
+> aside negative
+>
+> **Caution:** In this sample, static resources are served using a [`cache-first`](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network) strategy, which results in a copy of any cached content being returned without consulting the network. While a `cache-first` strategy is easy to implement, it can cause challenges in the future.
+
+#### **Caching the app data**
+
+The [stale-while-revalidate strategy](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate) is ideal for certain types of data and works well for our app. It gets data on screen as quickly as possible, then updates that once the network has returned the latest data. Stale-while-revalidate means we need to kick off two asynchronous requests, one to the cache and one to the network.
+
+
+
+Under normal circumstances, the cached data will be returned almost immediately providing the app with recent data it can use. Then, when the network request returns, the app will be updated using the latest data from the network.
+
+For our app, this provides a better experience than the network, falling back to cache strategy because the user does not have to wait until the network request times out to see something on screen. They may initially see older data, but once the network request returns, the app will be updated with the latest data.
+
+### **Update app logic**
+
+As mentioned previously, the app needs to kick off two asynchronous requests, one to the cache and one to the network. The app uses the `caches` object available in `window` to access the cache and retrieve the latest data. This is an excellent example of progressive enhancement as the `caches` object may not be available in all browsers, and if it's not the network request should still work.
+
+Update the `getForecastFromCache()` function, to check if the `caches` object is available in the global `window` object, and if it is, request the data from the cache.
+
+#### [public/scripts/app.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/app.js#L164)
+
+```
+// CODELAB: Add code to get weather forecast from the caches object.
+if (!('caches' in window)) {
+ return null;
+}
+const url = `${window.location.origin}/forecast/${coords}`;
+return caches.match(url)
+ .then((response) => {
+ if (response) {
+ return response.json();
+ }
+ return null;
+ })
+ .catch((err) => {
+ console.error('Error getting data from cache', err);
+ return null;
+ });
+```
+
+Then, we need to modify [`updateData()`](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/app.js#L196) so that it makes two calls, one to `getForecastFromNetwork()` to get the forecast from the network, and one to `getForecastFromCache()` to get the latest cached forecast:
+
+#### [public/scripts/app.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/app.js#L200)
+
+```
+// CODELAB: Add code to call getForecastFromCache.
+getForecastFromCache(location.geo)
+ .then((forecast) => {
+ renderForecast(card, forecast);
+ });
+```
+
+Our weather app now makes two asynchronous requests for data, one from the cache and one via a `fetch`. If there's data in the cache, it'll be returned and rendered extremely quickly (tens of milliseconds). Then, when the `fetch` responds, the card will be updated with the freshest data direct from the weather API.
+
+Notice how the cache request and the `fetch` request both end with a call to update the forecast card. How does the app know whether it's displaying the latest data? This is handled in the following code from `renderForecast()`:
+
+#### [public/scripts/app.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/app.js#L85)
+
+```
+// If the data on the element is newer, skip the update.
+if (lastUpdated >= data.currently.time) {
+ return;
+}
+```
+
+Every time that a card is updated, the app stores the timestamp of the data on a hidden attribute on the card. The app just bails if the timestamp that already exists on the card is newer than the data that was passed to the function.
+
+### **Pre-cache our app resources**
+
+In the service worker, let's add a `DATA_CACHE_NAME` so that we can separate our applications data from the app shell. When the app shell is updated and older caches are purged, our data will remain untouched, ready for a super fast load. Keep in mind, if your data format changes in the future, you'll need a way to handle that and ensure the app shell and content stay in sync.
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L21)
+
+```
+// CODELAB: Update cache names any time any of the cached files change.
+const CACHE_NAME = 'static-cache-v2';
+const DATA_CACHE_NAME = 'data-cache-v1';
+```
+
+Don't forget to also update the `CACHE_NAME`; we'll be changing all of our static resources as well.
+
+In order for our app to work offline, we need to precache all of the resources it needs. This will also help our performance. Instead of having to get all of the resources from the network, the app will be able to load all of them from the local cache, eliminating any network instability.
+
+Update the `FILES_TO_CACHE` array with the list of files:
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L23)
+
+```
+// CODELAB: Add list of files to cache here.
+const FILES_TO_CACHE = [
+ '/',
+ '/index.html',
+ '/scripts/app.js',
+ '/scripts/install.js',
+ '/scripts/luxon-1.11.4.js',
+ '/styles/inline.css',
+ '/images/add.svg',
+ '/images/clear-day.svg',
+ '/images/clear-night.svg',
+ '/images/cloudy.svg',
+ '/images/fog.svg',
+ '/images/hail.svg',
+ '/images/install.svg',
+ '/images/partly-cloudy-day.svg',
+ '/images/partly-cloudy-night.svg',
+ '/images/rain.svg',
+ '/images/refresh.svg',
+ '/images/sleet.svg',
+ '/images/snow.svg',
+ '/images/thunderstorm.svg',
+ '/images/tornado.svg',
+ '/images/wind.svg',
+];
+```
+
+Since we are manually generating the list of files to cache, every time we update a file we **must update the**
+
+
+**`CACHE_NAME`**. We were able to remove `offline.html` from our list of cached files because our app now has all the necessary resources it needs to work offline, and won't ever show the offline page again.
+
+> aside negative
+>
+> **Caution:** In this sample, we hand-rolled our own service worker. Each time we update any of the static resources, we need to re-roll the service worker and update the cache, otherwise the old content will be served. In addition, when one file changes, the entire cache is invalidated and needs to be re-downloaded. That means fixing a simple single character spelling mistake will invalidate the cache and require everything to be downloaded again—not exactly efficient. [Workbox](https://developers.google.com/web/tools/workbox/) handles this gracefully, by integrating it into your build process, only changed files will be updated, saving bandwidth for users and easier maintenance for you!
+
+#### **Update the activate event handler**
+
+To ensure our `activate` event doesn't accidentally delete our data, in the `activate` event of `service-worker.js`, replace `if (key !== CACHE_NAME) {` with:
+
+#### **public/service-worker.js**
+
+```
+if (key !== CACHE_NAME && key !== DATA_CACHE_NAME) {
+```
+
+#### **Update the fetch event handler**
+
+We need to modify the service worker to intercept requests to the weather API and store their responses in the cache, so we can easily access them later. In the stale-while-revalidate strategy, we expect the network response to be the ‘source of truth', always providing us with the most recent information. If it can't, it's OK to fail because we've already retrieved the latest cached data in our app.
+
+Update the `fetch` event handler to handle requests to the data API separately from other requests.
+
+#### [public/service-worker.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/service-worker.js#L42)
+
+```
+// CODELAB: Add fetch event handler here.
+if (evt.request.url.includes('/forecast/')) {
+ console.log('[Service Worker] Fetch (data)', evt.request.url);
+ evt.respondWith(
+ caches.open(DATA_CACHE_NAME).then((cache) => {
+ return fetch(evt.request)
+ .then((response) => {
+ // If the response was good, clone it and store it in the cache.
+ if (response.status === 200) {
+ cache.put(evt.request.url, response.clone());
+ }
+ return response;
+ }).catch((err) => {
+ // Network request failed, try to get it from the cache.
+ return cache.match(evt.request);
+ });
+ }));
+ return;
+}
+evt.respondWith(
+ caches.open(CACHE_NAME).then((cache) => {
+ return cache.match(evt.request)
+ .then((response) => {
+ return response || fetch(evt.request);
+ });
+ })
+);
+```
+
+The code intercepts the request and checks if it is for a weather forecast. If it is, use `fetch` to make the request. Once the response is returned, open the cache, clone the response, store it in the cache, and return the response to the original requestor.
+
+We need to remove the `evt.request.mode !== 'navigate'` check because we want our service worker to handle all requests (including images, scripts, CSS files, etc), not just navigations. If we left that check in, only the HTML would be served from the service worker cache, everything else would be requested from the network.
+
+### **Try it out**
+
+The app should be completely offline-functional now. Refresh the page to ensure that you've got the latest service worker installed, then save a couple of cities and press the refresh button on the app to get fresh weather data.
+
+Then go to the **Cache Storage** pane on the **Application** panel of DevTools. Expand the section and you should see the name of your static cache and data cache listed on the left-hand side. Opening the data cache should show the data stored for each city.
+
+
+
+Then, open DevTools and switch to the Service Workers pane, and check the Offline checkbox, then try reloading the page, and then go offline and reload the page.
+
+If you're on a fast network and want to see how weather forecast data is updated on a slow connection, set the `FORECAST_DELAY` property in `server.js` to `5000`. All requests to the forecast API will be delayed by 5000ms.
+
+### **Verify changes with Lighthouse**
+
+It's also a good idea to run Lighthouse again.
+
+**SEO Audit**
+
+* **✅ PASSED:** Document has a meta description.
+
+**Progressive Web App Audit**
+
+* **✅ PASSED:** Current page responds with a 200 when offline.
+* **✅ PASSED:** `start_url` responds with a 200 when offline.
+* **✅ PASSED:** Registers a service worker that controls page and `start_url.`
+* **✅ PASSED:** Web app manifest meets the installability requirements.
+* **✅ PASSED:** Configured for a custom splash screen.
+* **✅ PASSED:** Sets an address-bar theme color.
+
+
+## Add install experience
+Duration: 05:00
+
+
+When a Progressive Web App is installed, it looks and behaves like all of the other installed apps. It launches from the same place as other apps launch. It runs in an app without an address bar or other browser UI. And like all other installed apps, it's a top level app in the task switcher.
+
+
+
+In Chrome, a Progressive Web App can either be installed through the three-dot context menu, or you can provide a button or other UI component to the user that will prompt them to install your app.
+
+> aside positive
+>
+> **Tip:** Since the install experience in Chrome's three-dot context menu is somewhat buried, we recommend that you provide some indication within your app to notify the user your app can be installed, and an install button to complete the install process.
+
+### **Audit with Lighthouse**
+
+In order for a user to be able to install your Progressive Web App, it needs to meet [certain criteria](https://developers.google.com/web/fundamentals/app-install-banners/#criteria). The easiest way to check is to use Lighthouse and make sure it meets the installable criteria.
+
+
+
+If you're worked through this codelab, your PWA should already meet these criteria.
+
+> aside positive
+>
+> **DevTip:** For this section, enable the **Bypass for network** checkbox in the **Service Workers** pane of the **Application** panel in DevTools. When checked, requests bypass the service worker and are sent directly to the network. This simplifies our development process since we don't have to update our service worker while working through this section.
+
+### **Add install.js to index.html**
+
+First, let's add the `install.js` to our `index.html` file.
+
+#### [public/index.html](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/index.html#L204)
+
+```
+
+
+```
+
+### Listen for `beforeinstallprompt` **event**
+
+If the add to home screen [criteria](https://developers.google.com/web/fundamentals/app-install-banners/#criteria) are met, Chrome will fire a `beforeinstallprompt` event, that you can use to indicate your app can be 'installed', and then prompt the user to install it. Add the code below to listen for the `beforeinstallprompt` event:
+
+#### [public/scripts/install.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/install.js#L24)
+
+```
+// CODELAB: Add event listener for beforeinstallprompt event
+window.addEventListener('beforeinstallprompt', saveBeforeInstallPromptEvent);
+```
+
+### **Save event and show install button**
+
+In our `saveBeforeInstallPromptEvent` function, we'll save a reference to the `beforeinstallprompt` event so that we can call `prompt()` on it later, and update our UI to show the install button.
+
+#### [public/scripts/install.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/install.js#L34)
+
+```
+// CODELAB: Add code to save event & show the install button.
+deferredInstallPrompt = evt;
+installButton.removeAttribute('hidden');
+```
+
+### **Show the prompt / hide the button**
+
+When the user clicks the install button, we need to call `.prompt()` on the saved `beforeinstallprompt` event. We also need to hide the install button, because `.prompt()` can only be called once on each saved event.
+
+#### [public/scripts/install.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/install.js#L45)
+
+```
+// CODELAB: Add code show install prompt & hide the install button.
+deferredInstallPrompt.prompt();
+// Hide the install button, it can't be called twice.
+evt.srcElement.setAttribute('hidden', true);
+```
+
+Calling `.prompt()` will show a modal dialog to the user, asking them to add your app to their home screen.
+
+### **Log the results**
+
+You can check to see how the user responded to the install dialog by listening for the promise returned by the `userChoice` property of the saved `beforeinstallprompt` event. The promise returns an object with an `outcome` property after the prompt has shown and the user has responded to it.
+
+#### [public/scripts/install.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/install.js#L47)
+
+```
+// CODELAB: Log user response to prompt.
+deferredInstallPrompt.userChoice
+ .then((choice) => {
+ if (choice.outcome === 'accepted') {
+ console.log('User accepted the A2HS prompt', choice);
+ } else {
+ console.log('User dismissed the A2HS prompt', choice);
+ }
+ deferredInstallPrompt = null;
+ });
+```
+
+One comment about `userChoice`, the [spec defines it as a property](https://w3c.github.io/manifest/#beforeinstallpromptevent-interface), not a function as you might expect.
+
+#### **Log all install events**
+
+In addition to any UI you add to install your app, users can also install your PWA through other methods, for example Chrome's three-dot menu. To track these events, listen for the appinstalled event.
+
+#### [public/scripts/install.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/install.js#L51)
+
+```
+// CODELAB: Add event listener for appinstalled event
+window.addEventListener('appinstalled', logAppInstalled);
+```
+
+Then, we'll need to update the `logAppInstalled` function, for this codelab, we'll just use `console.log`, but in a production app, you probably want to log this as an event with your analytics software.
+
+#### [public/scripts/install.js](https://github.com/googlecodelabs/your-first-pwapp/blob/master/public/scripts/install.js#L60)
+
+```
+// CODELAB: Add code to log the event
+console.log('Weather App was installed.', evt);
+```
+
+### **Update the service worker**
+
+Don't forget to update the `CACHE_NAME` in your `service-worker.js` file since you've made changes to files that are already cached. Enabling the **Bypass for network** checkbox in the Service Workers pane of the Application panel in DevTools will work in development, but won't help in the real world.
+
+### **Try it out**
+
+Let's see how our install step went. To be safe, use the **Clear site data** button in the Application panel of DevTools to clear everything away and make sure we're starting fresh. If you previously installed the app, be sure to uninstall it, otherwise the install icon won't show up again.
+
+#### **Verify the install button is visible**
+
+First, let's verify our install icon shows up properly, be sure to try this on both desktop and mobile.
+
+1. Open the URL in a new Chrome tab.
+2. Open Chrome's three-dot menu (next to the address bar).
+▢ Verify you see "*Install Weather...*" in the menu.
+3. Refresh the weather data using the refresh button in the upper right corner to ensure we meet the [user engagement heuristics](https://developers.google.com/web/fundamentals/app-install-banners/#criteria).
+▢ Verify the install icon is visible in the app header.
+
+#### **Verify the install button works**
+
+Next, let's make sure everything installs properly, and our events are properly fired. You can do this either on desktop or mobile. If you want to test this on mobile, be sure you're using remote debugging so you can see what's logged to the console.
+
+1. Open Chrome, and in a new browser tab, navigate to your Weather PWA.
+2. Open DevTools and switch to the Console pane.
+3. Click the install button in the upper right corner.
+▢ Verify the install button disappears
+▢ Verify the install modal dialog is shown.
+4. Click Cancel.
+▢ Verify "*User dismissed the A2HS prompt*" is shown in the console output.
+▢ Verify the install button reappears.
+5. Click the install button again, then click the install button in the modal dialog.
+▢ Verify "*User accepted the A2HS prompt*" is shown in the console output.
+▢ Verify "*Weather App was installed*" is shown in the console output.
+▢ Verify the Weather app is added to the place where you'd typically find apps.
+6. Launch the Weather PWA.
+▢ Verify the app opens as a standalone app, either in an app window on desktop, or full screen on mobile.
+
+Note, if you're running on desktop from localhost, your installed PWA may show an address banner because localhost isn't considered a secure host.
+
+#### **Verify iOS installation works properly**
+
+Let's also check the behavior on iOS. If you have an iOS device, you can use that, or if you're on a Mac, try the iOS Simulator available with Xcode.
+
+1. Open Safari and in a new browser tab, navigate to your Weather PWA.
+2. Click the *Share* button.
+3. Scroll right and click on the *Add to Home Screen* button.
+
+1. Verify the title, URL and icon are correct.
+
+4. Click *Add.*
+
+1. Verify the app icon is added to the home screen.
+
+5. Launch the Weather PWA from the home screen.
+
+1. Verify the app launches full screen.
+
+### **Bonus: Detecting if your app is launched from the home screen**
+
+The `display-mode` media query makes it possible to apply styles depending on how the app was launched, or determine how it was launched with JavaScript.
+
+```
+@media all and (display-mode: standalone) {
+ body {
+ background-color: yellow;
+ }
+}
+```
+
+You can also check the `display-mode` media query in [JavaScript to see if you're running in standalone](https://developers.google.com/web/fundamentals/app-install-banners/#detect-mode).
+
+### **Bonus: Uninstalling your PWA**
+
+Remember, the `beforeinstallevent` doesn't fire if the app is already installed, so during development you'll probably want to install and uninstall your app several times to make sure everything is working as expected.
+
+#### **Android**
+
+On Android, PWAs are uninstalled in the same way other installed apps are uninstalled.
+
+* Open the app drawer.
+* Scroll down to find the Weather icon.
+* Drag the app icon to the top of the screen.
+* Choose *Uninstall.*
+
+#### **ChromeOS**
+
+On ChromeOS, PWAs are easily uninstalled from the launcher search box.
+
+* Open the launcher.
+* Type "*Weather*" into the search box, your Weather PWA should appear in the results.
+* Right click (alt-click) on the Weather PWA.
+* Click *Remove from Chrome...*
+
+#### **macOS and Windows**
+
+On Mac and Windows, PWAs may be uninstalled through Chrome:
+
+* In a new browser tab, open *chrome://apps*.
+* Right click (alt-click) on the Weather PWA.
+* Click *Remove from Chrome...*
+
+You can also open the installed PWA, click the the dot menu in the upper right corner, and choose "*Uninstall Weather PWA...*"
+
+
+## Congratulations
+
+
+
+Congratulations, you've successfully built your first Progressive Web App!
+
+You added a web app manifest to enable it to be installed, and you added a service worker to ensure that your PWA is always fast, and reliable. You learned how to use DevTools to audit an app and how it can help you improve your user experience.
+
+You now know the key steps required to turn any web app into a Progressive Web App.
+
+### **What's next?**
+
+Check out some of these codelabs...
+
+* [Adding Push Notifications to a Web App](https://codelabs.developers.google.com/codelabs/push-notifications/index.html)
+* [Debugging Service Workers](https://codelabs.developers.google.com/codelabs/debugging-service-workers/index.html)
+* [Build a PWA using Workbox](https://codelabs.developers.google.com/codelabs/workbox-lab/index.html)
+
+### **Further reading**
+
+* [High-performance service worker loading](https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading)
+* [Service Worker Caching Strategies Based on Request Types](https://medium.com/dev-channel/service-worker-caching-strategies-based-on-request-types-57411dd7652c)
+
+### **Reference docs**
+
+* [Web App Manifest docs](https://developers.google.com/web/fundamentals/web-app-manifest)
+* [Web App Manifest properties (MDN)](https://developer.mozilla.org/en-US/docs/Web/Manifest#Members)
+* [Install & Add to Home Screen](https://developers.google.com/web/fundamentals/app-install-banners/)
+* [Service Worker Overview](https://developers.google.com/web/fundamentals/primers/service-workers/)
+* [Service Worker Lifecycle](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle)
+* [High-performance service worker loading](https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading)
+* [Offline Cookbook](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#generic-fallback)
+
+