diff --git a/static/scripts/changer.js b/static/scripts/changer.js
index 31177d5e..224e24ba 100644
--- a/static/scripts/changer.js
+++ b/static/scripts/changer.js
@@ -115,13 +115,11 @@ class BrickChanger {
 }
 
 // Helper to setup the changer
-const setup_changers = () => {
-    document.querySelectorAll("*[data-changer-id]").forEach(el => {
-        new BrickChanger(
-            el.dataset.changerPrefix,
-            el.dataset.changerId,
-            el.dataset.changerUrl,
-            el.dataset.changerParent
-        );
-      });
-}
\ No newline at end of file
+const setup_changers = () => document.querySelectorAll("*[data-changer-id]").forEach(
+    el => new BrickChanger(
+        el.dataset.changerPrefix,
+        el.dataset.changerId,
+        el.dataset.changerUrl,
+        el.dataset.changerParent
+    )
+);
\ No newline at end of file
diff --git a/static/scripts/grid.js b/static/scripts/grid.js
index 62468175..42b8ac3b 100644
--- a/static/scripts/grid.js
+++ b/static/scripts/grid.js
@@ -50,15 +50,15 @@ class BrickGridSortButton {
 
 // Grid class
 class BrickGrid {
-    constructor(id) {
-        this.id = id;
+    constructor(grid) {
+        this.id = grid.id;
 
         // Grid elements (built based on the initial id)
-        this.html_grid = document.getElementById(id);
-        this.html_sort = document.getElementById(`${id}-sort`);
-        this.html_search = document.getElementById(`${id}-search`);
-        this.html_filter = document.getElementById(`${id}-filter`);
-        this.html_theme = document.getElementById(`${id}-theme`);
+        this.html_grid = document.getElementById(this.id);
+        this.html_sort = document.getElementById(`${this.id}-sort`);
+        this.html_search = document.getElementById(`${this.id}-search`);
+        this.html_filter = document.getElementById(`${this.id}-filter`);
+        this.html_theme = document.getElementById(`${this.id}-theme`);
 
         // Sort buttons
         this.html_sort_buttons = {};
@@ -251,3 +251,8 @@ class BrickGrid {
         }
     }
 }
+
+// Helper to setup the grids
+const setup_grids = () => document.querySelectorAll('*[data-grid="true"]').forEach(
+    el => new BrickGrid(el)
+);
diff --git a/static/scripts/table.js b/static/scripts/table.js
index 68179af2..669afc57 100644
--- a/static/scripts/table.js
+++ b/static/scripts/table.js
@@ -1,6 +1,19 @@
 class BrickTable {
-    constructor(id, per_page, no_sort = [], number = []) {
-        const columns = [];
+    constructor(table, per_page) {
+        const columns = []
+        const no_sort = [];
+        const number = [];
+
+        // Read the table header for parameters
+        table.querySelectorAll('th').forEach((th, index) => {
+            if (th.dataset.tableNoSort) {
+                no_sort.push(index);
+            }
+
+            if (th.dataset.tableNumber) {
+                number.push(index);
+            }
+        });
 
         if (no_sort.length) {
             columns.push({ select: no_sort, sortable: false, searchable: false });
@@ -10,7 +23,7 @@ class BrickTable {
             columns.push({ select: number, type: "number", searchable: false });
         }
 
-        this.table = new simpleDatatables.DataTable(`#${id}`, {
+        this.table = new simpleDatatables.DataTable(`#${table.id}`, {
             columns: columns,
             pagerDelta: 1,
             perPage: per_page,
@@ -67,3 +80,8 @@ class BrickTable {
         return search;
     }
 }
+
+// Helper to setup the tables
+const setup_tables = (per_page) => document.querySelectorAll('table[data-table="true"]').forEach(
+    el => new BrickTable(el, per_page)
+);
diff --git a/templates/add.html b/templates/add.html
index 8fff6185..140eec62 100644
--- a/templates/add.html
+++ b/templates/add.html
@@ -70,7 +70,3 @@
 </div>
 {% include 'set/socket.html' %}
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/socket.js') }}"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/admin.html b/templates/admin.html
index 860d99f9..dc872566 100644
--- a/templates/admin.html
+++ b/templates/admin.html
@@ -42,7 +42,3 @@
   </div>
 </div>
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/changer.js') }}"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/admin/checkbox.html b/templates/admin/checkbox.html
index 7cbd59d5..b71cc2a6 100644
--- a/templates/admin/checkbox.html
+++ b/templates/admin/checkbox.html
@@ -60,8 +60,3 @@
   </li>
 </ul>
 {{ accordion.footer() }}
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    setup_changers();
-  });
-</script>
diff --git a/templates/base.html b/templates/base.html
index 23badab3..1132f2be 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -78,11 +78,25 @@
     <script src="https://cdnjs.cloudflare.com/ajax/libs/baguettebox.js/1.12.0/baguetteBox.min.js" integrity="sha512-HzIuiABxntLbBS8ClRa7drXZI3cqvkAZ5DD0JCAkmRwUtykSGqzA9uItHivDhRUYnW3MMyY5xqk7qVUHOEMbMA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.8.1/socket.io.min.js" integrity="sha512-8ExARjWWkIllMlNzVg7JKq9RKWPlJABQUNq6YvAjE/HobctjH/NA+bSiDMDvouBVjp4Wwnf1VP1OEv7Zgjtuxw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
     <script src="https://cdn.jsdelivr.net/npm/simple-datatables@9.2.1/dist/umd/simple-datatables.min.js"></script>
+    <!-- BrickTracker scripts -->
+    <script src="{{ url_for('static', filename='scripts/changer.js') }}"></script>
+    <script src="{{ url_for('static', filename='scripts/grid.js') }}"></script>
+    <script src="{{ url_for('static', filename='scripts/set.js') }}"></script>
+    <script src="{{ url_for('static', filename='scripts/socket.js') }}"></script>
+    <script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
+    <script type="text/javascript">
+      document.addEventListener("DOMContentLoaded", () => {
+        setup_grids();
+        setup_changers();
+        setup_tables({{ config['DEFAULT_TABLE_PER_PAGE'] }});
+        baguetteBox.run('[data-lightbox]');
+      });
+    </script>
+
     <!-- Bootstrap tooltips -->
     <script type="text/javascript">
       const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
       const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
     </script>
-    {% block scripts %}{% endblock %}
   </body>
 </html>
\ No newline at end of file
diff --git a/templates/bulk.html b/templates/bulk.html
index 1974e1b0..6e6e5d8a 100644
--- a/templates/bulk.html
+++ b/templates/bulk.html
@@ -62,7 +62,3 @@
   {% include 'set/socket.html' %}
 {% endwith %}
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/socket.js') }}"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/delete.html b/templates/delete.html
index d61821aa..07c2b082 100644
--- a/templates/delete.html
+++ b/templates/delete.html
@@ -12,13 +12,4 @@
     </div>
   </div>
 </div>
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    baguetteBox.run('[data-lightbox]');
-  });
-</script>
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/set.js') }}"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/instructions.html b/templates/instructions.html
index 79597968..70cd1eb0 100644
--- a/templates/instructions.html
+++ b/templates/instructions.html
@@ -23,7 +23,3 @@
     </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/delete.html b/templates/instructions/delete.html
index 9443dd07..247e7032 100644
--- a/templates/instructions/delete.html
+++ b/templates/instructions/delete.html
@@ -28,8 +28,3 @@
     <div class="card-footer"></div>
   </div>
 </div>
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    baguetteBox.run('[data-lightbox]');
-  });
-</script>
diff --git a/templates/instructions/rename.html b/templates/instructions/rename.html
index 0be3dbe3..a3269c16 100644
--- a/templates/instructions/rename.html
+++ b/templates/instructions/rename.html
@@ -34,8 +34,3 @@
     <div class="card-footer"></div>
   </div>
 </div>
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    baguetteBox.run('[data-lightbox]');
-  });
-</script>
diff --git a/templates/instructions/table.html b/templates/instructions/table.html
index 8f507aa7..8ad9f3cf 100644
--- a/templates/instructions/table.html
+++ b/templates/instructions/table.html
@@ -1,14 +1,14 @@
 {% import 'macro/table.html' as table %}
 
 <div class="table-responsive-sm">
-  <table class="table table-striped align-middle" id="instructions">
+  <table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle" id="instructions">
     <thead>
       <tr>
         <th scope="col"><i class="ri-file-line fw-normal"></i> Filename</th>
         <th scope="col"><i class="ri-hashtag fw-normal"></i> Set</th>
-        <th class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
+        <th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
         {% if g.login.is_authenticated() %}
-          <th class="no-sort" scope="col"><i class="ri-settings-4-line fw-normal"></i> Actions</th>
+          <th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-settings-4-line fw-normal"></i> Actions</th>
         {% endif %}
         </tr>
     </thead>
@@ -46,10 +46,3 @@
     </tbody>
   </table>
 </div>
-{% if all %}
-  <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 d4246f2a..91bb1c92 100644
--- a/templates/macro/table.html
+++ b/templates/macro/table.html
@@ -1,25 +1,25 @@
 {% macro header(color=false, quantity=false, missing=false, missing_parts=false, sets=false, minifigures=false) %}
   <thead>
     <tr>
-      <th class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
+      <th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
       <th scope="col"><i class="ri-pencil-line fw-normal"></i> Name</th>
       {% if color %}
         <th scope="col"><i class="ri-palette-line fw-normal"></i> Color</th>
       {% endif %}
       {% if quantity %}
-        <th scope="col"><i class="ri-functions fw-normal"></i> Quantity</th>
+        <th data-table-number="true" scope="col"><i class="ri-functions fw-normal"></i> Quantity</th>
       {% endif %}
       {% if missing %}
-        <th scope="col"><i class="ri-error-warning-line fw-normal"></i> Missing</th>
+        <th data-table-number="true" scope="col"><i class="ri-error-warning-line fw-normal"></i> Missing</th>
       {% endif %}
       {% if missing_parts %}
-        <th scope="col"><i class="ri-error-warning-line fw-normal"></i> Missing parts</th>
+        <th data-table-number="true" scope="col"><i class="ri-error-warning-line fw-normal"></i> Missing parts</th>
       {% endif %}
       {% if sets %}
-        <th scope="col"><i class="ri-hashtag fw-normal"></i> Sets</th>
+        <th data-table-number="true" scope="col"><i class="ri-hashtag fw-normal"></i> Sets</th>
       {% endif %}
       {% if minifigures %}
-        <th scope="col"><i class="ri-group-line fw-normal"></i> Minifigures</th>
+        <th data-table-number="true" scope="col"><i class="ri-group-line fw-normal"></i> Minifigures</th>
       {% endif %}
     </tr>
   </thead>
diff --git a/templates/minifigure.html b/templates/minifigure.html
index 3359897b..52ed7a1a 100644
--- a/templates/minifigure.html
+++ b/templates/minifigure.html
@@ -12,9 +12,4 @@
     </div>
   </div>
 </div>
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    baguetteBox.run('[data-lightbox]');
-  });
-</script>
 {% endblock %}
