diff --git a/layouts/shortcodes/readfile.html b/layouts/shortcodes/readfile.html
new file mode 100644
index 0000000000..f858502a40
--- /dev/null
+++ b/layouts/shortcodes/readfile.html
@@ -0,0 +1,36 @@
+{{/* Handle the "file" named parameter or a single unnamed parameter as the file
+path */}}
+{{ if .IsNamedParams }}
+ {{ $.Scratch.Set "fparameter" ( .Get "file" ) }}
+{{ else }}
+ {{ $.Scratch.Set "fparameter" ( .Get 0 ) }}
+{{ end }}
+
+
+{{/* If the first character is "/", the path is absolute from the site's
+`baseURL`. Otherwise, construct an absolute path using the current directory */}}
+
+{{ if eq (.Scratch.Get "fparameter" | printf "%.1s") "/" }}
+ {{ $.Scratch.Set "filepath" ($.Scratch.Get "fparameter") }}
+{{ else }}
+ {{ $.Scratch.Set "filepath" "/" }}
+ {{ $.Scratch.Add "filepath" $.Page.File.Dir }}
+ {{ $.Scratch.Add "filepath" ($.Scratch.Get "fparameter") }}
+{{ end }}
+
+
+{{/* If the file exists, read it and highlight it if it's code. Throw an error
+if the file is not found */}}
+
+{{ if fileExists ($.Scratch.Get "filepath") }}
+ {{ if eq (.Get "code") "true" }}
+ {{- highlight ($.Scratch.Get "filepath" | readFile | htmlUnescape |
+ safeHTML ) (.Get "lang") "" -}}
+ {{ else }}
+ {{- $.Scratch.Get "filepath" | readFile | htmlUnescape | safeHTML -}}
+ {{ end }}
+{{ else }}
+
+
The file {{ $.Scratch.Get "filepath" }}
was not found.
+
+{{ end }}
diff --git a/layouts/shortcodes/readfile.md b/layouts/shortcodes/readfile.md
deleted file mode 100644
index 117c7e8706..0000000000
--- a/layouts/shortcodes/readfile.md
+++ /dev/null
@@ -1,8 +0,0 @@
-{{$file := .Get "file"}}
-{{- if eq (.Get "markdown") "true" -}}
-{{- $file | readFile | markdownify -}}
-{{- else if (.Get "highlight") -}}
-{{- highlight ($file | readFile) (.Get "highlight") "" -}}
-{{- else -}}
-{{ $file | readFile | safeHTML }}
-{{- end -}}
diff --git a/userguide/content/en/docs/Adding content/Shortcodes/includes/config.yaml b/userguide/content/en/docs/Adding content/Shortcodes/includes/config.yaml
new file mode 100644
index 0000000000..e28cac21bf
--- /dev/null
+++ b/userguide/content/en/docs/Adding content/Shortcodes/includes/config.yaml
@@ -0,0 +1,11 @@
+apiVersion: tekton.dev/v1beta1
+kind: Task
+metadata:
+ name: hello
+spec:
+ steps:
+ - name: echo
+ image: alpine
+ script: |
+ #!/bin/sh
+ echo "Hello World"
diff --git a/userguide/content/en/docs/Adding content/Shortcodes/includes/installation.md b/userguide/content/en/docs/Adding content/Shortcodes/includes/installation.md
new file mode 100644
index 0000000000..da1c7edd61
--- /dev/null
+++ b/userguide/content/en/docs/Adding content/Shortcodes/includes/installation.md
@@ -0,0 +1,10 @@
+**Installation**
+
+1. Download the installation files.
+
+1. Run the installation script
+
+ `sudo sh install.sh`
+
+1. Test that your installation was successfully completed.
+
diff --git a/userguide/content/en/docs/Adding content/Shortcodes/index.md b/userguide/content/en/docs/Adding content/Shortcodes/index.md
index 3526aa5d7a..735e2a88f2 100644
--- a/userguide/content/en/docs/Adding content/Shortcodes/index.md
+++ b/userguide/content/en/docs/Adding content/Shortcodes/index.md
@@ -497,3 +497,107 @@ File[] hiddenFiles = new File("directory_name")
{{< /card-code >}}
{{< /cardpane >}}
+## Include external files
+
+Sometimes there's content that is relevant for several documents, or that is
+maintained in a file that is not necessarily a document. For situations like
+these, the `readfile` shortcode allows you to import the contents of an external
+file into a document.
+
+### Reuse documentation
+
+In case you want to reuse some content in several documents, you can write said
+content in a separate file and include it wherever you need it.
+
+For example, suppose you have a file called `installation.md` with the following
+contents:
+
+```go-html-template
+## Installation
+
+1. Download the installation files.
+
+1. Run the installation script
+
+ `sudo sh install.sh`
+
+1. Test that your installation was successfully completed.
+
+```
+
+You can import this section into another document:
+
+```go-html-template
+The following section explains how to install the database:
+
+{{%/* readfile "installation.md" */%}}
+
+```
+
+This will be rendered as if the instructions were in the parent document:
+
+---
+
+The following section explains how to install the database:
+
+{{% readfile "includes/installation.md" %}}
+
+---
+
+The parameter is the relative path to the file. Only relative paths
+under the parent file's working directory are supported.
+
+For files outside the current working directory you can use an absolute path
+starting with `/`. The root directory is the `/content` folder.
+
+### Include code files
+
+Suppose you have an `includes` folder containing several code samples you want
+to use as part of your documentation. You can use `readfile` with some
+additional parameters:
+
+```go-html-template
+To create a new pipeline, follow the next steps:
+
+1. Create a configuration file `config.yaml`:
+
+ {{* readfile file="includes/config.yaml" code="true" lang="yaml" */>}}
+
+1. Apply the file to your cluster `kubectl apply config.yaml`
+
+```
+
+This code automatically reads the content of `import/config.yaml` and inserts it
+into the document. The rendered text looks like this:
+
+---
+
+To create a new pipeline, follow the next steps:
+
+1. Create a configuration file `config.yaml`:
+
+ {{< readfile file="includes/config.yaml" code="true" lang="yaml" >}}
+
+1. Apply the file to your cluster `kubectl apply config.yaml`
+
+---
+
+{{% alert title="Warning" color="warning" %}}
+You must use `{{* */>}}` delimiters for the code highlighting to work
+correctly.
+{{% /alert %}}
+
+The "file" parameter is the relative path to the file. Only relative paths
+under the parent file's working directory are supported.
+
+For files outside the current working directory you can use an absolute path
+starting with `/`. The root directory is the `/content` folder.
+
+
+
+| Parameter | Default | Description |
+| ---------------- |------------| ------------|
+| file | | Path of external file|
+| code | false | Boolean value. If `true` the contents is treated as code|
+| lang | plain text | Programming language |
+