diff --git a/config/install/core.entity_form_display.taxonomy_term.uw_vocab_audience.default.yml b/config/install/core.entity_form_display.taxonomy_term.uw_vocab_audience.default.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8d0a4697d3ce43bba73bfb51ab24815beacf58b3
--- /dev/null
+++ b/config/install/core.entity_form_display.taxonomy_term.uw_vocab_audience.default.yml
@@ -0,0 +1,44 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - taxonomy.vocabulary.uw_vocab_audience
+  module:
+    - text
+id: taxonomy_term.uw_vocab_audience.default
+targetEntityType: taxonomy_term
+bundle: uw_vocab_audience
+mode: default
+content:
+  description:
+    type: text_textarea
+    weight: 1
+    region: content
+    settings:
+      placeholder: ''
+      rows: 5
+    third_party_settings: {  }
+  langcode:
+    type: language_select
+    weight: 2
+    region: content
+    settings:
+      include_locked: true
+    third_party_settings: {  }
+  name:
+    type: string_textfield
+    weight: 0
+    region: content
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+  status:
+    type: boolean_checkbox
+    settings:
+      display_label: true
+    weight: 3
+    region: content
+    third_party_settings: {  }
+hidden:
+  path: true
diff --git a/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_content.yml b/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_content.yml
index 2f22cae3d2f8003862e2e75fd38b07cf35d073be..50e40679e908821f5517f30752ed57848148cd85 100755
--- a/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_content.yml
+++ b/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_content.yml
@@ -35,7 +35,8 @@ blocks:
     weight: 0
     image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/fullwidthimage.svg
     image_alt: ''
-  - block_id: 'inline_block:uw_cbl_image_gallery'
+  -
+    block_id: 'inline_block:uw_cbl_image_gallery'
     weight: 0
     image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/imagegallery.svg
     image_alt: ''
@@ -49,3 +50,8 @@ blocks:
     weight: 0
     image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/relatedlinks.svg
     image_alt: ''
+  -
+    block_id: 'inline_block:uw_cbl_timeline'
+    weight: 0
+    image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/timeline.svg
+    image_alt: ''
diff --git a/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_external_embeds.yml b/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_external_embeds.yml
index 5566f9f296785f88ac5ee285f4576971c21bc83e..03e03111c6da5884daa22ff3fe8e00dade08a133 100644
--- a/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_external_embeds.yml
+++ b/config/install/layout_builder_browser.layout_builder_browser_blockcat.uw_bc_external_embeds.yml
@@ -30,3 +30,13 @@ blocks:
     weight: 0
     image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/twitter.svg
     image_alt: ''
+  -
+    block_id: 'inline_block:uw_cbl_powerbi'
+    weight: 0
+    image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/powerbi.svg
+    image_alt: ''
+  -
+    block_id: 'inline_block:uw_cbl_google_maps'
+    weight: 0
+    image_path: /profiles/uw_base_profile/themes/uw_fdsu_theme_resp/images/layout_builder_browser/maps_google.svg
+    image_alt: ''
diff --git a/config/install/metatag.settings.yml b/config/install/metatag.settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..77b2e7415847715fa8c8184b3b6a19530294763f
--- /dev/null
+++ b/config/install/metatag.settings.yml
@@ -0,0 +1,26 @@
+entity_type_groups:
+  node:
+    uw_ct_blog:
+      basic: basic
+      advanced: advanced
+      open_graph: open_graph
+      twitter_cards: twitter_cards
+      schema_article: schema_article
+    uw_ct_event:
+      basic: basic
+      advanced: advanced
+      open_graph: open_graph
+      twitter_cards: twitter_cards
+      schema_event: schema_event
+    uw_ct_news_item:
+      basic: basic
+      advanced: advanced
+      open_graph: open_graph
+      twitter_cards: twitter_cards
+      schema_article: schema_article
+    uw_ct_web_page:
+      basic: basic
+      advanced: advanced
+      open_graph: open_graph
+      twitter_cards: twitter_cards
+      schema_web_page: schema_web_page
diff --git a/config/install/user.role.anonymous.yml b/config/install/user.role.anonymous.yml
index 3d01ac9df3d27935feb4a2fdae8bbb1c377d6700..d0dc1b6ddb54d65b045168d25967633771de679c 100644
--- a/config/install/user.role.anonymous.yml
+++ b/config/install/user.role.anonymous.yml
@@ -21,3 +21,4 @@ permissions:
   - 'view paragraph content uw_para_fact_text'
   - 'view paragraph content uw_para_facts_and_figures'
   - 'view paragraph content uw_para_ff'
+  - 'view paragraph content uw_para_timeline'
diff --git a/config/install/user.role.authenticated.yml b/config/install/user.role.authenticated.yml
index 1c4c2893cecf32d6867e99dcf428f0d1ae2f6eb6..c4bf03a464f402b6ef22db28d8d4057c5425f8a5 100644
--- a/config/install/user.role.authenticated.yml
+++ b/config/install/user.role.authenticated.yml
@@ -24,4 +24,5 @@ permissions:
   - 'view paragraph content uw_para_fact_text'
   - 'view paragraph content uw_para_facts_and_figures'
   - 'view paragraph content uw_para_ff'
+  - 'view paragraph content uw_para_timeline'
   - 'view the administration theme'
