diff --git a/.ci/build_indices.sh b/.ci/build_indices.sh
new file mode 100644
index 0000000000000000000000000000000000000000..ea563f40feb28c4e551695e2621ae4a39aea9017
--- /dev/null
+++ b/.ci/build_indices.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+DIRECTORY=build
+
+# Install lunr to build the index
+npm install lunr@2.3.8
+
+# Go to the directory...
+cd $DIRECTORY
+
+printf "Found the following build targets inside: \n$(ls -d */)\n\n"
+
+# ...and loop through all the build targets
+for branch in $(ls -d */); do
+    echo "Entering: $branch";
+
+    cd "$branch";
+
+    echo "Generating the index..."    
+    cat documents.js | node $CI_PROJECT_DIR/build_index.js > index.js
+    rm documents.js build_index.js
+
+    echo "...should be completed. First 50 characters of the index: "
+    cat index.js | head -c50
+    echo ""
+
+    cd ..
+    
+done
+
+rm $CI_PROJECT_DIR/build_index.js
diff --git a/.ci/deploy.sh b/.ci/deploy.sh
index 84ab84e9a0ed5f968790fbce1f9a90cb1c3251a5..d6f5cceb7ad6b0dc94884c6f71ceda2aeff5dc9e 100644
--- a/.ci/deploy.sh
+++ b/.ci/deploy.sh
@@ -1,4 +1,4 @@
-mkdir -p public
+mkdir -p build
 artefact="latest"
 
 # loop through all the branches
@@ -14,14 +14,15 @@ for branch in $(git for-each-ref --format='%(refname:strip=3)' refs/remotes); do
     echo $artefact;
     git checkout -f $branch
     git reset --hard $branch
+    git pull
 
     # build the website
     bundle install
-    bundle exec jekyll build --baseurl="howto-cards/$artefact" -d "public/$artefact"
+    bundle exec jekyll build --baseurl="howto-cards/$artefact" -d "build/$artefact"
 
     if [[ $branch == "master" ]]; then
         # set the 404
-        cp howto-cards/$artefact/404.html public/404.html
+        cp howto-cards/$artefact/404.html build/404.html
     fi
 done
 
@@ -31,4 +32,4 @@ git checkout -f $CI_COMMIT_REF_NAME
 git reset --hard origin/$CI_COMMIT_REF_NAME
 
 # set the auto redirection
-cp .ci/.autoRedirect public/index.html
+cp .ci/.autoRedirect build/index.html
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f7e6360d8eb7c15052c6dffc8eb5f5ef76ccfc44..b3e0ff1c39f89bab1519e86f9bf3e333bd824844 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,22 +1,52 @@
 # In case something goes horribly wrong, you can fall back to `image: ruby:2.5`
 image: git-r3lab.uni.lu:4567/r3/docker/jekyll-lcsb:1.1
 
-variables:
-  JEKYLL_ENV: production
+stages:
+  - build
+  - generate_index
+  - deploy
+
+build_pages:
+  stage: build
+  before_script:
+    - apt-get -qq update
+    - apt-get install -y -qq git-lfs
+    - gem install bundler:2.0.2 && bundle install  
+  script:
+    - bash .ci/deploy.sh
+  variables:
+    JEKYLL_ENV: production
+  artifacts:
+    expire_in: 1 day
+    paths:
+      - build
 
-before_script:
-  - apt-get -qq update
-  - apt-get install -y -qq git-lfs
-  - gem install bundler:2.0.2 && bundle install
+
+generate the search index:
+  stage: generate_index
+  image: node:13.8.0-slim
+  rules:
+    - if: $CI_COMMIT_BRANCH == "master"
+    - if: $CI_COMMIT_BRANCH == "develop"
+  script:
+    - bash .ci/build_indices.sh
+    - mv build processed_build
+  artifacts:
+    expire_in: 1 day
+    paths:
+      - processed_build
 
 pages:
+  image: alpine:3.11.3
   stage: deploy
   rules:
     - if: $CI_COMMIT_BRANCH == "master"
     - if: $CI_COMMIT_BRANCH == "develop"
   script:
-    - bash .ci/deploy.sh
-
+    - mv processed_build public
+  rules:
+    - if: $CI_COMMIT_BRANCH == "master"
+    - if: $CI_COMMIT_BRANCH == "develop"
   artifacts:
     expire_in: 1 week
     paths:
diff --git a/_config.yml b/_config.yml
index 5e2991f53350af4605cbd0a7147420b779412c59..5aac579f64493c33be53e1e916ad451160d8fa05 100644
--- a/_config.yml
+++ b/_config.yml
@@ -66,6 +66,7 @@ defaults:
       path: "external/*"
     values:
       include_link: true
+      searchable: 1.0 
 
 
 # Exclude from processing. (no need to touch these)
diff --git a/build_index.js b/build_index.js
new file mode 100644
index 0000000000000000000000000000000000000000..eeb6c44f9809fc4f005bc8fa5afdeefea4f3b9dc
--- /dev/null
+++ b/build_index.js
@@ -0,0 +1,28 @@
+var lunr = require('lunr'),
+    stdin = process.stdin,
+    stdout = process.stdout,
+    buffer = [];
+
+stdin.resume();
+stdin.setEncoding('utf8');
+
+stdin.on('data', function (data) {
+  buffer.push(data);
+});
+
+stdin.on('end', function () {
+  var documents = JSON.parse(buffer.join(''))
+
+  var idx = lunr(function () {
+    this.ref('id')
+    this.field('title', { boost: 10 })
+    this.field('url')
+    this.field('content')
+
+    documents.forEach(function (doc) {
+      this.add(doc)
+    }, this)
+  })
+
+  stdout.write(JSON.stringify(idx))
+});
diff --git a/documents.js b/documents.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d641bc2d4c23487dba72fb9ff938ae2d430ad92
--- /dev/null
+++ b/documents.js
@@ -0,0 +1,12 @@
+---
+---
+
+{% assign the_cards = site.pages | where_exp:"card","card.searchable >= 1.0" %}
+
+[ {% for card in the_cards %} {
+            "id": "{{ card.url | slugify }}",
+            "title": "{{ card.shortcut | xml_escape }}",
+            "content": {{ card.content | markdownify | strip_html | jsonify }},
+            "url": "{{ card.url | xml_escape | relative_url }}"
+        } {% unless forloop.last %},{% endunless %} {% endfor %}
+]
diff --git a/external/contribute/markdown/markdown.md b/external/contribute/markdown/markdown.md
index 7c64eb2f8a59c8ebd998e7685e300165aabfabad..b8d26dc5c4fcb2ac4d37b10ba371f619564bb2ab 100644
--- a/external/contribute/markdown/markdown.md
+++ b/external/contribute/markdown/markdown.md
@@ -34,7 +34,7 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
 
 
 ## Tips to write in markdown:
-<table>
+<table style="table-layout: fixed; width: 95%;white-space: normal">
   <thead>
   <tr>
     <th>Markdown</th>
@@ -44,7 +44,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   <tbody>
   <tr>
     <td>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
         # Header 1<br>
         ## Header 2<br>
         ### Header 3 <br>
@@ -60,7 +61,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   </tr>
   <tr>
     <td>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       To make a text **bold**, use **double asterisk** or __underscores__ before and after a word or phrase.
       To make a text **italic**, use *one asterisk* or _underscore_.
       </pre>
@@ -72,7 +74,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   </tr>
   <tr>
     <td>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       Use numbers for ordered lists:
         1. First item
         2. Second item
@@ -99,7 +102,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   </tr>
   <tr>
     <td>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       For unordered lists use asterisk, minus or plus
         - First item
         - Second item
