diff --git a/static/scripts/table.js b/static/scripts/table.js
new file mode 100644
index 0000000..68179af
--- /dev/null
+++ b/static/scripts/table.js
@@ -0,0 +1,69 @@
+class BrickTable {
+    constructor(id, per_page, no_sort = [], number = []) {
+        const columns = [];
+
+        if (no_sort.length) {
+            columns.push({ select: no_sort, sortable: false, searchable: false });
+        }
+
+        if (number.length) {
+            columns.push({ select: number, type: "number", searchable: false });
+        }
+
+        this.table = new simpleDatatables.DataTable(`#${id}`, {
+            columns: columns,
+            pagerDelta: 1,
+            perPage: per_page,
+            perPageSelect: [10, 25, 50, 100, 500, 1000],
+            searchable: true,
+            searchMethod: (table => (terms, cell, row, column, source) => table.search(terms, cell, row, column, source))(this),
+            searchQuerySeparator: "",
+            tableRender: () => {
+              baguetteBox.run("[data-lightbox]");
+            },
+            pagerRender: () => {
+              baguetteBox.run("[data-lightbox]");
+            }
+        });
+    }
+
+    // Custom search method
+    // Very simplistic but will exclude pill links
+    search(terms, cell, row, column, source) {
+        // Create a searchable string from the data stack ignoring data-search="exclude"
+        const search = this.buildSearch(cell.data).filter(data => data != "").join(" ");
+
+        // Search it
+        for (const term of terms) {
+            if (search.includes(term)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    // Build the search string
+    buildSearch(dataList) {
+        let search = [];
+
+        for (const data of dataList) {
+            // Exclude
+            if (data.attributes && data.attributes['data-search'] && data.attributes['data-search'] == 'exclude') {
+                continue;
+            }
+
+            // Childnodes
+            if (data.childNodes) {
+                search = search.concat(this.buildSearch(data.childNodes));
+            }
+
+            // Data
+            if(data.data) {
+                search.push(data.data.trim().toLowerCase());
+            }
+        }
+
+        return search;
+    }
+}
diff --git a/templates/instructions.html b/templates/instructions.html
index 54bb4c0..7959796 100644
--- a/templates/instructions.html
+++ b/templates/instructions.html
@@ -22,4 +22,8 @@
       {% endwith %}
     </div>
   {% endif %}
+{% endblock %}
+
+{% block scripts %}
+<script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
 {% endblock %}
\ No newline at end of file
diff --git a/templates/instructions/table.html b/templates/instructions/table.html
index ba8f5f8..8f507aa 100644
--- a/templates/instructions/table.html
+++ b/templates/instructions/table.html
@@ -23,8 +23,8 @@
           {%- if item.allowed -%}
             </a>
           {% endif %}
-          <span class="badge rounded-pill text-bg-info fw-normal"><i class="ri-hard-drive-line"></i> {{ item.human_size() }}</span>
-          <span class="badge rounded-pill text-bg-light border fw-normal"><i class="ri-calendar-line"></i> {{ item.human_time() }}</span>
+          <span data-search="exclude" class="badge rounded-pill text-bg-info fw-normal"><i class="ri-hard-drive-line"></i> {{ item.human_size() }}</span>
+          <span data-search="exclude" class="badge rounded-pill text-bg-light border fw-normal"><i class="ri-calendar-line"></i> {{ item.human_time() }}</span>
         </td>
         <td>
           {% if item.set %}<span class="badge text-bg-secondary fw-normal"><i class="ri-hashtag"></i> {{ item.set }}</span>{% endif %}
@@ -47,5 +47,9 @@
   </table>
 </div>
 {% if all %}
-  {{ table.dynamic('instructions', no_sort='2,3')}}
+  <script type="text/javascript">
+    document.addEventListener("DOMContentLoaded", () => {
+      new BrickTable('instructions', {{ config['DEFAULT_TABLE_PER_PAGE'] }}, [2, 3]);
+    });
+  </script>
 {% endif %}
diff --git a/templates/macro/table.html b/templates/macro/table.html
index aa63eee..d4246f2 100644
--- a/templates/macro/table.html
+++ b/templates/macro/table.html
@@ -28,7 +28,7 @@
 {% macro bricklink(item) %}
   {% set url=item.url_for_bricklink() %}
   {% if url %}
-    <a href="{{ url }}" target="_blank" class="badge rounded-pill text-bg-light border fw-normal">
+    <a data-search="exclude" href="{{ url }}" target="_blank" class="badge rounded-pill text-bg-light border fw-normal">
       <i class="ri-external-link-line"></i> Bricklink
     </a>
   {% endif %}
@@ -45,32 +45,8 @@
 {% macro rebrickable(item) %}
   {% set url=item.url_for_rebrickable() %}
   {% if url %}
-    <a href="{{ url }}" target="_blank" class="badge rounded-pill text-bg-light border fw-normal">
+    <a data-search="exclude" href="{{ url }}" target="_blank" class="badge rounded-pill text-bg-light border fw-normal">
       <i class="ri-external-link-line"></i> Rebrickable
     </a>
   {% endif %}
 {% endmacro %}
-
-{% macro dynamic(id, no_sort=none, number=none) %}
-  <script type="text/javascript">
-    document.addEventListener("DOMContentLoaded", () => {
-      new simpleDatatables.DataTable("#{{ id }}", {
-        columns: [
-          {% if no_sort %}{ select: [{{ no_sort }}], sortable: false, searchable: false },{% endif %}
-          {% if number %}{ select: [{{ number }}], type: "number", searchable: false },{% endif %}
-        ],
-        pagerDelta: 1,
-        perPage: {{ config['DEFAULT_TABLE_PER_PAGE'] }},
-        perPageSelect: [10, 25, 50, 100, 500, 1000],
-        searchable: true,
-        searchQuerySeparator: "",
-        tableRender: () => {
-          baguetteBox.run('[data-lightbox]')
-        },
-        pagerRender: () => {
-          baguetteBox.run('[data-lightbox]')
-        }
-      });
-    });
-  </script>
-{% endmacro %}
\ No newline at end of file
diff --git a/templates/minifigure/table.html b/templates/minifigure/table.html
index 287d7c9..6315fec 100644
--- a/templates/minifigure/table.html
+++ b/templates/minifigure/table.html
@@ -22,5 +22,9 @@
   </table>
 </div>
 {% if all %}
-  {{ table.dynamic('minifigures', no_sort='0', number='2, 3, 4')}}
+  <script type="text/javascript">
+    document.addEventListener("DOMContentLoaded", () => {
+      new BrickTable('minifigures', {{ config['DEFAULT_TABLE_PER_PAGE'] }}, [0], [2, 3, 4]);
+    });
+  </script>
 {% endif %}
diff --git a/templates/minifigures.html b/templates/minifigures.html
index 5b42357..b28b600 100644
--- a/templates/minifigures.html
+++ b/templates/minifigures.html
@@ -8,4 +8,8 @@
     {% include 'minifigure/table.html' %}
   {% endwith %}
 </div>
+{% endblock %}
+
+{% block scripts %}
+<script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
 {% endblock %}
\ No newline at end of file
diff --git a/templates/missing.html b/templates/missing.html
index 659205b..de36f35 100644
--- a/templates/missing.html
+++ b/templates/missing.html
@@ -8,4 +8,8 @@
     {% include 'part/table.html' %}
   {% endwith %}
 </div>
+{% endblock %}
+
+{% block scripts %}
+<script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
 {% endblock %}
\ No newline at end of file
diff --git a/templates/part/table.html b/templates/part/table.html
index c47ca71..3603392 100644
--- a/templates/part/table.html
+++ b/templates/part/table.html
@@ -52,5 +52,9 @@
   </table>
 </div>
 {% if all %}
-  {{ table.dynamic('parts', no_sort='0', number='3, 4, 5, 6')}}
+  <script type="text/javascript">
+    document.addEventListener("DOMContentLoaded", () => {
+      new BrickTable('parts', {{ config['DEFAULT_TABLE_PER_PAGE'] }}, [0], [3, 4, 5, 6]);
+    });
+  </script>
 {% endif %}
\ No newline at end of file
diff --git a/templates/parts.html b/templates/parts.html
index 9ed411b..d2cb4b3 100644
--- a/templates/parts.html
+++ b/templates/parts.html
@@ -8,4 +8,8 @@
     {% include 'part/table.html' %}
   {% endwith %}
 </div>
+{% endblock %}
+
+{% block scripts %}
+<script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
 {% endblock %}
\ No newline at end of file
diff --git a/templates/wish/table.html b/templates/wish/table.html
index 03d7102..83536e3 100644
--- a/templates/wish/table.html
+++ b/templates/wish/table.html
@@ -41,5 +41,9 @@
   </table>
 </div>
 {% if all %}
-  {{ table.dynamic('wish', no_sort='0,7')}}
+  <script type="text/javascript">
+    document.addEventListener("DOMContentLoaded", () => {
+      new BrickTable('wish', {{ config['DEFAULT_TABLE_PER_PAGE'] }}, [0, 7]);
+    });
+  </script>
 {% endif %}
diff --git a/templates/wishes.html b/templates/wishes.html
index 1593a24..cc9a242 100644
--- a/templates/wishes.html
+++ b/templates/wishes.html
@@ -28,4 +28,8 @@
     {% include 'wish/table.html' %}
   {% endwith %}
 </div>
+{% endblock %}
+
+{% block scripts %}
+<script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
 {% endblock %}
\ No newline at end of file