diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index caca7be44191f92dd447131aea370bc3aa303048..1edb017ba368305f7b913819de28cb23e8465cd7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -36,6 +36,15 @@ build-docker:
     - .docker-matrix
     - .tag-docker-image
 
+## tag contribution branches with a more stable name than `git-${CI_COMMIT_SHORT_SHA}`
+tag contrib branch:
+  extends:
+    - .tag-docker
+    - .on-branches
+  variables:
+    # `feature/foo-bar_quux` → `feature-foo-bar-quux`
+    IMAGE_TAG: $CI_COMMIT_REF_SLUG
+
 ## dev images
 tag dev:
   extends:
diff --git a/Dockerfile.commitlint b/Dockerfile.commitlint
index f24930d17f18c50ee5c9b84fe5c4e3d424d2277b..3668b610476737ef478755f8110f455ac734c5b9 100644
--- a/Dockerfile.commitlint
+++ b/Dockerfile.commitlint
@@ -2,8 +2,8 @@ FROM node:current-alpine
 
 LABEL maintainer="eole@ac-dijon.fr"
 
-ARG COMMITLINT_VERSION=13
-ARG COMMITLINT_CONFIG_CONVENTIONAL_VERSION=13
+ARG COMMITLINT_VERSION=16
+ARG COMMITLINT_CONFIG_CONVENTIONAL_VERSION=16
 
 RUN apk add --no-cache git \
                        ca-certificates
diff --git a/Dockerfile.semantic-release-gitlab b/Dockerfile.semantic-release-gitlab
index 83781fcb0e4288d6bc3c1e805c9783f175848f21..0fab16d3a64d6cce263d753b36fefcd7ff2865e4 100644
--- a/Dockerfile.semantic-release-gitlab
+++ b/Dockerfile.semantic-release-gitlab
@@ -2,11 +2,12 @@ FROM node:current-alpine
 
 LABEL maintainer="eole@ac-dijon.fr"
 
-ARG SEMANTIC_RELEASE_VERSION=18
+ARG SEMANTIC_RELEASE_VERSION=19
 ARG SEMAINTIC_GITLAB_VERSION=7
 ARG SEMAINTIC_CHANGELOG_VERSION=6
 ARG SEMAINTIC_EXEC_VERSION=6
 ARG SEMAINTIC_GIT_VERSION=10
+ARG SEMANTIC_NPM_VERSION=9
 ARG SEMANTIC_PYPI_VERSION=2
 
 RUN apk add --no-cache git \
@@ -26,4 +27,5 @@ RUN npm install -g semantic-release@${SEMAINTIC_RELEASE_VERSION} \
                    @semantic-release/changelog@${SEMAINTIC_CHANGELOG_VERSION} \
                    @semantic-release/exec@${SEMAINTIC_EXEC_VERSION} \
                    @semantic-release/git@${SEMAINTIC_GIT_VERSION} \
+                   @semantic-release/npm@${SEMAINTIC_NPM_VERSION} \
                    semantic-release-pypi@${SEMANTIC_PYPI_VERSION}
diff --git a/docs/GETTING-STARTED.md b/docs/GETTING-STARTED.md
index bba3a6b4b8db1f8024ece83294e04701ebd0a671..68a45da11ca383756373234db12a6419176431e0 100644
--- a/docs/GETTING-STARTED.md
+++ b/docs/GETTING-STARTED.md
@@ -223,10 +223,11 @@ you need mostly 4 steps:
        file: /templates/Lint/Commitlint.yaml
      - project: EOLE/infra/ci-tools
        ref: stable
-       file: /templates/Docker.yaml
+       file: /templates/Release/Semantic-release.yaml
      - project: EOLE/infra/ci-tools
        ref: stable
-       file: /templates/Release/Semantic-release.yaml
+       file: /templates/Docker.yaml
+
 
    stages:
      - initial-checks