diff --git a/templates/minifigure/table.html b/templates/minifigure/table.html
index 6315fecf..94ccef75 100644
--- a/templates/minifigure/table.html
+++ b/templates/minifigure/table.html
@@ -1,7 +1,7 @@
 {% import 'macro/table.html' as table %}
 
 <div class="table-responsive-sm">
-  <table class="table table-striped align-middle" id="minifigures">
+  <table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle" id="minifigures">
     {{ table.header(quantity=true, missing_parts=true, sets=true) }}
     <tbody>
       {% for item in table_collection %}
@@ -21,10 +21,3 @@
     </tbody>
   </table>
 </div>
-{% if all %}
-  <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 b28b600d..ce42f18d 100644
--- a/templates/minifigures.html
+++ b/templates/minifigures.html
@@ -9,7 +9,3 @@
   {% 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 de36f351..d7c82a54 100644
--- a/templates/missing.html
+++ b/templates/missing.html
@@ -9,7 +9,3 @@
   {% 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.html b/templates/part.html
index 969b676b..40899d9c 100644
--- a/templates/part.html
+++ b/templates/part.html
@@ -12,9 +12,4 @@
     </div>
   </div>
 </div>
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    baguetteBox.run('[data-lightbox]');
-  });
-</script>
 {% endblock %}