diff --git a/config/install/user.role.uw_role_content_author.yml b/config/install/user.role.uw_role_content_author.yml
index 980e028dc15c4434aad9c26b9a270db182377a41..438b798d6428a45885cdd1d9494b1fece98a06d1 100644
--- a/config/install/user.role.uw_role_content_author.yml
+++ b/config/install/user.role.uw_role_content_author.yml
@@ -38,6 +38,7 @@ permissions:
   - 'create paragraph content uw_para_fact_text'
   - 'create paragraph content uw_para_facts_and_figures'
   - 'create paragraph content uw_para_ff'
+  - 'create paragraph content uw_para_timeline'
   - 'create terms in uw_tax_event_tags'
   - 'create terms in uw_tax_event_type'
   - 'create terms in uw_vocab_audience'
@@ -47,6 +48,7 @@ permissions:
   - 'create terms in uw_vocab_news_tags'
   - 'create url aliases'
   - 'create uw_ct_blog content'
+  - 'create uw_ct_catalog_item content'
   - 'create uw_ct_event content'
   - 'create uw_ct_news_item content'
   - 'create uw_ct_sidebar content'
@@ -62,13 +64,16 @@ permissions:
   - 'delete paragraph content uw_para_fact_text'
   - 'delete paragraph content uw_para_facts_and_figures'
   - 'delete paragraph content uw_para_ff'
+  - 'delete paragraph content uw_para_timeline'
   - 'edit any uw_ct_blog content'
+  - 'edit any uw_ct_catalog_item content'
   - 'edit any uw_ct_event content'
   - 'edit any uw_ct_news_item content'
   - 'edit any uw_ct_sidebar content'
   - 'edit any uw_ct_site_footer content'
   - 'edit any uw_ct_web_page content'
   - 'edit own uw_ct_blog content'
+  - 'edit own uw_ct_catalog_item content'
   - 'edit own uw_ct_event content'
   - 'edit own uw_ct_news_item content'
   - 'edit own uw_ct_sidebar content'
@@ -85,6 +90,7 @@ permissions:
   - 'make smart dates recur'
   - 'reschedule smart date recur instances'
   - 'revert uw_ct_blog revisions'
+  - 'revert uw_ct_catalog_item revisions'
   - 'revert uw_ct_event revisions'
   - 'revert uw_ct_news_item revisions'
   - 'revert uw_ct_sidebar revisions'
@@ -99,6 +105,7 @@ permissions:
   - 'update paragraph content uw_para_fact_text'
   - 'update paragraph content uw_para_facts_and_figures'
   - 'update paragraph content uw_para_ff'
+  - 'update paragraph content uw_para_timeline'
   - 'use uw_workflow transition needs_review'
   - 'use workbench access'
   - 'view all media revisions'
@@ -109,6 +116,7 @@ permissions:
   - 'view own unpublished media'
   - 'view unpublished paragraphs'
   - 'view uw_ct_blog revisions'
+  - 'view uw_ct_catalog_item revisions'
   - 'view uw_ct_event revisions'
   - 'view uw_ct_news_item revisions'
   - 'view uw_ct_sidebar revisions'
diff --git a/config/install/user.role.uw_role_content_editor.yml b/config/install/user.role.uw_role_content_editor.yml
index 269b69361e42eb29232df67531afb284db7925f4..d9dac7e2defeca1f149a045c91e127d19629f3c9 100644
--- a/config/install/user.role.uw_role_content_editor.yml
+++ b/config/install/user.role.uw_role_content_editor.yml
@@ -39,6 +39,7 @@ permissions:
   - 'create paragraph content uw_para_fact_text'
   - 'create paragraph content uw_para_facts_and_figures'
   - 'create paragraph content uw_para_ff'
+  - 'create paragraph content uw_para_timeline'
   - 'create terms in uw_tax_event_tags'
   - 'create terms in uw_tax_event_type'
   - 'create terms in uw_vocab_audience'
@@ -48,6 +49,7 @@ permissions:
   - 'create terms in uw_vocab_news_tags'
   - 'create url aliases'
   - 'create uw_ct_blog content'
+  - 'create uw_ct_catalog_item content'
   - 'create uw_ct_event content'
   - 'create uw_ct_news_item content'
   - 'create uw_ct_sidebar content'
@@ -63,13 +65,16 @@ permissions:
   - 'delete paragraph content uw_para_fact_text'
   - 'delete paragraph content uw_para_facts_and_figures'
   - 'delete paragraph content uw_para_ff'
+  - 'delete paragraph content uw_para_timeline'
   - 'edit any uw_ct_blog content'
+  - 'edit any uw_ct_catalog_item content'
   - 'edit any uw_ct_event content'
   - 'edit any uw_ct_news_item content'
   - 'edit any uw_ct_sidebar content'
   - 'edit any uw_ct_site_footer content'
   - 'edit any uw_ct_web_page content'
   - 'edit own uw_ct_blog content'
+  - 'edit own uw_ct_catalog_item content'
   - 'edit own uw_ct_event content'
   - 'edit own uw_ct_news_item content'
   - 'edit own uw_ct_sidebar content'
@@ -86,6 +91,7 @@ permissions:
   - 'make smart dates recur'
   - 'reschedule smart date recur instances'
   - 'revert uw_ct_blog revisions'
+  - 'revert uw_ct_catalog_item revisions'
   - 'revert uw_ct_event revisions'
   - 'revert uw_ct_news_item revisions'
   - 'revert uw_ct_sidebar revisions'
@@ -100,6 +106,7 @@ permissions:
   - 'update paragraph content uw_para_fact_text'
   - 'update paragraph content uw_para_facts_and_figures'
   - 'update paragraph content uw_para_ff'