@@ -236,8 +237,10 @@ you need mostly 4 steps:
      - release
 
    variables:
+     # Globally defined docker image name
      IMAGE_NAME: useless
 
+
    ###############################################################################
    # `initial-checks` stage: `has-dev-branch`, `has-testing-branch`, `has-stable-branch`
    ###############################################################################
@@ -268,17 +271,35 @@ you need mostly 4 steps:
      variables:
        TARGET_BRANCH: $STABLE_BRANCH
 
+
    ###############################################################################
    # `lint` stage: `commitlint`
    ###############################################################################
    # the `commitlint` is defined in `templates/Lint/Commitlint.yaml` included before
 
+
    ###############################################################################
    # `build` stage: `build-docker`
    ###############################################################################
    # The name of the built image is define globally by `$IMAGE_NAME`
+   # The build is done:
+   # - for contribution branches
+   # - for `$DEV_BRANCH`
+   # - on release tags (stable and testing) after the application
+   #   versions are updated by `semantic-release`
    build-docker:
      extends: .build-docker-image
+     rules:
+       # The ordering is CRITICAL
+       - !reference [.rules-map, not-on-schedule]
+       - !reference [.rules-map, not-on-draft]
+       - !reference [.rules-map, on-release-tag]
+       - !reference [.rules-map, on-testing-tag]
+       - !reference [.rules-map, not-on-stable]
+       - !reference [.rules-map, not-on-testing]
+       - !reference [.rules-map, not-on-semantic-release-commit]
+       - !reference [.rules-map, on-branch]
+
 
    ###############################################################################
    # `test` stage: `useless-test`
@@ -291,10 +312,20 @@ you need mostly 4 steps:
      script:
        - echo "I successfully ran in ${IMAGE_NAME}:git-${CI_COMMIT_SHORT_SHA}"
 
+
    ###############################################################################
-   # `release` stage: `semantic-release`, `merge-to-dev`, `tag *`
+   # `release` stage: `semantic-release`, `testing-prerelease`,
+   #                  `merge-to-dev`, `tag *`
    ###############################################################################
-   # Avoid regression by merging all pre-release fixes to dev
+   # the `semantic-release` is defined in `templates/Release/Semantic-Release.yaml`
+
+   # Create the prereleases versions on `$TESTING_BRANCH`
+   # update `release.config.js` variable `testingBranch`
+   testing-prerelease:
+     extends:
+       - .semantic-release:testing
+
+   # Avoid regression by merging all pre-release fixes to `$DEV_BRANCH`
    merge-to-dev:
      stage: release
      extends: .on-release-tag
@@ -311,6 +342,15 @@ you need mostly 4 steps:
        # Remove `upstream` to avoid caching `CI_JOB_TOKEN`
        - "git remote remove upstream"
 
+   ## tag contribution branches with a more stable name than `git-${CI_COMMIT_SHORT_SHA}`
+   tag contrib branch:
+     extends:
+       - .tag-docker-image
+       - .on-branches
+     variables:
+       # `feature/foo-bar_quux` → `feature-foo-bar-quux`
+       IMAGE_TAG: $CI_COMMIT_REF_SLUG
+
    ## dev images
    tag dev:
      extends:
@@ -323,24 +363,19 @@ you need mostly 4 steps:
    tag testing:
      extends:
        - .tag-docker-image
-       - .on-testing
+       # After `semantic-release`
+       - .on-testing-tag
      variables:
        IMAGE_TAG: testing
 
    ## stable images
-   # we retag the latest `testing`
-   .tag-stable:
-     extends: .tag-docker-image
-     variables:
-       SOURCE_TAG: "testing"
-
    # add the `X.Y.Z` tag
    tag release:
-     extends: .tag-stable
+     extends: .tag-docker-image
 
    # add the `X` tag
    tag major:
-     extends: .tag-stable
+     extends: .tag-docker-image
      before_script:
        - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
        - export RELEASE=${CI_COMMIT_TAG#${RELEASE_PREFIX}}
@@ -348,20 +383,19 @@ you need mostly 4 steps:
 
    # add the `X.Y` tag
    tag minor:
-     extends:
-       - .tag-stable
+     extends: .tag-docker-image
      before_script:
        - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
        - export RELEASE=${CI_COMMIT_TAG#${RELEASE_PREFIX}}
        - export IMAGE_TAG=${RELEASE%.${RELEASE##*.}}
 
    tag stable:
-     extends: .tag-stable
+     extends: .tag-docker-image
      variables:
        IMAGE_TAG: stable
 
    tag latest:
-     extends: .tag-stable
+     extends: .tag-docker-image
      variables:
        IMAGE_TAG: latest
    ```
@@ -441,7 +475,7 @@ to:
 ```diff
 --- .gitlab-ci.yml.orig 2021-12-14 11:47:56.645304805 +0100
 +++ .gitlab-ci.yml      2021-12-14 11:47:36.277406568 +0100
-@@ -5,3 +5,14 @@
+@@ -5,3 +5,16 @@
    - project: EOLE/infra/ci-tools
      ref: stable
      file: /templates/Rules.yaml
@@ -449,13 +483,15 @@ to:
 +    ref: stable
 +    file: /templates/Lint/Commitlint.yaml
 +
++
 +stages:
 +  - lint
 +
++
 +###############################################################################
 +# `lint` stage: `commitlint`
 +###############################################################################
-+# the `commitlint` is defined in `templates/Lint/Commitlint.yaml`
++# the `commitlint` is defined in `templates/Lint/Commitlint.yaml` included before
 ```
 
 #### Generate release with semantic version scheme
@@ -465,8 +501,7 @@ Before enabling the automatic release creation, you should enable [`commitlint`]
 To setup [`semantic-release`](https://github.com/semantic-release/),
 you need:
 
-1. the `.not-on-stable` rules template provided by the
-   [rules](#target-when-to-run-jobs) template
+1. the [rules](#target-when-to-run-jobs) template included
 2. include the
    [`templates/Release/Semantic-release.yaml`](templates/Release/Semantic-release.yaml)
 3. be sure to have the `release` stage to your current `stages` in your `.gitlab-ci.yml`
@@ -477,7 +512,7 @@ you need:
 ```diff
 --- .gitlab-ci.yml.orig 2021-12-14 11:51:49.984245841 +0100
 +++ .gitlab-ci.yml  2021-12-14 11:51:29.196333335 +0100
-@@ -8,11 +8,21 @@
+@@ -8,13 +8,27 @@
    - project: EOLE/infra/ci-tools
      ref: stable
      file: /templates/Lint/Commitlint.yaml
@@ -485,20 +520,27 @@ you need:
 +    ref: stable
 +    file: /templates/Release/Semantic-release.yaml
 
+
  stages:
    - lint
 +  - release
 
+
  ###############################################################################
  # `lint` stage: `commitlint`
  ###############################################################################
- # the `commitlint` is defined in `templates/Lint/Commitlint.yaml`
+ # the `commitlint` is defined in `templates/Lint/Commitlint.yaml` included before
 +
 +
 +###############################################################################
-+# `release` stage: `semantic-release`
++# `release` stage: `semantic-release`, `testing-prerelease`,
 +###############################################################################
 +# the `semantic-release` is defined in `templates/Release/Semantic-Release.yaml`
++
++# Create the prereleases versions on `$TESTING_BRANCH`
++testing-prerelease:
++  extends:
++    - .semantic-release:testing
 ```
 
 #### Build and tag docker images
@@ -519,8 +561,7 @@ does not require to enable docker-in-docker privileged mode.
 
 The simplest use of this template require 4 elements:
 
-1. the `.not-on-stable` rules template provided by the
-   [rules](#target-when-to-run-jobs) template
+1. the [rules](#target-when-to-run-jobs) template included
 2. include the [`templates/Docker.yaml`](templates/Docker.yaml) template
 3. be sure to have the `build` stage to your current `stages` in your `.gitlab-ci.yml`
 4. extends the `.build-docker-image` template to define the build job
@@ -528,7 +569,7 @@ The simplest use of this template require 4 elements:
 ```diff
 --- .gitlab-ci.yml.orig 2021-12-14 11:53:19.627880842 +0100
 +++ .gitlab-ci.yml  2021-12-14 11:54:50.483528896 +0100
-@@ -11,11 +11,19 @@
+@@ -11,12 +11,20 @@
    - project: EOLE/infra/ci-tools
      ref: stable
      file: /templates/Release/Semantic-release.yaml
@@ -536,6 +577,7 @@ The simplest use of this template require 4 elements:
 +    ref: stable
 +    file: /templates/Docker.yaml
 
+
  stages:
    - lint
 +  - build
@@ -545,24 +587,38 @@ The simplest use of this template require 4 elements:
 +  # Globally defined docker image name
 +  IMAGE_NAME: useless
 +
+
  ###############################################################################
  # `lint` stage: `commitlint`
- ###############################################################################
-@@ -23,6 +31,14 @@
+@@ -24,6 +32,28 @@
+ # the `commitlint` is defined in `templates/Lint/Commitlint.yaml` included before
 
 
- ###############################################################################
++###############################################################################
 +# `build` stage: `build-docker`
 +###############################################################################
 +# The name of the built image is define globally by `$IMAGE_NAME`
++# The build is done:
++# - for contribution branches
++# - for `$DEV_BRANCH`
++# - on release tags after the application versions are updated by `semantic-release`
 +build-docker:
 +  extends: .build-docker-image
++  rules:
++    # The ordering is CRITICAL
++    - !reference [.rules-map, not-on-schedule]
++    - !reference [.rules-map, not-on-draft]
++    - !reference [.rules-map, on-release-tag]
++    - !reference [.rules-map, on-testing-tag]
++    - !reference [.rules-map, not-on-stable]
++    - !reference [.rules-map, not-on-testing]
++    - !reference [.rules-map, not-on-semantic-release-commit]
++    - !reference [.rules-map, on-branch]
 +
 +
-+###############################################################################
- # `release` stage: `semantic-release`
  ###############################################################################
- # the `semantic-release` is defined in `templates/Release/Semantic-Release.yaml`
+ # `release` stage: `semantic-release`, `testing-prerelease`,
+ ###############################################################################
 ```
 
 ##### Tagging docker images
@@ -598,14 +654,19 @@ To be used, you need:
 ```diff
 --- .gitlab-ci.yml.orig 2021-12-14 11:58:55.434649075 +0100
 +++ .gitlab-ci.yml  2021-12-14 12:00:21.410358359 +0100
-@@ -39,6 +39,69 @@
+@@ -54,7 +54,7 @@
 
 
  ###############################################################################
--# `release` stage: `semantic-release`
-+# `release` stage: `semantic-release`, `tag *`
+-# `release` stage: `semantic-release`, `testing-prerelease`,
++# `release` stage: `semantic-release`, `testing-prerelease`, `tag *`
  ###############################################################################
  # the `semantic-release` is defined in `templates/Release/Semantic-Release.yaml`
+
+@@ -62,3 +62,60 @@
+ testing-prerelease:
+   extends:
+     - .semantic-release:testing
 +
 +## tag contribution branches with a more stable name than `git-${CI_COMMIT_SHORT_SHA}`
 +tag contrib branch:
@@ -628,24 +689,19 @@ To be used, you need:
 +tag testing:
 +  extends:
 +    - .tag-docker-image
-+    - .on-testing
++    # After `semantic-release`
++    - .on-testing-tag
 +  variables:
 +    IMAGE_TAG: testing
 +
 +## stable images
-+# we retag the latest `testing`
-+.tag-stable:
-+  extends: .tag-docker-image
-+  variables:
-+    SOURCE_TAG: "testing"
-+
 +# add the `X.Y.Z` tag
 +tag release:
-+  extends: .tag-stable
++  extends: .tag-docker-image
 +
 +# add the `X` tag
 +tag major:
-+  extends: .tag-stable
++  extends: .tag-docker-image
 +  before_script:
 +    - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
 +    - export RELEASE=${CI_COMMIT_TAG#${RELEASE_PREFIX}}
@@ -653,20 +709,19 @@ To be used, you need:
 +
 +# add the `X.Y` tag
 +tag minor:
-+  extends:
-+    - .tag-stable
++  extends: .tag-docker-image
 +  before_script:
 +    - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
 +    - export RELEASE=${CI_COMMIT_TAG#${RELEASE_PREFIX}}
 +    - export IMAGE_TAG=${RELEASE%.${RELEASE##*.}}
 +
 +tag stable:
-+  extends: .tag-stable
++  extends: .tag-docker-image
 +  variables:
 +    IMAGE_TAG: stable
 +
 +tag latest:
-+  extends: .tag-stable
++  extends: .tag-docker-image
 +  variables:
 +    IMAGE_TAG: latest
 ```
diff --git a/templates/Release/Semantic-release.yaml b/templates/Release/Semantic-release.yaml
index 643e734723615c6b4dad83a707ca4f848099da3a..87e8cf23c42bb1a0e47139357919144c86d04e0a 100644
--- a/templates/Release/Semantic-release.yaml
+++ b/templates/Release/Semantic-release.yaml
@@ -2,16 +2,28 @@
 # vim: ft=yaml
 ---
 # Produce a new release using semantic versionning scheme when new
-# commits arrive on the production branch.
+# commits arrive on the `$STABLE_BRANCH` branch.
+#
+# By default, a `semantic-release` job is created for `$STABLE_BRANCH`
+# and you can create jobs for `$TESTING_BRANCH` and `$DEV_BRANCH` by
+# extending the `.semantic-release:testing` and
+# `.semantic-release:dev` template jobs.
 #
 # USAGE
 # =====
 #
 # include:
+#   # stable semantic-release job is created by include
 #   - project: EOLE/infra/ci-tools
 #     ref: stable
 #     file: /templates/Release/Semantic-release.yaml
 #
+# testing-prerelease:
+#   extends: .semantic-release:testing
+#
+# dev-prerelease:
+#   extends: .semantic-release:dev
+#
 # REQUIREMENTS
 # ============
 #
@@ -51,6 +63,25 @@
 semantic-release:
   extends: .semantic-release:stable
 
+.semantic-release:stable:
+  stage: release
+  extends: .on-stable-with-semantic-release-config
+  image: "$SEMANTIC_RELEASE_IMAGE"
+  variables:
+    SEMANTIC_RELEASE_IMAGE: 'hub.eole.education/eole/semantic-release-gitlab:latest'
+  script:
+    - 'semantic-release'
+
+.semantic-release:testing:
+  extends:
+    - .semantic-release:stable
+    - .on-testing-with-semantic-release-config
+
+.semantic-release:dev:
+  extends:
+    - .semantic-release:stable
+    - .on-dev-with-semantic-release-config
+
 .on-stable-with-semantic-release-config:
   rules:
     - !reference [.rules-map, not-on-schedule]
@@ -95,13 +126,4 @@ semantic-release:
         - .releaserc.json
         - .releaserc.js
       when: on_success
-
-.semantic-release:stable:
-  stage: release
-  extends: .on-stable-with-semantic-release-config
-  image: "$SEMANTIC_RELEASE_IMAGE"
-  variables:
-    SEMANTIC_RELEASE_IMAGE: 'hub.eole.education/eole/semantic-release-gitlab:latest'
-  script:
-    - 'semantic-release'
 ...