diff --git a/templates/part/table.html b/templates/part/table.html
index 3603392e..1fca2648 100644
--- a/templates/part/table.html
+++ b/templates/part/table.html
@@ -1,7 +1,7 @@
 {% import 'macro/table.html' as table %}
 
 <div class="table-responsive-sm">
-  <table class="table table-striped align-middle {% if not all %}sortable mb-0{% endif %}" {% if all %}id="parts"{% endif %}>
+  <table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle {% if not all %}sortable mb-0{% endif %}" {% if all %}id="parts"{% endif %}>
     {{ table.header(color=true, quantity=not no_quantity, missing=not no_missing, sets=all, minifigures=all) }}
     <tbody>
       {% for item in table_collection %}
@@ -51,10 +51,3 @@
     </tbody>
   </table>
 </div>
-{% if all %}
-  <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 d2cb4b33..1c3e417b 100644
--- a/templates/parts.html
+++ b/templates/parts.html
@@ -9,7 +9,3 @@
   {% 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/set.html b/templates/set.html
index d5eeef92..69ba6dd1 100644
--- a/templates/set.html
+++ b/templates/set.html
@@ -12,15 +12,4 @@
     </div>
   </div>
 </div>
-<script type="text/javascript">
-  document.addEventListener("DOMContentLoaded", () => {
-    baguetteBox.run('[data-lightbox]');
-    setup_changers();
-  });
-</script>
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/changer.js') }}"></script>
-<script src="{{ url_for('static', filename='scripts/set.js') }}"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/sets.html b/templates/sets.html
index 2517c964..ea08c2d5 100644
--- a/templates/sets.html
+++ b/templates/sets.html
@@ -58,7 +58,7 @@
     </div>
   </div>
 
-  <div class="row" id="grid">
+  <div class="row" data-grid="true" id="grid">
   {% for item in collection %}
     <div class="col-md-6 col-xl-3 d-flex align-items-stretch">
       {% with index=loop.index0 %}
@@ -67,19 +67,8 @@
     </div>
   {% endfor %}
   </div>
-  <script type="text/javascript">
-    document.addEventListener("DOMContentLoaded", () => {
-      new BrickGrid("grid");
-      setup_changers();
-    });
-  </script>
 </div>
 {% else %}
   {% include 'set/empty.html' %}
 {% endif %}
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/grid.js') }}"></script>
-<script src="{{ url_for('static', filename='scripts/changer.js') }}"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/wish/table.html b/templates/wish/table.html
index 83536e3d..73a5eb89 100644
--- a/templates/wish/table.html
+++ b/templates/wish/table.html
@@ -2,10 +2,10 @@
 {% import 'macro/badge.html' as badge %}
 
 <div class="table-responsive-sm">
-  <table class="table table-striped align-middle" id="wish">
+  <table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle" id="wish">
     <thead>
       <tr>
-        <th class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
+        <th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
         <th scope="col"><i class="ri-hashtag fw-normal"></i> Set</th>
         <th scope="col"><i class="ri-pencil-line fw-normal"></i> Name</th>
         <th scope="col"><i class="price-tag-3-line fw-normal"></i> Theme</th>
@@ -13,7 +13,7 @@
         <th scope="col"><i class="ri-shapes-line fw-normal"></i> Parts</th>
         <th scope="col"><i class="ri-calendar-close-line fw-normal"></i> Retirement</th>
         {% if g.login.is_authenticated() %}
-          <th class="no-sort" scope="col"><i class="ri-settings-4-line fw-normal"></i> Actions</th>
+          <th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-settings-4-line fw-normal"></i> Actions</th>
         {% endif %}
         </tr>
     </thead>
@@ -40,10 +40,3 @@
     </tbody>
   </table>
 </div>
-{% if all %}
-  <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 cc9a242f..eac8255f 100644
--- a/templates/wishes.html
+++ b/templates/wishes.html
@@ -29,7 +29,3 @@
   {% endwith %}
 </div>
 {% endblock %}
-
-{% block scripts %}
-<script src="{{ url_for('static', filename='scripts/table.js') }}"></script>
-{% endblock %}
\ No newline at end of file