+  - 'update paragraph content uw_para_timeline'
   - 'use uw_workflow transition archived'
   - 'use uw_workflow transition draft'
   - 'use uw_workflow transition needs_review'
@@ -113,6 +120,7 @@ permissions:
   - 'view own unpublished media'
   - 'view unpublished paragraphs'
   - 'view uw_ct_blog revisions'
+  - 'view uw_ct_catalog_item revisions'
   - 'view uw_ct_event revisions'
   - 'view uw_ct_news_item revisions'
   - 'view uw_ct_sidebar revisions'
diff --git a/config/install/user.role.uw_role_site_manager.yml b/config/install/user.role.uw_role_site_manager.yml
index c99b9fcb043fcb2c59e960e76b6c2b30f663eb1b..f1ef4627356b8094f98b05a37ecd16d8d151ce75 100644
--- a/config/install/user.role.uw_role_site_manager.yml
+++ b/config/install/user.role.uw_role_site_manager.yml
@@ -40,6 +40,7 @@ permissions:
   - 'create paragraph content uw_para_fact_text'
   - 'create paragraph content uw_para_facts_and_figures'
   - 'create paragraph content uw_para_ff'
+  - 'create paragraph content uw_para_timeline'
   - 'create terms in uw_tax_event_tags'
   - 'create terms in uw_tax_event_type'
   - 'create terms in uw_vocab_audience'
@@ -49,6 +50,7 @@ permissions:
   - 'create terms in uw_vocab_news_tags'
   - 'create url aliases'
   - 'create uw_ct_blog content'
+  - 'create uw_ct_catalog_item content'
   - 'create uw_ct_event content'
   - 'create uw_ct_news_item content'
   - 'create uw_ct_sidebar content'
@@ -58,6 +60,7 @@ permissions:
   - 'delete all revisions'
   - 'delete any media'
   - 'delete any uw_ct_blog content'
+  - 'delete any uw_ct_catalog_item content'
   - 'delete any uw_ct_event content'
   - 'delete any uw_ct_news_item content'
   - 'delete any uw_ct_sidebar content'
@@ -66,6 +69,7 @@ permissions:
   - 'delete any uw_news_item content'
   - 'delete orphan revisions'
   - 'delete own uw_ct_blog content'
+  - 'delete own uw_ct_catalog_item content'
   - 'delete own uw_ct_event content'
   - 'delete own uw_ct_news_item content'
   - 'delete own uw_ct_sidebar content'
@@ -80,6 +84,7 @@ permissions:
   - 'delete paragraph content uw_para_fact_text'
   - 'delete paragraph content uw_para_facts_and_figures'
   - 'delete paragraph content uw_para_ff'
+  - 'delete paragraph content uw_para_timeline'
   - 'delete terms in uw_tax_event_tags'
   - 'delete terms in uw_tax_event_type'
   - 'delete terms in uw_vocab_audience'
@@ -89,6 +94,7 @@ permissions:
   - 'delete terms in uw_vocab_news_tags'
   - 'delete uw_news_item revisions'
   - 'edit any uw_ct_blog content'
+  - 'edit any uw_ct_catalog_item content'
   - 'edit any uw_ct_event content'
   - 'edit any uw_ct_news_item content'
   - 'edit any uw_ct_sidebar content'
@@ -96,6 +102,7 @@ permissions:
   - 'edit any uw_ct_web_page content'
   - 'edit any uw_news_item content'
   - 'edit own uw_ct_blog content'
+  - 'edit own uw_ct_catalog_item content'
   - 'edit own uw_ct_event content'
   - 'edit own uw_ct_news_item content'
   - 'edit own uw_ct_sidebar content'
@@ -113,6 +120,7 @@ permissions:
   - 'reschedule smart date recur instances'
   - 'revert all revisions'
   - 'revert uw_ct_blog revisions'
+  - 'revert uw_ct_catalog_item revisions'
   - 'revert uw_ct_event revisions'
   - 'revert uw_ct_news_item revisions'
   - 'revert uw_ct_sidebar revisions'
@@ -128,6 +136,7 @@ permissions:
   - 'update paragraph content uw_para_fact_text'
   - 'update paragraph content uw_para_facts_and_figures'
   - 'update paragraph content uw_para_ff'
+  - 'update paragraph content uw_para_timeline'
   - 'use uw_workflow transition archived'
   - 'use uw_workflow transition draft'
   - 'use uw_workflow transition needs_review'
@@ -141,6 +150,7 @@ permissions:
   - 'view own unpublished media'
   - 'view unpublished paragraphs'
   - 'view uw_ct_blog revisions'
+  - 'view uw_ct_catalog_item revisions'
   - 'view uw_ct_event revisions'
   - 'view uw_ct_news_item revisions'
   - 'view uw_ct_sidebar revisions'
diff --git a/layouts/uw-inverted-l-right/uw-layout-inverted-l-right.css b/layouts/uw-inverted-l-right/uw-layout-inverted-l-right.css
index 54a5da7f7bcf00411706e477a2118162e92522d0..97b0651fa597d5ad1d8bb7c7913aa047ab83a488 100644
--- a/layouts/uw-inverted-l-right/uw-layout-inverted-l-right.css
+++ b/layouts/uw-inverted-l-right/uw-layout-inverted-l-right.css
@@ -43,4 +43,4 @@
   box-shadow: none;
   border: 1px solid #bfbfba;
   padding: 1rem;
