diff --git a/CHANGELOG.md b/CHANGELOG.md
index 54b0fa8..40b4f17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@
 
 - Minifigure
     - Deduplicate
+    - Compute number of parts
 
 Parts
     - Damaged parts
@@ -57,6 +58,9 @@ Parts
     - Add a clear button for dynamic text inputs
     - Add error message in a tooltip for dynamic inputs
 
+- Minifigure
+    - Display number of parts
+
 - Parts
     - Use Rebrickable URL if stored (+ color code)
     - Display color and transparency
diff --git a/bricktracker/minifigure.py b/bricktracker/minifigure.py
index 1ad6aa6..c09589e 100644
--- a/bricktracker/minifigure.py
+++ b/bricktracker/minifigure.py
@@ -37,9 +37,6 @@ class BrickMinifigure(RebrickableMinifigure):
                 # Insert into database
                 self.insert(commit=False)
 
-            # Insert the rebrickable set into database
-            self.insert_rebrickable()
-
             # Load the inventory
             if not BrickPartList.download(
                 socket,
@@ -49,6 +46,9 @@ class BrickMinifigure(RebrickableMinifigure):
             ):
                 return False
 
+            # Insert the rebrickable set into database (after counting parts)
+            self.insert_rebrickable()
+
         except Exception as e:
             socket.fail(
                 message='Error while importing minifigure {figure} from {set}: {error}'.format(  # noqa: E501
diff --git a/bricktracker/part_list.py b/bricktracker/part_list.py
index d0e7138..eb3f58d 100644
--- a/bricktracker/part_list.py
+++ b/bricktracker/part_list.py
@@ -239,10 +239,18 @@ class BrickPartList(BrickRecordList[BrickPart]):
             ).list()
 
             # Process each part
+            number_of_parts: int = 0
             for part in inventory:
+                # Count the number of parts for minifigures
+                if minifigure is not None:
+                    number_of_parts += part.fields.quantity
+
                 if not part.download(socket, refresh=refresh):
                     return False
 
+            if minifigure is not None:
+                minifigure.fields.number_of_parts = number_of_parts
+
         except Exception as e:
             socket.fail(
                 message='Error while importing {kind} {identifier} parts list: {error}'.format(  # noqa: E501
diff --git a/bricktracker/sql/migrations/0015.sql b/bricktracker/sql/migrations/0015.sql
new file mode 100644
index 0000000..de2d6ec
--- /dev/null
+++ b/bricktracker/sql/migrations/0015.sql
@@ -0,0 +1,32 @@
+-- description: Add number of parts for minifigures
+
+BEGIN TRANSACTION;
+
+-- Add the number_of_parts column to the minifigures
+ALTER TABLE "rebrickable_minifigures"
+ADD COLUMN "number_of_parts" INTEGER NOT NULL DEFAULT 0;
+
+-- Update the number of parts for each minifigure
+UPDATE "rebrickable_minifigures"
+SET "number_of_parts" = "parts_sum"."number_of_parts"
+FROM (
+    SELECT
+        "parts"."figure",
+        SUM("parts"."quantity") as "number_of_parts"
+    FROM (
+        SELECT
+            "bricktracker_parts"."figure",
+            "bricktracker_parts"."quantity"
+        FROM "bricktracker_parts"
+        WHERE "bricktracker_parts"."figure" IS NOT NULL
+        GROUP BY
+            "bricktracker_parts"."figure",
+            "bricktracker_parts"."part",
+            "bricktracker_parts"."color",
+            "bricktracker_parts"."spare"
+    ) "parts"
+    GROUP BY "parts"."figure"
+) "parts_sum"
+WHERE "rebrickable_minifigures"."figure" = "parts_sum"."figure";
+
+COMMIT;
diff --git a/bricktracker/sql/minifigure/base/base.sql b/bricktracker/sql/minifigure/base/base.sql
index d651bf0..a3a30a7 100644
--- a/bricktracker/sql/minifigure/base/base.sql
+++ b/bricktracker/sql/minifigure/base/base.sql
@@ -2,6 +2,7 @@ SELECT
     "bricktracker_minifigures"."quantity",
     "rebrickable_minifigures"."figure",
     "rebrickable_minifigures"."number",
+    "rebrickable_minifigures"."number_of_parts",
     "rebrickable_minifigures"."name",
     "rebrickable_minifigures"."image",
     {% block total_missing %}
diff --git a/bricktracker/sql/rebrickable/minifigure/insert.sql b/bricktracker/sql/rebrickable/minifigure/insert.sql
index 6c0ac8e..3db1680 100644
--- a/bricktracker/sql/rebrickable/minifigure/insert.sql
+++ b/bricktracker/sql/rebrickable/minifigure/insert.sql
@@ -2,16 +2,19 @@ INSERT OR IGNORE INTO "rebrickable_minifigures" (
     "figure",
     "number",
     "name",
-    "image"
+    "image",
+    "number_of_parts"
 ) VALUES (
     :figure,
     :number,
     :name,
-    :image
+    :image,
+    :number_of_parts
 )
 ON CONFLICT("figure")
 DO UPDATE SET
 "number" = :number,
 "name" = :name,
-"image" = :image
+"image" = :image,
+"number_of_parts" = :number_of_parts
 WHERE "rebrickable_minifigures"."figure" IS NOT DISTINCT FROM :figure
diff --git a/bricktracker/version.py b/bricktracker/version.py
index 767fad5..4efb1e6 100644
--- a/bricktracker/version.py
+++ b/bricktracker/version.py
@@ -1,4 +1,4 @@
 from typing import Final
 
 __version__: Final[str] = '1.2.0'
-__database_version__: Final[int] = 14
+__database_version__: Final[int] = 15
diff --git a/templates/macro/table.html b/templates/macro/table.html
index d31e1c2..ebf1ded 100644
--- a/templates/macro/table.html
+++ b/templates/macro/table.html
@@ -1,4 +1,4 @@
-{% macro header(color=false, quantity=false, missing_parts=false, damaged_parts=false, sets=false, minifigures=false) %}
+{% macro header(color=false, parts=false, quantity=false, missing_parts=false, damaged_parts=false, sets=false, minifigures=false) %}
   <thead>
     <tr>
       <th data-table-no-sort="true" class="no-sort" scope="col"><i class="ri-image-line fw-normal"></i> Image</th>
@@ -6,6 +6,9 @@
       {% if color %}
         <th scope="col"><i class="ri-palette-line fw-normal"></i> Color</th>
       {% endif %}
+      {% if parts %}
+        <th data-table-number="true" scope="col"><i class="ri-shapes-line fw-normal"></i> Parts</th>
+      {% endif %}
       {% if quantity %}
         <th data-table-number="true" scope="col"><i class="ri-functions fw-normal"></i> Quantity</th>
       {% endif %}
diff --git a/templates/minifigure/card.html b/templates/minifigure/card.html
index 80459e3..2cba9b4 100644
--- a/templates/minifigure/card.html
+++ b/templates/minifigure/card.html
@@ -6,6 +6,7 @@
   {{ card.header(item, item.fields.name, solo=solo, identifier=item.fields.figure, icon='user-line') }}
   {{ card.image(item, solo=solo, last=last, caption=item.fields.name, alt=item.fields.figure, medium=true) }}
   <div class="card-body border-bottom {% if not solo %}p-1{% endif %}">
+    {{ badge.parts(item.fields.number_of_parts, solo=solo, last=last) }}
     {% if last %}
       {{ badge.set(item.fields.set, solo=solo, last=last, id=item.fields.rebrickable_set_id) }}
       {{ badge.quantity(item.fields.quantity, solo=solo, last=last) }}
diff --git a/templates/minifigure/table.html b/templates/minifigure/table.html
index aeb0bb7..c91ab58 100644
--- a/templates/minifigure/table.html
+++ b/templates/minifigure/table.html
@@ -2,7 +2,7 @@
 
 <div class="table-responsive-sm">
   <table data-table="{% if all %}true{% endif %}" class="table table-striped align-middle" id="minifigures">
-    {{ table.header(quantity=true, missing_parts=true, damaged_parts=true, sets=true) }}
+    {{ table.header(parts=true, quantity=true, missing_parts=true, damaged_parts=true, sets=true) }}
     <tbody>
       {% for item in table_collection %}
       <tr>
@@ -13,6 +13,7 @@
             {{ table.rebrickable(item) }}
           {% endif %}
         </td>
+        <td>{{ item.fields.number_of_parts }}</td>
         <td>{{ item.fields.total_quantity }}</td>
         <td>{{ item.fields.total_missing }}</td>
         <td>{{ item.fields.total_damaged }}</td>