diff --git a/bricktracker/metadata_list.py b/bricktracker/metadata_list.py
new file mode 100644
index 0000000..80bb3df
--- /dev/null
+++ b/bricktracker/metadata_list.py
@@ -0,0 +1,77 @@
+import logging
+from typing import Type
+
+from .exceptions import NotFoundException
+from .fields import BrickRecordFields
+from .record_list import BrickRecordList
+from .set_status import BrickSetStatus
+
+logger = logging.getLogger(__name__)
+
+T = BrickSetStatus
+
+
+# Lego sets metadata list
+class BrickMetadataList(BrickRecordList[T]):
+    kind: str
+    mapping: dict[str, T]
+    model: Type[T]
+
+    # Database table
+    table: str
+
+    # Queries
+    select_query: str
+
+    def __init__(self, model: Type[T], /, *, force: bool = False):
+        # Load statuses only if there is none already loaded
+        records = getattr(self, 'records', None)
+
+        if records is None or force:
+            # Don't use super()__init__ as it would mask class variables
+            self.fields = BrickRecordFields()
+
+            logger.info('Loading {kind} list'.format(
+                kind=self.kind
+            ))
+
+            self.__class__.records = []
+            self.__class__.mapping = {}
+
+            # Load the statuses from the database
+            for record in self.select():
+                status = model(record=record)
+
+                self.__class__.records.append(status)
+                self.__class__.mapping[status.fields.id] = status
+
+    # Return the items as columns for a select
+    def as_columns(self, /, **kwargs) -> str:
+        return ', '.join([
+            '"{table}"."{column}"'.format(
+                table=self.table,
+                column=record.as_column(),
+            )
+            for record
+            in self.filter(**kwargs)
+        ])
+
+    # Filter the list of records (this one does nothing)
+    def filter(self) -> list[T]:
+        return self.records
+
+    # Grab a specific status
+    def get(self, id: str, /) -> T:
+        if id not in self.mapping:
+            raise NotFoundException(
+                '{kind} with ID {id} was not found in the database'.format(
+                    kind=self.kind.capitalize(),
+                    id=id,
+                ),
+            )
+
+        return self.mapping[id]
+
+    # Get the list of statuses depending on the context
+    def list(self, /, **kwargs) -> list[T]:
+        return self.filter(**kwargs)
diff --git a/bricktracker/reload.py b/bricktracker/reload.py
index 28de7bf..259cffa 100644
--- a/bricktracker/reload.py
+++ b/bricktracker/reload.py
@@ -1,5 +1,6 @@
 from .instructions_list import BrickInstructionsList
 from .retired_list import BrickRetiredList
+from .set_status import BrickSetStatus
 from .set_status_list import BrickSetStatusList
 from .theme_list import BrickThemeList
 
@@ -12,7 +13,7 @@ def reload() -> None:
         BrickInstructionsList(force=True)
 
         # Reload the set statuses
-        BrickSetStatusList(force=True)
+        BrickSetStatusList(BrickSetStatus, force=True)
 
         # Reload retired sets
         BrickRetiredList(force=True)
diff --git a/bricktracker/set.py b/bricktracker/set.py
index 1b11a94..32bf8da 100644
--- a/bricktracker/set.py
+++ b/bricktracker/set.py
@@ -9,6 +9,7 @@ from .exceptions import NotFoundException
 from .minifigure_list import BrickMinifigureList
 from .part_list import BrickPartList
 from .rebrickable_set import RebrickableSet
+from .set_status import BrickSetStatus
 from .set_status_list import BrickSetStatusList
 from .sql import BrickSQL
 if TYPE_CHECKING:
@@ -161,7 +162,7 @@ class BrickSet(RebrickableSet):
 
         # Load from database
         if not self.select(
-            statuses=BrickSetStatusList().as_columns(solo=True)
+            statuses=BrickSetStatusList(BrickSetStatus).as_columns(all=True)
         ):
             raise NotFoundException(
                 'Set with ID {id} was not found in the database'.format(
diff --git a/bricktracker/set_list.py b/bricktracker/set_list.py
index 47d31b2..251cfdc 100644
--- a/bricktracker/set_list.py
+++ b/bricktracker/set_list.py
@@ -3,6 +3,7 @@ from typing import Self
 from flask import current_app
 
 from .record_list import BrickRecordList
+from .set_status import BrickSetStatus
 from .set_status_list import BrickSetStatusList
 from .set import BrickSet
 
@@ -37,7 +38,7 @@ class BrickSetList(BrickRecordList[BrickSet]):
         # Load the sets from the database
         for record in self.select(
             order=self.order,
-            statuses=BrickSetStatusList().as_columns()
+            statuses=BrickSetStatusList(BrickSetStatus).as_columns()
         ):
             brickset = BrickSet(record=record)
 
@@ -73,7 +74,7 @@ class BrickSetList(BrickRecordList[BrickSet]):
         for record in self.select(
             order=order,
             limit=limit,
-            statuses=BrickSetStatusList().as_columns()
+            statuses=BrickSetStatusList(BrickSetStatus).as_columns()
         ):
             brickset = BrickSet(record=record)
 
diff --git a/bricktracker/set_status_list.py b/bricktracker/set_status_list.py
index 12ce85a..b96f213 100644
--- a/bricktracker/set_status_list.py
+++ b/bricktracker/set_status_list.py
@@ -1,71 +1,23 @@
 import logging
 
-from .exceptions import NotFoundException
-from .fields import BrickRecordFields
-from .record_list import BrickRecordList
+from .metadata_list import BrickMetadataList
 from .set_status import BrickSetStatus
 
 logger = logging.getLogger(__name__)
 
 
 # Lego sets status list
-class BrickSetStatusList(BrickRecordList[BrickSetStatus]):
-    statuses: dict[str, BrickSetStatus]
+class BrickSetStatusList(BrickMetadataList):
+    kind: str = 'set statuses'
+
+    # Database table
+    table: str = 'bricktracker_set_statuses'
 
     # Queries
     select_query = 'set/metadata/status/list'
 
-    def __init__(self, /, *, force: bool = False):
-        # Load statuses only if there is none already loaded
-        records = getattr(self, 'records', None)
-
-        if records is None or force:
-            # Don't use super()__init__ as it would mask class variables
-            self.fields = BrickRecordFields()
-
-            logger.info('Loading set statuses list')
-
-            BrickSetStatusList.records = []
-            BrickSetStatusList.statuses = {}
-
-            # Load the statuses from the database
-            for record in self.select():
-                status = BrickSetStatus(record=record)
-
-                BrickSetStatusList.records.append(status)
-                BrickSetStatusList.statuses[status.fields.id] = status
-
-    # Return the statuses as columns for a select
-    def as_columns(
-        self,
-        /,
-        *,
-        solo: bool = False,
-        table: str = 'bricktracker_set_statuses'
-    ) -> str:
-        return ', '.join([
-            '"{table}"."{column}"'.format(
-                table=table,
-                column=record.as_column(),
-            )
-            for record
-            in self.records
-            if solo or record.fields.displayed_on_grid
-        ])
-
-    # Grab a specific status
-    def get(self, id: str, /) -> BrickSetStatus:
-        if id not in self.statuses:
-            raise NotFoundException(
-                'Status with ID {id} was not found in the database'.format(
-                    id=id,
-                ),
-            )
-
-        return self.statuses[id]
-
-    # Get the list of statuses depending on the context
-    def list(self, /, *, all: bool = False) -> list[BrickSetStatus]:
+    # Filter the list of set status
+    def filter(self, all: bool = False) -> list[BrickSetStatus]:
         return [
             record
             for record
diff --git a/bricktracker/views/admin/admin.py b/bricktracker/views/admin/admin.py
index a7f8ce7..c18a74b 100644
--- a/bricktracker/views/admin/admin.py
+++ b/bricktracker/views/admin/admin.py
@@ -41,7 +41,7 @@ def admin() -> str:
         database_version = database.version
         database_counters = BrickSQL().count_records()
 
-        metadata_statuses = BrickSetStatusList().list(all=True)
+        metadata_statuses = BrickSetStatusList(BrickSetStatus).list(all=True)
     except Exception as e:
         database_exception = e
 
diff --git a/bricktracker/views/index.py b/bricktracker/views/index.py
index 3e3a880..f8fe7b7 100644
--- a/bricktracker/views/index.py
+++ b/bricktracker/views/index.py
@@ -2,6 +2,7 @@ from flask import Blueprint, render_template
 
 from .exceptions import exception_handler
 from ..minifigure_list import BrickMinifigureList
+from ..set_status import BrickSetStatus
 from ..set_status_list import BrickSetStatusList
 from ..set_list import BrickSetList
 
@@ -16,5 +17,5 @@ def index() -> str:
         'index.html',
         brickset_collection=BrickSetList().last(),
         minifigure_collection=BrickMinifigureList().last(),
-        brickset_statuses=BrickSetStatusList().list(),
+        brickset_statuses=BrickSetStatusList(BrickSetStatus).list(),
     )
diff --git a/bricktracker/views/set.py b/bricktracker/views/set.py
index 17fcff9..9f1990c 100644
--- a/bricktracker/views/set.py
+++ b/bricktracker/views/set.py
@@ -16,6 +16,7 @@ from .exceptions import exception_handler
 from ..minifigure import BrickMinifigure
 from ..part import BrickPart
 from ..set import BrickSet
+from ..set_status import BrickSetStatus
 from ..set_status_list import BrickSetStatusList
 from ..set_list import BrickSetList
 from ..socket import MESSAGES
@@ -32,7 +33,7 @@ def list() -> str:
     return render_template(
         'sets.html',
         collection=BrickSetList().all(),
-        brickset_statuses=BrickSetStatusList().list(),
+        brickset_statuses=BrickSetStatusList(BrickSetStatus).list(),
     )
 
 
@@ -42,7 +43,7 @@ def list() -> str:
 @exception_handler(__file__, json=True)
 def update_status(*, id: str, metadata_id: str) -> Response:
     brickset = BrickSet().select_light(id)
-    status = BrickSetStatusList().get(metadata_id)
+    status = BrickSetStatusList(BrickSetStatus).get(metadata_id)
 
     state = status.update_set_state(brickset, request.json)
 
@@ -97,7 +98,7 @@ def details(*, id: str) -> str:
         'set.html',
         item=BrickSet().select_specific(id),
         open_instructions=request.args.get('open_instructions'),
-        brickset_statuses=BrickSetStatusList().list(all=True),
+        brickset_statuses=BrickSetStatusList(BrickSetStatus).list(all=True),
     )