-}
\ No newline at end of file
+}
diff --git a/src/Access/UwNodeAccessCheck.php b/src/Access/UwNodeAccessCheck.php
index a805775f5510f755a9ab42e27dd72fbb7a022b33..0c190d08124f36fd1c0aa2452cc26451742b536e 100644
--- a/src/Access/UwNodeAccessCheck.php
+++ b/src/Access/UwNodeAccessCheck.php
@@ -17,7 +17,7 @@ class UwNodeAccessCheck implements AccessInterface {
    * A custom access check.
    *
    * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *
+   *   Route matching.
    * @param \Drupal\Core\Session\AccountInterface $account
    *   Run access checks for this account.
    *
@@ -29,22 +29,26 @@ class UwNodeAccessCheck implements AccessInterface {
     // Get the node object, which is in the route match variable.
     $node = $route_match->getParameter('node');
 
-    // Check if this is a sidebar content type and if the user has permission to edit the content type.
-    // We want to throw a 404 (NotFoundHttpException) if they do not have access.  This is the case when
-    // a user is not logged in, and when they do not have permission to edit it.
+    // Check if this is a sidebar content type and if the user has permission
+    // to edit the content type. We want to throw a 404 (NotFoundHttpException)
+    // if they do not have access.  This is the case when a user is not logged
+    // in, and when they do not have permission to edit it.
     if ($node && $node->bundle() == 'uw_ct_sidebar' && !$account->hasPermission('edit any uw_ct_sidebar content')) {
       throw new NotFoundHttpException();
     }
 
-    // Check if this is a sidebar content type and if the user has permission to edit the content type.
-    // We want to throw a 404 (NotFoundHttpException) if they do not have access.  This is the case when
-    // a user is not logged in, and when they do not have permission to edit it.
+    // Check if this is a sidebar content type and if the user has permission
+    // to edit the content type. We want to throw a 404 (NotFoundHttpException)
+    // if they do not have access.  This is the case when a user is not logged
+    // in, and when they do not have permission to edit it.
     if ($node && $node->bundle() == 'uw_ct_site_footer' && !$account->hasPermission('edit any uw_ct_site_footer content')) {
       throw new NotFoundHttpException();
     }
 
-    // We have to return some type of access, so we are going to return allowed, if they do not have access,
-    // the new exception is going to be thrown above.
+    // We have to return some type of access, so we are going to return
+    // allowed, if they do not have access, the new exception is going to be
+    // thrown above.
     return AccessResult::allowed();
   }
+
 }
diff --git a/src/Form/UwContentModerationForm.php b/src/Form/UwContentModerationForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1c03a08b4c77627d9eff8c4d3fbc06f64a3d15c
--- /dev/null
+++ b/src/Form/UwContentModerationForm.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace Drupal\uw_cfg_common\Form;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Form class for the content access form.
+ */
+class UwContentModerationForm extends ConfirmFormBase {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The nid (node id).
+   *
+   * @var int
+   */
+  protected $nid;
+
+  /**
+   * The vid (version id).
+   *
+   * @var int
+   */
+  protected $vid;
+
+  /**
+   * Class constructor.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    // Instantiates this form class.
+    return new static(
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'uw_content_moderation_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, $nid = NULL, $vid = NULL) {
+
+    // Set the node and version ids.
+    $this->nid = $nid;
+    $this->vid = $vid;
+
+    // Return the form from the parent (confirm form).
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+
+    // Set the options for the URL.
+    $options = ['absolute' => TRUE];
+
+    // Return the URL back to the node.
+    $url = Url::fromRoute('entity.node.canonical', ['node' => $this->nid], $options);
+
+    // Adding the redirect back to the node.
+    $form_state->setRedirectUrl($url);
+
+    // Set the message that the permissions have been saved.
+    $this->messenger()->addStatus($this->t('There is still work to be done to unpublish, but we made it here.'));
+  }
+
+  /**
+   * Returns the question to ask the user.
+   *
+   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
+   *   The form question. The page title will be set to this value.
+   */
+  public function getQuestion() {
+
+    // Get the node object.
+    $node = $this->entityTypeManager->getStorage('node')->load($this->nid);
+
+    // Return the question to see if they want to publish the node.
+    return $this->t('Are you sure you want to unpublish %node_title?', ['%node_title' => $node->getTitle()]);
+  }
+
+  /**
+   * Returns the route to go to if the user cancels the action.
+   *
+   * @return \Drupal\Core\Url
+   *   A URL object.
+   */
+  public function getCancelUrl() {
+
+    // Set the options for the URL.
+    $options = ['absolute' => TRUE];
+
+    // Return the URL back to the node.
+    return Url::fromRoute('entity.node.canonical', ['node' => $this->nid], $options);
+  }
+
+}
diff --git a/src/Plugin/Layout/Uw2ColumnLayout.php b/src/Plugin/Layout/Uw2ColumnLayout.php
index e1516e8a3e23bb321671ec90ecc79b89b041ebe2..eb4916305640466cbfcea96d02df1fa948953d4d 100644
--- a/src/Plugin/Layout/Uw2ColumnLayout.php
+++ b/src/Plugin/Layout/Uw2ColumnLayout.php
@@ -34,4 +34,5 @@ class Uw2ColumnLayout extends UwColumnLayoutBase {
 
     return $form;
   }
+
 }
