diff --git a/.github/scripts/update_layer_arn.sh b/.github/scripts/update_layer_arn.sh
new file mode 100755
index 0000000000..51a7149880
--- /dev/null
+++ b/.github/scripts/update_layer_arn.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+# This script is run during the reusable_update_v2_layer_arn_docs CI job,
+# and it is responsible for replacing the layer ARN in our documentation,
+# based on the output files generated by CDK when deploying to each pseudo_region.
+#
+# see .github/workflows/reusable_deploy_v2_layer_stack.yml
+
+set -eo pipefail
+
+if [[ $# -ne 1 ]]; then
+  cat <<EOM
+Usage: $(basename $0) cdk-output-dir
+
+cdk-output-dir: directory containing the cdk output files generated when deploying the Layer
+EOM
+  exit 1
+fi
+
+CDK_OUTPUT_DIR=$1
+
+# Check if CDK output dir is a directory
+if [ ! -d "$CDK_OUTPUT_DIR" ]; then
+  echo "No $CDK_OUTPUT_DIR directory found, not replacing lambda layer versions"
+  exit 1
+fi
+
+# Process each file inside the directory
+files="$CDK_OUTPUT_DIR/*"
+for file in $files; do
+  echo "[+] Processing: $file"
+
+  # Process each line inside the file
+  lines=$(cat "$file")
+  for line in $lines; do
+    echo -e "\t[*] ARN: $line"
+    # line = arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:49
+
+    # From the full ARN, extract everything but the version at the end. This prefix
+    # will later be used to find/replace the ARN on the documentation file.
+    prefix=$(echo "$line" | cut -d ':' -f 1-7)
+    # prefix = arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript
+
+    # Now replace the all "prefix"s in the file with the full new Layer ARN (line)
+    # prefix:\d+ ==> line
+    # sed doesn't support \d+ in a portable way, so we cheat with (:digit: :digit: *)
+    sed -i -e "s/$prefix:[[:digit:]][[:digit:]]*/$line/g" docs/index.md
+
+    # We use the eu-central-1 layer as the version for all the frameworks (SAM, CDK, SLS, etc)
+    # We could have used any other region. What's important is the version at the end.
+
+    # Examples of strings found in the documentation with pseudo regions:
+    # arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:39
+    # arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:39
+    # arn:aws:lambda:${aws:region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:39
+    # arn:aws:lambda:{env.region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:39
+    if [[ "$line" == *"eu-central-1"* ]]; then
+      # These are all the framework pseudo parameters currently found in the docs
+      for pseudo_region in '{region}' '${AWS::Region}' '${aws::region}' '{aws::region}' '{env.region}' '${cdk.Stack.of(this).region}' '${aws.getRegionOutput().name}'; do
+        prefix_pseudo_region=$(echo "$prefix" | sed "s/eu-central-1/${pseudo_region}/")
+        # prefix_pseudo_region = arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScript
+
+        line_pseudo_region=$(echo "$line" | sed "s/eu-central-1/${pseudo_region}/")
+        # line_pseudo_region = arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:49
+
+        # Replace all the "prefix_pseudo_region"'s in the file
+        # prefix_pseudo_region:\d+ ==> line_pseudo_region
+        sed -i -e "s/$prefix_pseudo_region:[[:digit:]][[:digit:]]*/$line_pseudo_region/g" docs/index.md
+      done
+    fi
+  done
+done
diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml
index 838081df3c..812c0e93c4 100644
--- a/.github/workflows/make-release.yml
+++ b/.github/workflows/make-release.yml
@@ -9,6 +9,8 @@ jobs:
   publish-npm:
     needs: run-unit-tests
     runs-on: ubuntu-latest
+    outputs:
+      RELEASE_VERSION: ${{ steps.set-release-version.outputs.RELEASE_VERSION }}
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
@@ -47,3 +49,21 @@ jobs:
           git remote set-url origin https://x-access-token:${GH_TOKEN}@github.com/$GITHUB_REPOSITORY
           npx lerna version --conventional-commits --force-publish --yes
           npx lerna publish from-git --no-verify-access --yes
+      - name: Set release version
+        id: set-release-version
+        run: |
+          RELEASE=$(npm view  @aws-lambda-powertools/tracer version)
+          echo RELEASE_VERSION="$RELEASE_VERSION" >> "$GITHUB_OUTPUT"
+
+  # NOTE: Watch out for the depth limit of 4 nested workflow_calls.
+  # publish_layer -> reusable_deploy_layer_stack -> reusable_update_layer_arn_docs
+  publish_layer:
+    needs: publish-npm
+    secrets: inherit
+    permissions:
+      id-token: write
+      contents: write
+      pages: write
+    uses: ./.github/workflows/publish_layer.yml
+    with:
+      latest_published_version: ${{ needs.publish-npm.outputs.RELEASE_VERSION }}
diff --git a/.github/workflows/on-merge-to-main.yml b/.github/workflows/on-merge-to-main.yml
index 411cd14ee8..8ebd13984a 100644
--- a/.github/workflows/on-merge-to-main.yml
+++ b/.github/workflows/on-merge-to-main.yml
@@ -21,15 +21,6 @@ jobs:
     needs: get_pr_details
     if: ${{ needs.get_pr_details.outputs.prIsMerged == 'true' }}
     uses: ./.github/workflows/reusable-run-linting-check-and-unit-tests.yml
-  publish:
-    needs:
-      [get_pr_details, run-unit-tests]
-    uses: ./.github/workflows/reusable-publish-docs.yml
-    with:
-      workflow_origin: ${{ github.event.repository.full_name }}
-      prIsMerged: ${{ needs.get_pr_details.outputs.prIsMerged }}
-    secrets:
-      token: ${{ secrets.GITHUB_TOKEN }}
   update-release-draft:
     needs: publish
     runs-on: ubuntu-latest
diff --git a/.github/workflows/on_doc_merge.yml b/.github/workflows/on_doc_merge.yml
new file mode 100644
index 0000000000..d412082ee7
--- /dev/null
+++ b/.github/workflows/on_doc_merge.yml
@@ -0,0 +1,24 @@
+name: Docs
+
+on:
+  push:
+    branches:
+      - main
+    paths:
+      - "docs/**"
+      - "mkdocs.yml"
+      - "examples/**"
+
+jobs:
+  release-docs:
+    needs: changelog
+    permissions:
+      contents: write
+      pages: write
+    uses: ./.github/workflows/reusable-publish-docs.yml
+    with:
+      workflow_origin: ${{ github.event.repository.full_name }}
+      version: dev
+      alias: stage
+    secrets:
+      token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/publish-docs-on-release.yml b/.github/workflows/publish-docs-on-release.yml
deleted file mode 100644
index 7d5a4fdcc3..0000000000
--- a/.github/workflows/publish-docs-on-release.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Publish docs on release
-
-on:
-  # Triggered manually
-  workflow_dispatch:
-    inputs:
-      versionNumber:
-        required: true
-        type: string
-        description: "If running this manually please insert a version number that corresponds to the latest published in the GitHub releases (i.e. v1.1.1)"
-  # Or triggered as result of a release
-  release:
-    types: [released]
-
-jobs:
-  publish-docs:
-    uses: ./.github/workflows/reusable-publish-docs.yml
-    with:
-      workflow_origin: ${{ github.event.repository.full_name }}
-      isRelease: "true"
-      versionNumber: ${{ inputs.versionNumber }}
-    secrets:
-      token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/publish_layer.yaml b/.github/workflows/publish_layer.yaml
index 0131612aa6..0f3968dba8 100644
--- a/.github/workflows/publish_layer.yaml
+++ b/.github/workflows/publish_layer.yaml
@@ -12,11 +12,18 @@ on:
         description: "Latest npm published version to rebuild corresponding layer for, e.g. v1.0.2"
         default: "v1.0.2"
         required: true
-  # Automatic trigger after release
-  workflow_run:
-    workflows: ["Make Release"]
-    types:
-      - completed
+
+  workflow_call:
+    inputs:
+      latest_published_version:
+        type: string
+        description: "Latest npm published version to rebuild latest docs for, e.g. 2.0.0, 2.0.0a1 (pre-release)"
+        required: true
+      pre_release:
+        description: "Publishes documentation using a pre-release tag (2.0.0a1)."
+        default: false
+        type: boolean
+        required: false
 
 jobs:
   # Build layer by running cdk synth in layer-publisher directory and uploading cdk.out for deployment
@@ -73,6 +80,7 @@ jobs:
     with:
       stage: "BETA"
       artifact-name: "cdk-layer-artifact"
+      latest_published_version: ${{ inputs.latest_published_version }}
     secrets:
       target-account-role: ${{ secrets.AWS_LAYERS_BETA_ROLE_ARN }}
 
@@ -84,5 +92,33 @@ jobs:
     with:
       stage: "PROD"
       artifact-name: "cdk-layer-artifact"
+      latest_published_version: ${{ inputs.latest_published_version }}
     secrets:
-      target-account-role: ${{ secrets.AWS_LAYERS_PROD_ROLE_ARN }}
\ No newline at end of file
+      target-account-role: ${{ secrets.AWS_LAYERS_PROD_ROLE_ARN }}
+
+  prepare_docs_alias:
+    runs-on: ubuntu-latest
+    permissions:
+      contents: read
+    outputs:
+      DOCS_ALIAS: ${{ steps.set-alias.outputs.DOCS_ALIAS }}
+    steps:
+      - name: Set docs alias
+        id: set-alias
+        run: |
+          DOCS_ALIAS=latest
+          if [[ "${{ inputs.pre_release }}" == true ]] ; then
+            DOCS_ALIAS=alpha
+          fi
+          echo DOCS_ALIAS="$DOCS_ALIAS" >> "$GITHUB_OUTPUT"
+
+  release-docs:
+    needs: [ prod, prepare_docs_alias ]
+    permissions:
+      contents: write
+      pages: write
+    uses: ./.github/workflows/reusable_publish_docs.yml
+    with:
+      version: ${{ inputs.latest_published_version }}
+      alias: ${{ needs.prepare_docs_alias.outputs.DOCS_ALIAS }}
+      detached_mode: true
diff --git a/.github/workflows/reusable-publish-docs.yml b/.github/workflows/reusable-publish-docs.yml
index b2d3aed5da..6c1990a0bb 100644
--- a/.github/workflows/reusable-publish-docs.yml
+++ b/.github/workflows/reusable-publish-docs.yml
@@ -1,22 +1,28 @@
 name: Reusable Publish docs
 
+env:
+  BRANCH: main
+  ORIGIN: awslabs/aws-lambda-powertools-typescript
+
+
 on:
   workflow_call:
     inputs:
-      workflow_origin: # see https://github.com/awslabs/aws-lambda-powertools-python/issues/1349
+      version:
+        description: "Version to build and publish docs (1.28.0, develop)"
         required: true
         type: string
-      prIsMerged:
-        required: false
-        default: "false"
-        type: string
-      isRelease:
-        required: false
-        default: "false"
+      alias:
+        description: "Alias to associate version (latest, stage)"
+        required: true
         type: string
-      versionNumber:
+      detached_mode:
+        description: "Whether it's running in git detached mode to ensure git is sync'd"
         required: false
-        default: ""
+        default: false
+        type: boolean
+      workflow_origin: # see https://github.com/awslabs/aws-lambda-powertools-python/issues/1349
+        required: true
         type: string
     secrets:
       token:
@@ -65,32 +71,6 @@ jobs:
         uses: actions/setup-python@v4
         with:
           python-version: "3.8"
-      # We run this step only when the workflow has been triggered by a release
-      # in this case we publish the docs to `/latest`
-      - name: (Conditional) Set RELEASE_VERSION env var to `latest`
-        if: ${{ inputs.isRelease == 'true' }}
-        run: |
-          RELEASE_VERSION=$(echo ${{ github.ref_name }} | sed 's/v//')
-          EXPLICIT_RELEASE_VERSION=$(echo ${{ inputs.versionNumber }} | sed 's/v//')
-          if [ $EXPLICIT_RELEASE_VERSION != "" ]; then
-            echo "RELEASE_VERSION=${EXPLICIT_RELEASE_VERSION}"
-            echo "RELEASE_VERSION=${EXPLICIT_RELEASE_VERSION}" >> $GITHUB_ENV
-          else
-            echo "RELEASE_VERSION=${RELEASE_VERSION}"
-            echo "RELEASE_VERSION=${RELEASE_VERSION}" >> $GITHUB_ENV
-          fi
-      # We run this step only when the workflow has been triggered by a PR merge
-      # in this case we publish the docs to `/dev`
-      - name: (Conditional) Set RELEASE_VERSION env var to `dev`
-        if: ${{ inputs.prIsMerged == 'true' }}
-        run: |
-          echo "RELEASE_VERSION=dev" >> $GITHUB_ENV
-      - name: Check RELEASE_VERSION env var
-        if: ${{ env.RELEASE_VERSION == '' }}
-        uses: actions/github-script@v3
-        with:
-          script: |
-            core.setFailed('RELEASE_VERSION env var is empty.')
       - name: Install doc generation dependencies
         run: |
           pip install --upgrade pip 
@@ -98,35 +78,41 @@ jobs:
       - name: Setup doc deploy
         run: |
           git config --global user.name Docs deploy
-          git config --global user.email docs@dummy.bot.com
-      - name: Publish docs to latest if isRelease
-        if: ${{ env.RELEASE_VERSION != 'dev' }}
+          git config --global user.email aws-devax-open-source@amazon.com
+      - name: Git refresh tip (detached mode)
+        # Git Detached mode (release notes) doesn't have origin
+        if: ${{ inputs.detached_mode }}
+        run: |
+          git config pull.rebase true
+          git config remote.origin.url >&- || git remote add origin https://github.com/"$ORIGIN"
+          git pull origin "$BRANCH"
+      - name: Build docs website and API reference
+        run: |
+          make release-docs VERSION="$VERSION" ALIAS="$ALIAS"
+          poetry run mike set-default --push latest
+      - name: Build docs website and API reference
+        env:
+          VERSION: ${{ inputs.version }}
+          ALIAS: ${{ inputs.alias }}
         run: |
           rm -rf site
           mkdocs build
-          mike deploy --push --update-aliases --no-redirect "${{ env.RELEASE_VERSION }}" "latest"
+          mike deploy --push --update-aliases --no-redirect ${{ env.VERSION }} ${{ env.ALIAS }}"
           # Set latest version as a default
           mike set-default --push latest
-      - name: Publish docs to dev
-        if: ${{ env.RELEASE_VERSION == 'dev' }}
-        run: |
-          rm -rf site
-          mkdocs build
-          mike deploy --push dev
-      - name: Build API docs
-        run: |
-          rm -rf api
-          npm run docs-generateApiDoc
+
       - name: Release API docs
-        uses: peaceiris/actions-gh-pages@v3
+        uses: peaceiris/actions-gh-pages@bd8c6b06eba6b3d25d72b7a1767993c0aeee42e7 # v3.9.2
+        env:
+          VERSION: ${{ inputs.version }}
         with:
           github_token: ${{ secrets.GITHUB_TOKEN }}
           publish_dir: ./api
           keep_files: true
-          destination_dir: ${{ env.RELEASE_VERSION }}/api
-      - name: Release API docs to latest if isRelease
-        if: ${{ env.RELEASE_VERSION != 'dev' }}
-        uses: peaceiris/actions-gh-pages@v3
+          destination_dir: ${{ env.VERSION }}/api
+      - name: Release API docs to latest
+        if: ${{ input.alias == 'latest' }}
+        uses: peaceiris/actions-gh-pages@bd8c6b06eba6b3d25d72b7a1767993c0aeee42e7
         with:
           github_token: ${{ secrets.GITHUB_TOKEN }}
           publish_dir: ./api
diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml
index 9d56cd9678..cd5961b85b 100644
--- a/.github/workflows/reusable_deploy_layer_stack.yml
+++ b/.github/workflows/reusable_deploy_layer_stack.yml
@@ -8,15 +8,22 @@ on:
   workflow_call:
     inputs:
       stage:
+        description: "Deployment stage (BETA, PROD)"
         required: true
         type: string
       artifact-name:
+        description: "CDK Layer artifact name to download"
+        required: true
+        type: string
+      latest_published_version:
+        description: "Latest version that is published"
         required: true
         type: string
     secrets:
       target-account-role:
         required: true
 
+
 jobs:
   deploy-cdk-stack:
     runs-on: ubuntu-latest
@@ -84,4 +91,24 @@ jobs:
       - name: Unzip artifact
         run: unzip cdk.out.zip
       - name: Deploy Layer
-        run: npm run cdk -w layers -- deploy --app cdk.out --context region=${{ matrix.region }} 'LayerPublisherStack' --require-approval never --verbose
+        run: npm run cdk -w layers -- deploy --app cdk.out --context region=${{ matrix.region }} 'LayerPublisherStack' --require-approval never --verbose --outputs-file cdk-outputs.json
+      - name: Store latest Layer ARN
+        if: ${{ inputs.stage == 'PROD' }}
+        run: |
+          mkdir cdk-layer-stack
+          jq -r -c '.LayerPublisherStack.LatestLayerArn' cdk-outputs.json > cdk-layer-stack/${{ matrix.region }}-layer-version.txt
+          cat cdk-layer-stack/${{ matrix.region }}-layer-version.txt
+      - name: Save Layer ARN artifact
+        if: ${{ inputs.stage == 'PROD' }}
+        uses: actions/upload-artifact@v3
+        with:
+          name: cdk-layer-stack
+          path: ./layer/cdk-layer-stack/* # NOTE: upload-artifact does not inherit working-directory setting.
+          if-no-files-found: error
+          retention-days: 1
+  update_v2_layer_arn_docs:
+    needs: deploy-cdk-stack
+    if: ${{ inputs.stage == 'PROD' }}
+    uses: ./.github/workflows/reusable_update_layer_arn_docs.yml
+    with:
+      latest_published_version: ${{ inputs.latest_published_version }}
\ No newline at end of file
diff --git a/.github/workflows/reusable_update_layer_arn_docs.yml b/.github/workflows/reusable_update_layer_arn_docs.yml
new file mode 100644
index 0000000000..db63440d43
--- /dev/null
+++ b/.github/workflows/reusable_update_layer_arn_docs.yml
@@ -0,0 +1,52 @@
+name: Update V2 Layer ARN Docs
+
+on:
+  workflow_call:
+    inputs:
+      latest_published_version:
+        description: "Latest NPM published version to rebuild latest docs for, e.g. 1.5.1"
+        type: string
+        required: true
+
+permissions:
+  contents: write
+
+env:
+  BRANCH: main
+
+jobs:
+  publish_layer_arn:
+    # Force Github action to run only a single job at a time (based on the group name)
+    # This is to prevent race-condition and inconsistencies with changelog push
+    concurrency:
+      group: changelog-build
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository # reusable workflows start clean, so we need to checkout again
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      - name: Git client setup and refresh tip
+        run: |
+          git config user.name "Release bot"
+          git config user.email "aws-devax-open-source@amazon.com"
+          git config pull.rebase true
+          git config remote.origin.url >&- || git remote add origin https://github.com/"${origin}" # Git Detached mode (release notes) doesn't have origin
+          git pull origin "${BRANCH}"
+      - name: Download CDK layer artifact
+        uses: actions/download-artifact@v3
+        with:
+          name: cdk-layer-stack
+          path: cdk-layer-stack/
+      - name: Replace layer versions in documentation
+        run: |
+          ls -la cdk-layer-stack/
+          ./.github/scripts/update_layer_arn.sh cdk-layer-stack
+      - name: Update documentation in trunk
+        run: |
+          HAS_CHANGE=$(git status --porcelain)
+          test -z "${HAS_CHANGE}" && echo "Nothing to update" && exit 0
+          git add docs/index.md
+          git commit -m "chore: update layer ARN on documentation"
+          git pull origin "${BRANCH}" # prevents concurrent branch update failing push
+          git push origin HEAD:refs/heads/"${BRANCH}"