diff --git a/preview.sh b/preview.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f3839420add25b9026acd9a98e36dc03d26799bc
--- /dev/null
+++ b/preview.sh
@@ -0,0 +1,451 @@
+#!/usr/bin/env bash
+# """Setup a temporary documentation folder to preview the rendering of the template
+#
+# SYNOPSIS:
+#   `./preview.sh [-c|--clean] [-r|--very-clean]`
+#
+# DESCRIPTION:
+#   This script will build the final list of folder that will be installed in
+#   the folder that will host the documenation and render a preview of such
+#   basic documentation based from template.
+#
+#   This will be done by creating symlinks from `templates` and `user_config`
+#   folders into `preview` folder.
+#
+#   Available options are:
+#
+#     * `-c,--clean`      : Remove every existing symlinks before rendering the
+#                           preview.
+#
+#     * `-r,--very-clean` : Remove every existing symlinks without rendering the
+#                           preview.
+#
+#     * `-h,--help`       : Print this help.
+#
+# """
+
+# Set constant variables
+MKDOCS_ROOT="${PWD}"
+MKDOCS_TMP="${MKDOCS_ROOT}/preview"
+MKDOCS_DEBUG_LEVEL="DEBUG"
+
+SCRIPT_PATH="$( cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 || return 1 ; pwd -P )"
+SCRIPT_FULL_PATH="${SCRIPT_PATH}/$(basename "${BASH_SOURCE[0]}")"
+
+main()
+{
+  # """Setup preview folder to be able to see the rendering of the documentation template.
+  #
+  # Build the list of the file that will be installed if using the mkdocs
+  # documentation template, make a symlinks of all these files into `preview`
+  # folder and, depending on the options provided, render the documentation
+  # preview.
+  #
+  # Globals:
+  #   UPGRADE
+  #   SUBREPO
+  #   REPO_URL
+  #   MKDOCS_ROOT
+  #   MKDOCS_TMP
+  #   MKDOCS_CLONE_ROOT
+  #
+  # Arguments:
+  #     * `-c,--clean`      : Remove every existing symlinks before rendering the preview.
+  #     * `-r,--very-clean` : Remove every existing symlinks without rendering the preview.
+  #     * `-h,--help`       : Print this help.
+  #
+  # Output:
+  #   Log informations
+  #
+  # Returns:
+  #   0, if rendering of the preview documentation went right.
+  #   1, if rendering of the preview documentation went wrong.
+  #
+  # """
+
+  manpage()
+  {
+    # """Extract the script documentation from header and print it on stdout.
+    #
+    # Simply extract the docstring from the header of the script, format it with
+    # some output enhancement (such as bold) and print it to stdout.
+    #
+    # Globals:
+    #   SCRIPT_FULL_PATH
+    #
+    # Arguments:
+    #   None
+    #
+    # Output:
+    #   Help to stdout
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    local e_normal="\\\e[0m"     # Normal (usually white fg & transparent bg)
+    local e_bold="\\\e[1m"       # Bold
+    # Extract module documentation and format it
+    help_content="$(\
+      sed -n -e "/^# \"\"\".*/,/^# \"\"\"/"p "${SCRIPT_FULL_PATH}" \
+        | sed -e "s/^# \"\"\"//g" \
+              -e "s/^# //g" \
+              -e "s/^#$//g" \
+              -e "s/DESCRIPTION[:]/${e_bold}DESCRIPTION${e_normal}\n/g" \
+              -e "s/COMMANDS[:]/${e_bold}COMMANDS${e_normal}\n/g" \
+              -e "s/OPTIONS[:]/${e_bold}OPTIONS${e_normal}\n/g" \
+              -e "s/SYNOPSIS[:]/${e_bold}SYNOPSIS${e_normal}\n/g")"
+    echo -e "${help_content}"
+    exit 0
+  }
+
+
+  #   - SC2034: var appears unused, Verify use (or export if used externally)
+  # shellcheck disable=SC2034
+  mkdocs_log()
+  {
+    # """Print debug message in colors depending on message severity on stderr.
+    #
+    # Echo colored log depending on user provided message severity. Message
+    # severity are associated to following color output:
+    #
+    #   - `DEBUG` print in the fifth colors of the terminal (usually magenta)
+    #   - `INFO` print in the second colors of the terminal (usually green)
+    #   - `WARNING` print in the third colors of the terminal (usually yellow)
+    #   - `ERROR` print in the third colors of the terminal (usually red)
+    #
+    # If no message severity is provided, severity will automatically be set to
+    # INFO.
+    #
+    # Globals:
+    #   ZSH_VERSION
+    #
+    # Arguments:
+    #   $1: string, message severity or message content
+    #   $@: string, message content
+    #
+    # Output:
+    #   Log informations colored
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    # Store color prefixes in variable to ease their use.
+    # Base on only 8 colors to ensure portability of color when in tty
+    local e_normal="\e[0m"     # Normal (usually white fg & transparent bg)
+    local e_bold="\e[1m"       # Bold
+    local e_underline="\e[4m"  # Underline
+    local e_debug="\e[0;35m"   # Fifth term color (usually magenta fg)
+    local e_info="\e[0;32m"    # Second term color (usually green fg)
+    local e_warning="\e[0;33m" # Third term color (usually yellow fg)
+    local e_error="\e[0;31m"   # First term color (usually red fg)
+
+    # Store preformated colored prefix for log message
+    local error="${e_bold}${e_error}[ERROR]${e_normal}${e_error}"
+    local warning="${e_bold}${e_warning}[WARNING]${e_normal}${e_warning}"
+    local info="${e_bold}${e_info}[INFO]${e_normal}${e_info}"
+    local debug="${e_bold}${e_debug}[DEBUG]${e_normal}${e_debug}"
+
+    local color_output="e_error"
+    local msg_severity
+    local msg
+
+    # Not using ${1^^} to ensure portability when using ZSH
+    msg_severity=$(echo "$1" | tr '[:upper:]' '[:lower:]')
+
+    if [[ "${msg_severity}" =~ ^(error|time|warning|info|debug)$ ]]
+    then
+      # Shift arguments by one such that $@ start from the second arguments
+      shift
+      # Place the content of variable which name is defined by ${msg_severity}
+      # For instance, if `msg_severity` is INFO, then `prefix` will have the same
+      # value as variable `info`.
+      if [[ -n "${ZSH_VERSION}" ]]
+      then
+        prefix="${(P)msg_severity}"
+      else
+        prefix="${!msg_severity}"
+      fi
+      color_output="e_${msg_severity}"
+    else
+      prefix="${info}"
+    fi
+
+    if [[ -n "${ZSH_VERSION}" ]]
+    then
+      color_output="${(P)color_output}"
+    else
+      color_output="${!color_output}"
+    fi
+
+    # Concat all remaining arguments in the message content and apply markdown
+    # like syntax.
+    msg_content=$(echo "$*" \
+      | sed -e "s/ \*\*/ \\${e_bold}/g" \
+            -e "s/\*\*\./\\${e_normal}\\${color_output}./g" \
+            -e "s/\*\* /\\${e_normal}\\${color_output} /g" \
+            -e "s/\*\*$/\\${e_normal}\\${color_output} /g" \
+            -e "s/ \_\_/ \\${e_underline}/g" \
+            -e "s/\_\_\./\\${e_normal}\\${color_output}./g" \
+            -e "s/\_\_ /\\${e_normal}\\${color_output} /g")
+    msg="${prefix} ${msg_content}${e_normal}"
+
+    # Print message or not depending on message severity and MKDOCS_DEBUG_LEVEL
+    if [[ -z "${MKDOCS_DEBUG_LEVEL}" ]] && [[ "${msg_severity}" == "error" ]]
+    then
+      echo -e "${msg}" 1>&2
+    elif [[ -n "${MKDOCS_DEBUG_LEVEL}" ]]
+    then
+      case ${MKDOCS_DEBUG_LEVEL} in
+        DEBUG)
+          echo "${msg_severity}" \
+            | grep -q -E "(debug|info|warning|error)" && echo -e "${msg}" 1>&2
+          ;;
+        INFO)
+          echo "${msg_severity}" \
+            | grep -q -E "(info|warning|error)" && echo -e "${msg}" 1>&2
+          ;;
+        WARNING)
+          echo "${msg_severity}" \
+            | grep -q -E "(warning|error)" && echo -e "${msg}" 1>&2
+          ;;
+        ERROR)
+          echo "${msg_severity}" \
+            | grep -q -E "error" && echo -e "${msg}" 1>&2
+          ;;
+      esac
+    fi
+  }
+
+  build_file_list()
+  {
+    # """Recursively build a list of file from provided folder
+    #
+    # Recursively build a list of file from provided folder and store such list
+    # in a temporary bash array that must be set in parent method.
+    #
+    # Globals:
+    #   None
+    #
+    # Arguments:
+    #   $1: string, absolute path to the folder which will be parsed
+    #
+    # Output:
+    #   None
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    local folder=$1
+    for i_node in "$folder"/* "$folder"/.*
+    do
+      if ! [[ "${i_node}" =~ ^${folder}\/[\.]+$ ]] \
+        && ! [[ "${i_node}" =~ __pycache__ ]]
+      then
+        if [[ -f "${i_node}" ]]
+        then
+          tmp_nodes+=("${i_node}")
+        elif [[ -d "${i_node}" ]]
+        then
+          build_file_list "${i_node}"
+        fi
+      fi
+    done
+  }
+
+
+  build_final_file_list()
+  {
+    # """Build the merged list from `templates` and `user_config` folder.
+    #
+    # If there is the same file in `user_config` and `templates` folder, then
+    # replace the file to be installed from `templates` by the one in
+    # `user_config`. Finally, add remaining `user_config` files not in
+    # `templates` to the list of files to install or upgrade in a bash array set
+    # in parent method.
+    #
+    # Globals:
+    #   MKDOCS_ROOT
+    #
+    # Arguments:
+    #   None
+    #
+    # Output:
+    #   None
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    for i_template_node in "${template_nodes[@]##*templates\/}"
+    do
+      found="false"
+      for i_user_node in "${user_nodes[@]##*user_config\/}"
+      do
+        if [[ ${i_template_node} =~ ^${i_user_node}$ ]]
+        then
+          found="true"
+        fi
+      done
+      if [[ "${found}" == "false" ]]
+      then
+        tmp_nodes+=("templates/${i_template_node}")
+      fi
+    done
+    for i_user_node in "${user_nodes[@]##*user_config\/}"
+    do
+      tmp_nodes+=("user_config/${i_user_node}")
+    done
+    tmp_nodes=("${tmp_nodes[@]##*${MKDOCS_ROOT}\/}")
+  }
+
+  clean_preview()
+  {
+    # """Recursively clean the preview folder by removing all symlinks
+    #
+    # Simply remove recursively all symlinks from folder `preview`.
+    #
+    # Globals:
+    #   MKDOCS_ROOT
+    #   MKDOCS_CLONE_ROOT
+    #
+    # Arguments:
+    #   None
+    #
+    # Output:
+    #   Log message
+    #
+    # Returns:
+    #   None
+    #
+    # """
+    local path=$1
+    if [[ -d "${path}" ]] && ! rmdir "${path}" &> /dev/null
+    then
+      mkdocs_log "INFO" "Cleaning **${path##*${MKDOCS_ROOT}\/}"
+      for i_node in "${path}"/*
+      do
+        if [[ -d "${i_node}" ]]
+        then
+          clean_preview "${i_node}"
+        elif [[ -L "${i_node}" ]]
+        then
+          rm "${i_node}"
+        fi
+      done
+      rmdir --ignore-fail-on-non-empty "${path}"
+    fi
+  }
+
+
+  setup_mkdocs()
+  {
+    # """Recursively install base folder and script to render a preview of the documentation template.
+    #
+    # Build the list of files and folders, recursively create a symlink of all
+    # files to their right location from the temporary clone repo to the folder
+    # `preview`.
+    #
+    # Globals:
+    #   MKDOCS_ROOT
+    #   MKDOCS_CLONE_ROOT
+    #
+    # Arguments:
+    #   None
+    #
+    # Output:
+    #   Log message
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    local tmp_nodes=()
+    local template_nodes=()
+    local user_nodes=()
+    local file_from
+    local dir
+    local i_node
+    local file_from
+    local file_to
+
+    mkdocs_log "INFO" "Building list of files"
+    build_file_list "${MKDOCS_ROOT}/templates"
+    template_nodes=("${tmp_nodes[@]}")
+    tmp_nodes=()
+    build_file_list "${MKDOCS_ROOT}/user_config"
+    user_nodes=("${tmp_nodes[@]}")
+    tmp_nodes=()
+
+    build_final_file_list
+
+    for i_node in "${tmp_nodes[@]}"
+    do
+      file_from="${MKDOCS_ROOT}/${i_node}"
+      file_to="${MKDOCS_TMP}/${i_node//user_config\/}"
+      file_to="${file_to//templates\/}"
+      if ! [[ -d "$(dirname "${file_to}")" ]]
+      then
+        dir=$(dirname "${file_to}")
+        mkdocs_log "INFO" "Create dir **${dir##*${MKDOCS_ROOT}\/}**."
+        mkdir -p "${dir}"
+      fi
+      if ! [[ "${file_to}" =~ \.gitkeep$ ]] && ! [[ "${file_to}" =~ \/mkdocs.local.yml ]]
+      then
+        if ! [[ -e "${file_to}" ]]
+        then
+          ln -s "${file_from}" "${file_to}"
+        fi
+      elif [[ "${file_to}" =~ \/mkdocs.local.yml ]]
+      then
+        mkdocs_log "INFO" "Updating ${file_to##*${MKDOCS_ROOT}\/}"
+        cat "${file_from}" > "${file_to}"
+        echo "  - Example: example.md" >> "${file_to}"
+      fi
+    done
+  }
+
+  # Parse arguments
+  while [[ $# -gt 0 ]]
+  do
+    case "$1" in
+      --clean|-c)
+        clean_preview "${MKDOCS_ROOT}/preview"
+        shift
+        ;;
+      --very-clean|-r)
+        clean_preview "${MKDOCS_ROOT}/preview"
+        return
+        ;;
+      --help|-h)
+        manpage
+        ;;
+    esac
+  done
+
+  # Set color prefix
+  local e_normal="\e[0m"      # normal (white fg & transparent bg)
+  local e_bold="\e[1m"        # bold
+  local e_warning="\e[0;33m"  # yellow fg
+  local e_error="\e[0;31m"    # red fg
+  local e_info="\e[0;32m"     # green fg
+
+  setup_mkdocs
+  cd "${MKDOCS_TMP}" || exit 1
+  mkdocs serve -f "${MKDOCS_TMP}/mkdocs.local.yml"
+  cd "${MKDOCS_ROOT}" || exit 1
+}
+
+main "${@}"
+
+# ------------------------------------------------------------------------------
+# VIM MODELINE
+# vim: ft=bash: foldmethod=indent
+# ------------------------------------------------------------------------------
\ No newline at end of file