diff --git a/src/Plugin/Layout/Uw3ColumnLayout.php b/src/Plugin/Layout/Uw3ColumnLayout.php
index 84171c80f70b76d079e27aaace7816c01eccd7e1..308cc01ff3c8d570379baf881b6e96bd9472eeb5 100644
--- a/src/Plugin/Layout/Uw3ColumnLayout.php
+++ b/src/Plugin/Layout/Uw3ColumnLayout.php
@@ -37,4 +37,5 @@ class Uw3ColumnLayout extends UwColumnLayoutBase {
 
     return $form;
   }
+
 }
diff --git a/src/Plugin/Layout/Uw4ColumnLayout.php b/src/Plugin/Layout/Uw4ColumnLayout.php
index de8260e5aeb334a06d426ea8124ae0f1fabee09e..c4c655ec5e7c4e957ca3a5fd63e87b9aa0fa7d5a 100644
--- a/src/Plugin/Layout/Uw4ColumnLayout.php
+++ b/src/Plugin/Layout/Uw4ColumnLayout.php
@@ -37,4 +37,5 @@ class Uw4ColumnLayout extends UwColumnLayoutBase {
 
     return $form;
   }
+
 }
diff --git a/src/Plugin/Layout/UwColumnLayoutBase.php b/src/Plugin/Layout/UwColumnLayoutBase.php
index 299833fe1dbac07c8acfb152b7c55c037a3a0643..06460ba4d740a6c49e53351e75a137bb5b53674f 100644
--- a/src/Plugin/Layout/UwColumnLayoutBase.php
+++ b/src/Plugin/Layout/UwColumnLayoutBase.php
@@ -17,7 +17,10 @@ class UwColumnLayoutBase extends LayoutDefault implements PluginFormInterface {
   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
 
     // Set the column class in the config.
-    $this->configuration['column_class'] = $form_state->getValue(['layout_settings', 'column_class'], NULL);
+    $this->configuration['column_class'] = $form_state->getValue(
+      ['layout_settings', 'column_class'],
+      NULL
+    );
   }
 
   /**
diff --git a/src/Routing/UwNodeAccessRouteSubscriber.php b/src/Routing/UwNodeAccessRouteSubscriber.php
index 2b7f39544af31d0d2d09dd57be0dbdfa01cdaf92..d5309c69fe257f4c71aa0fda8cb7e26e726d9c83 100644
--- a/src/Routing/UwNodeAccessRouteSubscriber.php
+++ b/src/Routing/UwNodeAccessRouteSubscriber.php
@@ -1,23 +1,23 @@
-<?php
-
-namespace Drupal\uw_cfg_common\Routing;
-
-use Drupal\Core\Routing\RouteSubscriberBase;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * Listens to the dynamic route events.
- */
-class UwNodeAccessRouteSubscriber extends RouteSubscriberBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function alterRoutes(RouteCollection $collection) {
-    // Change the route associated with node (/node/{nid}).
-    if ($route = $collection->get('entity.node.canonical')) {
-      $route->setRequirement('_custom_access', 'Drupal\uw_cfg_common\Access\UwNodeAccessCheck::access');
-    }
-  }
-
-}
\ No newline at end of file
+<?php
+
+namespace Drupal\uw_cfg_common\Routing;
+
+use Drupal\Core\Routing\RouteSubscriberBase;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Listens to the dynamic route events.
+ */
+class UwNodeAccessRouteSubscriber extends RouteSubscriberBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function alterRoutes(RouteCollection $collection) {
+    // Change the route associated with node (/node/{nid}).
+    if ($route = $collection->get('entity.node.canonical')) {
+      $route->setRequirement('_custom_access', 'Drupal\uw_cfg_common\Access\UwNodeAccessCheck::access');
+    }
+  }
+
+}
diff --git a/src/Service/UWService.php b/src/Service/UWService.php
index 821964d7cc5176495b78e77006f90b37fb1c3f92..0643499d9a875429d844cb829af2768a44c69601 100644
--- a/src/Service/UWService.php
+++ b/src/Service/UWService.php
@@ -3,16 +3,46 @@
 namespace Drupal\uw_cfg_common\Service;
 
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\node\Entity\Node;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\node\NodeInterface;
+use Drupal\Core\Database\Connection;
 
 /**
- * Class UWService
+ * Class UWService.
+ *
+ * UW Service that holds common functionality used by uw blocks.
  *
  * @package Drupal\uw_cfg_common\Service
  */
 class UWService implements UWServiceInterface {
 
+  /**
+   * Entity type manager from core.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  private $entityTypeManager;
+
+  /**
+   * Database connection.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  private $database;
+
+  /**
+   * Default constructor.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
+   *   Entity Type Manager from core.
+   * @param \Drupal\Core\Database\Connection $database
+   *   The database entity.
+   */
+  public function __construct(EntityTypeManagerInterface $entityTypeManager, Connection $database) {
+    $this->entityTypeManager = $entityTypeManager;
+    $this->database = $database;
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -157,4 +187,76 @@ class UWService implements UWServiceInterface {
     return $variables;
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  public function getOrCheckAttachedSidebar(int $attached_page_nid, int $sidebar_nid = NULL, string $type = NULL): int {
+
+    // A database called to get the field with the condition of the
+    // attached_page_nid.
+    $result = $this->database
+      ->select('node__field_uw_attach_page', 'nfuap')
+      ->fields('nfuap', ['entity_id', 'field_uw_attach_page_target_id'])
+      ->condition('field_uw_attach_page_target_id', $attached_page_nid);
+
+    // If we are doing a a check for sidebar, then add the condition
+    // that it is not equal to the current sidebar_nid that we are on.
+    // Meaning that we are checking for any other sidebars that this
+    // attached_page_nid is attached to.
+    if ($type == 'check') {
+
+      // Add the not equals to condition.
+      $result->condition('entity_id', $sidebar_nid, '<>');
+    }
+
+    // Get the results of query, we only need to fetch, because we are
+    // only every expecting one sidebar only has one other node page
+    // attached.
+    $results = $result->execute()->fetch();
+
+    // If we have results, then return the entity_id, which is the
+    // sidebar_nid that the attached_page_nid is attached to.
+    if (isset($results->entity_id)) {
+
+      // Return the entity_id.
+      return $results->entity_id;
+    }
+
+    // If we made it here, there are no other sidebars that the
+    // attached_page_nid is attached to, so we can simply return 0.
+    else {
+      return 0;
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public function getUwContentTypes($with_sidebar = FALSE): array {
+    $return_content_types = [];
+
+    // This is the list of all UW content types, with a TRUE/FALSE, indicating
+    // whether or not a sidebar can be attached to this content type.
+    $content_types = [
+      'uw_ct_blog' => TRUE,
+      'uw_ct_catalog_item' => FALSE,
+      'uw_ct_event' => TRUE,
+      'uw_ct_news_item' => TRUE,
+      'uw_ct_sidebar' => FALSE,
+      'uw_ct_site_footer' => FALSE,
+      'uw_ct_web_page' => TRUE,
+    ];
+
+    foreach ($content_types as $key => $value) {
+      if ($with_sidebar && $value) {
+        $return_content_types[] = $key;
+      }
+      elseif (!$with_sidebar) {
+        $return_content_types[] = $key;
+      }
+    }
+
+    return $return_content_types;
+  }
+
 }
diff --git a/src/Service/UWServiceInterface.php b/src/Service/UWServiceInterface.php
index 360bbf854105a40e71b107adc78dc807751d1b78..f0c17c456875cfcecf0780fb3e913c748ff2a9bb 100644
--- a/src/Service/UWServiceInterface.php
+++ b/src/Service/UWServiceInterface.php
@@ -6,9 +6,9 @@ use Drupal\Core\Entity\EntityInterface;
 use Drupal\node\NodeInterface;
 
 /**
- * Interface UWServiceInterface
+ * Interface UWServiceInterface.
  *
- * Interface that is collection of common functions used throughout custom blocks.
+ * Interface that is collection of common functions used in custom blocks.
  *
  * @package Drupal\uw_cfg_common\Service
  */
@@ -41,4 +41,46 @@ interface UWServiceInterface {
    *   Array of variables and their values.
    */
   public function getTeaserContent(NodeInterface $node, array $variables_to_get, string $teaser_type): array;
+
+  /**
+   * A function to get or check the attached sidebar.
+   *
+   * If the type is set to check, then the function will return one
+   * of two things. It will either return a 0, which means that the
+   * attached_page_nid is not attached to any other sidebar in the
+   * system.  Or it will return the entity_id of the sidebar (sidebar_nid)
+   * that it is currently attached to.
+   *
+   * For example:
+   *   If the attached_page_nid is 3 and the sidebar_nid is 7, and
+   *   the query finds that 3 is already attached to sidebar_nid 6, then 6
+   *   will be returned.
+   *
+   *   If the attached_page_nid is 3 and the sidebar_nid is 7, and
+   *   the query finds no other sidebar_nids that 3 is attached to, then 0
+   *   will be returned.
+   *
+   * @param int $attached_page_nid
+   *   An integer value that represents the nid of the page to be attached to.
+   * @param int|null $sidebar_nid
+   *   An integer value that represents the nid of the current sidebar.
+   * @param string|null $type
+   *   A string value that represents either "get" or "check".
+   *
+   * @return int
+   *   A value that is either 0 (no nids) or the entity_id of a sidebar.
+   */
+  public function getOrCheckAttachedSidebar(int $attached_page_nid, int $sidebar_nid = NULL, string $type = NULL): int;
+
+  /**
+   * A function to get an array of UW content types, with or without sidebar.
+   *
+   * @param bool $with_sidebar
+   *   A boolean to state if we want content types that can have sidebars.
+   *
+   * @return array
+   *   An array of the machine names of the UW content types.
+   */
+  public function getUwContentTypes(bool $with_sidebar = FALSE): array;
+
 }
diff --git a/src/UwPermissions/UwPermissions.php b/src/UwPermissions/UwPermissions.php
index 7c229a783fa9ca98d18a98095a8b346294912f28..7b6411f8c4217b001afb35897b6a20157e4ecac6 100644
--- a/src/UwPermissions/UwPermissions.php
+++ b/src/UwPermissions/UwPermissions.php
@@ -6,6 +6,8 @@ use Drupal\user\Entity\Role;
 
 /**
  * Class UwPermissions.
+ *
+ * UW Specific permissions.
  */
 class UwPermissions {
 
@@ -54,54 +56,135 @@ class UwPermissions {
       // Blog permissions.
       'Blog' => [
         'Use content type' =>
-        UwPermissions::buildRolePermissionsListContentType('uw_ct_blog'),
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_blog'
+        ),
         'Create/edit tags' =>
-        UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_vocab_blog_tags', ['create', 'edit']),
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_blog_tags',
+          ['create', 'edit']
+        ),
         'Delete tags' =>
-        UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_vocab_blog_tags', ['delete']),
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_blog_tags',
+          ['delete']
+        ),
+      ],
+
+      // Catalog permissions.
+      'Catalog' => [
+        'Use content type' =>
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_catalog_item'
+        ),
+        'Create/edit audience' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_audience',
+          ['create', 'edit']
+        ),
+        'Delete audience' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_audience',
+          ['delete']
+        ),
+        'Create/edit categories' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_catalog_categories',
+          ['create', 'edit']
+        ),
+        'Delete categories' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_catalog_categories',
+          ['delete']
+        ),
+        'Create/edit catalogs' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_catalogs',
+          ['create', 'edit']
+        ),
+        'Delete catalogs' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_catalogs',
+          ['delete']
+        ),
       ],
 
       // Event permissions.
       'Event' => [
-        'Use content type' => UwPermissions::buildRolePermissionsListContentType('uw_ct_event'),
-        'Create/edit tags' => UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_tax_event_tags', ['create', 'edit']),
-        'Delete tags' => UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_tax_event_tags', ['delete']),
-        'Create/edit types' => UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_tax_event_type', ['create', 'edit']),
-        'Delete types' => UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_tax_event_type', ['delete']),
+        'Use content type' =>
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_event'
+        ),
+        'Create/edit tags' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_tax_event_tags',
+          ['create', 'edit']
+        ),
+        'Delete tags' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_tax_event_tags',
+          ['delete']
+        ),
+        'Create/edit types' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_tax_event_type',
+          ['create', 'edit']
+        ),
+        'Delete types' =>
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_tax_event_type',
+          ['delete']
+        ),
       ],
 
       // News permissions.
       'News' => [
         'Use content type' =>
-        UwPermissions::buildRolePermissionsListContentType('uw_ct_news_item'),
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_news_item'
+        ),
         'Create/edit tags' =>