@@ -125,7 +129,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   </tr>
   <tr>
     <td>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       Include links referring to a web [page](https://www.markdownguide.org/)
       </pre>
     </td>
@@ -136,15 +141,17 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   <tr>
     <td>
      
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
        Include local pictures using markdown:
 
         ![My awesome picture](img/r3_logo.png)
       </pre><br>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       Or use HTML tag allowing you to alter the image properties (e.g. size):
 
-        &lt;img src="img/r3_logo.png" width="40"&gt
+        &lt;img src="img/r3_logo.png" width="40"&gt;
       </pre>
     </td>
     <td>
@@ -156,7 +163,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   </tr>
   <tr>
     <td>
-     <pre>
+     <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       Include code blocks!
       ```
       def myAwesomeFunction(x):
@@ -176,7 +184,8 @@ Markdown is a lightweight markup language with plain text formatting syntax whic
   </tr>
   <tr>
     <td>
-      <pre>
+      <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
       Create table:
        |   Tables   |   Are  | Cool  |
        |------------|:------:|:-----:|
@@ -272,7 +281,8 @@ Another big advantage of Markdown is that it can contain HTML tags, which makes
   <tbody>
     <tr>
       <td>
-        <pre>
+        <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word">
+
           # DocTitle
           ### Attendees:
           ### Location:
diff --git a/search.md b/search.md
new file mode 100644
index 0000000000000000000000000000000000000000..516507a781354405ae1f56c3f19de90d4ceb3481
--- /dev/null
+++ b/search.md
@@ -0,0 +1,135 @@
+---
+layout: page
+title: Search
+permalink: /search
+order: 4
+---
+
+<link rel="prefetch" href="index.js" />
+
+<style>
+    #search_query {
+        border: solid 2px #eee; 
+        padding: 8px; 
+        height: 20px; 
+        font-size: 20px; 
+        width: 500px; 
+        min-width: 400px;
+    }
+
+    button.search[type=submit] {
+        border: solid 2px #eee; 
+        padding: 1px; 
+        height: 35px; 
+        width: 150px; 
+        font-size: 20px; 
+        color: #4c4c4c; 
+        background: #efefef; 
+        border-radius: 8px;
+        margin-top: 3px;
+    }
+
+    #search_header {
+        margin-top: 50px; 
+        display: none
+    }
+
+    #search_results_table {
+        margin-top: 20px; 
+        width: 100%;
+    }
+
+     #search_results_placeholder_td {
+        border: none;
+     }
+
+    h3.result {
+        font-size: large;
+    }
+</style>
+
+<form>
+    <input class="search" placeholder="What are you looking for?" name="search_query" id="search_query" /><br />
+    <button class="search" type="submit">Find it</button>
+</form>
+
+<h1 id="search_header">Results of your query:</h1>
+
+<table id="search_results_table">
+    <tbody id="search_results_tbody">
+        <tr id="search_results_placeholder" style="display: none">
+            <td id="search_results_placeholder_td"><h3>Please wait, search is in progress...</h3></td>
+        </tr>
+    </tbody>
+</table>
+
+<script src="https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.8/lunr.min.js" integrity="sha256-34Si1Y6llMBKM3G0jQILVeoQKEwuxjbk4zGWXXMT4ps=" crossorigin="anonymous"></script>
+
+<script>
+    var el_table_body = document.getElementById('search_results_tbody');
+    var el_input_query = document.getElementById('search_query');
+    var el_tr_placeholder = document.getElementById('search_results_placeholder');
+    var el_header = document.getElementById('search_header');
+
+    var url_params = new URLSearchParams(window.location.search);
+    var search_term = url_params.get('search_query') || "";
+
+    if (!!search_term.length) {
+        el_input_query.value = search_term;
+        el_header.style.display = "block";
+
+        el_tr_placeholder.style.display = "block";
+    }
+
+    var construct_cell = function(title, content, link) {
+        if (link == '#') {
+            return '<td><h3 class="result">' + title + '</h3><p>' + content + '</p></td>';
+        } else {
+            return '<td><h3><a href="' + link + '">' + title + '</a></h3><p>' + content + '</p></td>';
+        }
+    }
+
+    var capitalize = function(text) {
+        return text.charAt(0).toUpperCase() + text.slice(1);
+    }
+
+    var prettify = function(text) {
+        return text.split(':').map(capitalize).join(' &raquo; ');
+    }
+
+    {% assign the_cards = site.pages | where_exp:"card","card.searchable >= 1.0" %}
+
+    window.content = { {% for card in the_cards %} 
+        "{{ card.url | slugify }}": {
+            "title": "{{ card.shortcut | xml_escape }}",
+            "content": {{ card.content | strip_html | strip_newlines | jsonify }},
+            "url": "{{ card.url | xml_escape | relative_url }}"
+        } {% unless forloop.last %},{% endunless %} {% endfor %}
+    };
+
+    fetch('{{ "index.js" | relative_url }}').then(response => response.text()).then((data) => {
+        var the_index = JSON.parse(data);
+        window.search_index = lunr.Index.load(the_index);
+
+        if (search_term != "") {
+            var results = window.search_index.search(search_term);
+            for (var i = 0; i < results.length; i++) {
+                var node = document.createElement("tr");
+                node.innerHTML = construct_cell(prettify(window.content[results[i].ref].title), 
+                                                window.content[results[i].ref].content.substring(0, 125) + '...',
+                                                window.content[results[i].ref].url);
+                el_table_body.appendChild(node);
+            }
+            if (results.length == 0) {
+                var node = document.createElement("tr");
+                node.innerHTML = construct_cell("No results", 
+                                                'Sorry, we were unable to find anything that matches your query',
+                                                "#");
+                el_table_body.appendChild(node);
+            }
+        }
+
+        el_tr_placeholder.style.display = "none";
+    })
+
+</script>