-        UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_vocab_news_tags', ['create', 'edit']),
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_news_tags',
+          ['create', 'edit']
+        ),
         'Delete tags' =>
-        UwPermissions::buildRolePermissionsListTaxonomyTerm('uw_vocab_news_tags', ['delete']),
+        UwPermissions::buildRolePermissionsListTaxonomyTerm(
+          'uw_vocab_news_tags',
+          ['delete']
+        ),
       ],
 
       // Sidebar permissions.
       'Sidebar' => [
         'Use content type' =>
-          UwPermissions::buildRolePermissionsListContentType('uw_ct_sidebar'),
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_sidebar'
+        ),
       ],
 
       // Site footer permissions.
       'Site footer' => [
         'Use content type' =>
-        UwPermissions::buildRolePermissionsListContentType('uw_ct_site_footer'),
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_site_footer'
+        ),
       ],
 
       // Special alert permissions.
       'Special alert' => [
         'Use content type' =>
-        UwPermissions::buildRolePermissionsListCustom('administer special alert'),
+        UwPermissions::buildRolePermissionsListCustom(
+          'administer special alert'
+        ),
       ],
 
       // Web page permissions.
       'Web page' => [
         'Use content type' =>
-        UwPermissions::buildRolePermissionsListContentType('uw_ct_web_page'),
+        UwPermissions::buildRolePermissionsListContentType(
+          'uw_ct_web_page'
+        ),
       ],
     ];
 
diff --git a/uw_cfg_common.install b/uw_cfg_common.install
index 22a8f5e07651db13044d3237b5716b2913986253..b427141fffb1119800cbd0ad26e67f834a803580 100644
--- a/uw_cfg_common.install
+++ b/uw_cfg_common.install
@@ -5,6 +5,7 @@
  * Install, update and uninstall for Configuration of all common WCMS.
  */
 
+use Drupal\taxonomy\Entity\Term;
 use Drupal\uw_cfg_common\UwPermissions\UwPermissions;
 
 /**
@@ -27,6 +28,37 @@ function uw_cfg_common_install() {
         'Site manager',
       ],
     ],
+    'Catalog' => [
+      'Use content type' => [
+        'Site manager',
+        'Content author',
+        'Content editor',
+      ],
+      'Create/edit audience' => [
+        'Site manager',
+        'Content author',
+        'Content editor',
+      ],
+      'Delete audience' => [
+        'Site manager',
+      ],
+      'Create/edit categories' => [
+        'Site manager',
+        'Content author',
+        'Content editor',
+      ],
+      'Delete categories' => [
+        'Site manager',
+      ],
+      'Create/edit catalogs'    => [
+        'Site manager',
+        'Content author',
+        'Content editor',
+      ],
+      'Delete catalogs' => [
+        'Site manager',
+      ],
+    ],
     'Event' => [
       'Use content type' => [
         'Site manager',
@@ -106,29 +138,29 @@ function uw_cfg_common_install() {
       'Future undergraduate students',
       'Future graduate students',
     ],
-    'Faculty',
-    'Staff',
-    'Alumni',
-    'Parents',
-    'Donors | Friends | Supporters',
-    'Employers',
-    'International',
-    'Media',
+    'Faculty' => 'Faculty',
+    'Staff' => 'Staff',
+    'Alumni' => 'Alumni',
+    'Parents' => 'Parents',
+    'Donors | Friends | Supporters' => 'Donors | Friends | Supporters',
+    'Employers' => 'Employers',
+    'International' => 'International',
+    'Media' => 'Media',
   ];
 
   $weight = 0;
   foreach ($terms as $key => $term) {
-   if (is_array($term)) {
-     $parent = _uw_cfg_common_create_term($key, 'uw_vocab_audience', $weight, []);
+    if (is_array($term)) {
+      $parent = _uw_cfg_common_create_term($key, 'uw_vocab_audience', $weight, []);
 
-     foreach ($term as $child) {
-       _uw_cfg_common_create_term($child, 'uw_vocab_audience', $weight, [$parent]);
-     }
-   }
-   else {
-    _uw_cfg_common_create_term($term, 'uw_vocab_audience', $weight, []);
-   }
-   $weight++;
+      foreach ($term as $child) {
+        _uw_cfg_common_create_term($child, 'uw_vocab_audience', $weight, [$parent]);
+      }
+    }
+    else {
+      _uw_cfg_common_create_term($term, 'uw_vocab_audience', $weight, []);
+    }
+    $weight++;
   }
 }
 
@@ -148,20 +180,24 @@ function uw_cfg_common_install() {
  * $term_id = _nodemaker_term_create('My Term', 'my_vocab', 0, [999]);
  * @endcode
  *
- * @param string $term
+ * @param string $taxonomy_name
  *   - Term Name.
- * @param string $vocabulary
+ * @param string $vocab_machine_name
  *   - System id of the vocabulary term will be added to.
- * @param array $parent
+ * @param string|int $weight
+ *   - Taxonomy term weight.
+ * @param array $parent_tid
  *   - Array of term ids to be assigned as parent.
  *
  * @return int|null
  *   - Returns the term id of the created term on success, null on failure.
+ *
+ * @throws \Drupal\Core\Entity\EntityStorageException
  */
 function _uw_cfg_common_create_term($taxonomy_name, $vocab_machine_name, $weight, array $parent_tid = []) {
 
   // Create the taxonomy term.
-  $new_term = Drupal\taxonomy\Entity\Term::create([
+  $new_term = Term::create([
     'name' => $taxonomy_name,
     'vid' => $vocab_machine_name,
     'parent' => $parent_tid,
diff --git a/uw_cfg_common.module b/uw_cfg_common.module
index 9edb90c3a7c3adf129209e3e724da0b6e070ddd0..45770f0d0b29e68ce5d7818c5bcb496c3cc14072 100644
--- a/uw_cfg_common.module
+++ b/uw_cfg_common.module
@@ -173,3 +173,51 @@ function uw_cfg_common_toolbar_alter(&$items) {
     }
   }
 }
+
+/**
+ * Implements hook_preprocess_node().
+ */
+function uw_cfg_common_preprocess_node(&$variables) {
+
+  // Get the current path.
+  $path = explode('/', \Drupal::service('path.current')->getPath());
+
+  // The paths to place the content moderation block on.  Made this
+  // an array to future proof, if there are more pages later.
+  $paths_for_content_moderation = ['latest'];
+
+  // Check if we are to add the content moderation place.
+  if (in_array(end($path), $paths_for_content_moderation)) {
+
+    // Add the content moderation block.
+    $variables['uw_content_moderation_form'] = \Drupal::formBuilder()->getForm('Drupal\content_moderation\Form\EntityModerationForm', $variables['node']);
+  }
+  else {
+
+    $block_manager = \Drupal::service('plugin.manager.block');
+
+    $plugin_block = $block_manager->createInstance('uw_cbl_content_moderation', []);
+
+    $access_result = $plugin_block->access(\Drupal::currentUser());
+
+    // Return empty render array if user doesn't have access.
+    // $access_result can be boolean or an AccessResult class.
+    if (is_object($access_result) && $access_result->isForbidden() || is_bool($access_result) && !$access_result) {
+      return [];
+    }
+
+    $render = $plugin_block->build();
+
+    $variables['uw_content_moderation_form'] = $render;
+  }
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Set the default of preview mode disabled.
+ */
+function uw_cfg_common_form_node_type_add_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+  $form['submission']['preview_mode']['#default_value'] = 0;
+
+}
diff --git a/uw_cfg_common.routing.yml b/uw_cfg_common.routing.yml
index e64d3636cd0feba0b8c7cde126ee7bc4cd3ca1da..c22fe91f9ccaa3d712f7c8f48cd618cc2e4dc70f 100644
--- a/uw_cfg_common.routing.yml
+++ b/uw_cfg_common.routing.yml
@@ -5,3 +5,10 @@ uw_contact_access.form:
     _form: '\Drupal\uw_cfg_common\Form\UwContentAccessForm'
   requirements:
     _permission: 'access content access form'
+uw_content_moderation.form:
+  path: '/admin/uw-content-moderation/{nid}/{vid}'
+  defaults:
+    _title: 'Content moderation'
+    _form: '\Drupal\uw_cfg_common\Form\UwContentModerationForm'
+  requirements:
+    _permission: 'access content'
\ No newline at end of file
diff --git a/uw_cfg_common.services.yml b/uw_cfg_common.services.yml
index 3ebdfbfa42b4619ed8997f9a3b08a3fee9be95a7..750c7773cb38eff8da0452bcbf2053ab2c0dcb94 100644
--- a/uw_cfg_common.services.yml
+++ b/uw_cfg_common.services.yml
@@ -1,7 +1,7 @@
 services:
   uw_cfg_common.uw_service:
     class: Drupal\uw_cfg_common\Service\UWService
-    arguments: []
+    arguments: ['@entity_type.manager', '@database']
   uw_cfg_common.route_subscriber:
     class: Drupal\uw_cfg_common\Routing\UwNodeAccessRouteSubscriber
     tags: