diff --git a/build.gradle b/build.gradle
index 0787bf22f..2564cb39f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -180,6 +180,10 @@ allprojects {
 	}
 }
 
+// Apply auxiliary buildscripts to submodules
+// This must be done after all plugins are applied to subprojects
+apply from: "gradle/module-validation.gradle"
+
 javadoc {
 	options {
 		source = "8"
diff --git a/fabric-api-base/src/main/resources/fabric.mod.json b/fabric-api-base/src/main/resources/fabric.mod.json
index 4ce576766..7fda5d59f 100644
--- a/fabric-api-base/src/main/resources/fabric.mod.json
+++ b/fabric-api-base/src/main/resources/fabric.mod.json
@@ -18,5 +18,8 @@
   "depends": {
     "fabricloader": ">=0.4.0"
   },
-  "description": "Contains the essentials for Fabric API modules."
+  "description": "Contains the essentials for Fabric API modules.",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-biome-api-v1/src/main/resources/fabric.mod.json b/fabric-biome-api-v1/src/main/resources/fabric.mod.json
index 7f9984e6b..21c70d68f 100644
--- a/fabric-biome-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-biome-api-v1/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "mixins": [
     "fabric-biome-api-v1.mixins.json"
   ],
-  "accessWidener" : "fabric-biome-api-v1.accesswidener"
+  "accessWidener" : "fabric-biome-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "experimental"
+  }
 }
diff --git a/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json b/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json
index 036a3c431..12ec985b7 100644
--- a/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json
+++ b/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Registration utility for block and fluid render layers.",
   "mixins": [
     "fabric-blockrenderlayer-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-command-api-v1/src/main/resources/fabric.mod.json b/fabric-command-api-v1/src/main/resources/fabric.mod.json
index 64a43e5b7..1d996428f 100644
--- a/fabric-command-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-command-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Adds command-related hooks.",
   "mixins": [
     "fabric-command-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-commands-v0/src/main/resources/fabric.mod.json b/fabric-commands-v0/src/main/resources/fabric.mod.json
index 8048ade7c..7f401a491 100644
--- a/fabric-commands-v0/src/main/resources/fabric.mod.json
+++ b/fabric-commands-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   },
   "description": "Deprecated. Please migrate to v1",
   "mixins": [
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-containers-v0/src/main/resources/fabric.mod.json b/fabric-containers-v0/src/main/resources/fabric.mod.json
index 765b3500e..76281ce45 100644
--- a/fabric-containers-v0/src/main/resources/fabric.mod.json
+++ b/fabric-containers-v0/src/main/resources/fabric.mod.json
@@ -29,5 +29,8 @@
     "client": [
       "net.fabricmc.fabric.impl.client.container.ScreenProviderRegistryImpl::init"
     ]
+  },
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
   }
 }
diff --git a/fabric-content-registries-v0/src/main/resources/fabric.mod.json b/fabric-content-registries-v0/src/main/resources/fabric.mod.json
index b7486229b..d25c1c7d9 100644
--- a/fabric-content-registries-v0/src/main/resources/fabric.mod.json
+++ b/fabric-content-registries-v0/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "description": "Adds registries for vanilla mechanics that are missing them.",
   "mixins": [
     "fabric-content-registries-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json b/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json
index 53df27ffb..2d6add287 100644
--- a/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json
+++ b/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Adds Fabric-related debug info to crash reports.",
   "mixins": [
     "fabric-crash-report-info-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-dimensions-v1/src/main/resources/fabric.mod.json b/fabric-dimensions-v1/src/main/resources/fabric.mod.json
index 2a8c87e39..6a6606b1f 100644
--- a/fabric-dimensions-v1/src/main/resources/fabric.mod.json
+++ b/fabric-dimensions-v1/src/main/resources/fabric.mod.json
@@ -12,5 +12,8 @@
   },
   "mixins": [
     "fabric-dimensions-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "experimental"
+  }
 }
diff --git a/fabric-entity-events-v1/src/main/resources/fabric.mod.json b/fabric-entity-events-v1/src/main/resources/fabric.mod.json
index 5df554aab..ea5ce0a4a 100644
--- a/fabric-entity-events-v1/src/main/resources/fabric.mod.json
+++ b/fabric-entity-events-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Events to hook into entities.",
   "mixins": [
     "fabric-entity-events-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-events-interaction-v0/src/main/resources/fabric.mod.json b/fabric-events-interaction-v0/src/main/resources/fabric.mod.json
index 94a7c7f11..85cc9baae 100644
--- a/fabric-events-interaction-v0/src/main/resources/fabric.mod.json
+++ b/fabric-events-interaction-v0/src/main/resources/fabric.mod.json
@@ -31,5 +31,8 @@
   "description": "Events for player interaction with blocks and entities.",
   "mixins": [
     "fabric-events-interaction-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json b/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json
index 7eb6a935f..5630ecba6 100644
--- a/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json
+++ b/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json
@@ -29,5 +29,8 @@
     "fabric-item-api-v1": "*",
     "fabric-lifecycle-events-v1": "*"
   },
-  "description": "Legacy events for the game's lifecycle, superseded by fabric-lifecycle-events-v1 and fabric-item-api-v1."
+  "description": "Legacy events for the game's lifecycle, superseded by fabric-lifecycle-events-v1 and fabric-item-api-v1.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json b/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json
index 3d7f814be..a1e909b53 100644
--- a/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "mixins": [
     "fabric-game-rule-api-v1.mixins.json"
   ],
-  "accessWidener" : "fabric-game-rule-api-v1.accesswidener"
+  "accessWidener" : "fabric-game-rule-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-item-api-v1/src/main/resources/fabric.mod.json b/fabric-item-api-v1/src/main/resources/fabric.mod.json
index 111fe5731..6a2e17f7c 100644
--- a/fabric-item-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-item-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
     "fabricloader": ">=0.4.0",
     "fabric-api-base": "*"
   },
-  "description": "Hooks for items"
+  "description": "Hooks for items",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-item-groups-v0/src/main/resources/fabric.mod.json b/fabric-item-groups-v0/src/main/resources/fabric.mod.json
index 74ce83e75..9e60fb649 100644
--- a/fabric-item-groups-v0/src/main/resources/fabric.mod.json
+++ b/fabric-item-groups-v0/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "description": "An API for adding custom item groups.",
   "mixins": [
     "fabric-item-groups-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json b/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json
index c7fe5b4ff..db552fc70 100644
--- a/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Key Binding registry API.",
   "mixins": [
     "fabric-key-binding-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-keybindings-v0/src/main/resources/fabric.mod.json b/fabric-keybindings-v0/src/main/resources/fabric.mod.json
index a6c01bfaf..c35c67374 100644
--- a/fabric-keybindings-v0/src/main/resources/fabric.mod.json
+++ b/fabric-keybindings-v0/src/main/resources/fabric.mod.json
@@ -19,5 +19,8 @@
     "fabricloader": ">=0.4.0",
     "fabric-key-binding-api-v1": "*"
   },
-  "description": "Keybinding registry API."
+  "description": "Keybinding registry API.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json b/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json
index 724aa33a8..05ce7a7f7 100644
--- a/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json
+++ b/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json
@@ -30,5 +30,8 @@
     "fabricloader": ">=0.4.0",
     "fabric-api-base": "*"
   },
-  "description": "Events for the game's lifecycle."
+  "description": "Events for the game's lifecycle.",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-loot-tables-v1/src/main/resources/fabric.mod.json b/fabric-loot-tables-v1/src/main/resources/fabric.mod.json
index 597b845d2..ecd00ec3c 100644
--- a/fabric-loot-tables-v1/src/main/resources/fabric.mod.json
+++ b/fabric-loot-tables-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for manipulating loot tables.",
   "mixins": [
     "fabric-loot-tables-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-mining-levels-v0/src/main/resources/fabric.mod.json b/fabric-mining-levels-v0/src/main/resources/fabric.mod.json
index bbf95ced2..c7bfd8097 100644
--- a/fabric-mining-levels-v0/src/main/resources/fabric.mod.json
+++ b/fabric-mining-levels-v0/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
     "fabric-tag-extensions-v0": "*",
     "fabric-tool-attribute-api-v1": "*"
   },
-  "description": "Block mining level tags for tools. Deprecated and replaced by fabric-tool-attribute-v1."
+  "description": "Block mining level tags for tools. Deprecated and replaced by fabric-tool-attribute-v1.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-models-v0/src/main/resources/fabric.mod.json b/fabric-models-v0/src/main/resources/fabric.mod.json
index c66ff4e10..93a4b284b 100644
--- a/fabric-models-v0/src/main/resources/fabric.mod.json
+++ b/fabric-models-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for models and model loading.",
   "mixins": [
     "fabric-models-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-networking-api-v1/src/main/resources/fabric.mod.json b/fabric-networking-api-v1/src/main/resources/fabric.mod.json
index 0e2b09bc5..4264185e7 100644
--- a/fabric-networking-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-networking-api-v1/src/main/resources/fabric.mod.json
@@ -30,5 +30,8 @@
   "description": "Low-level, vanilla protocol oriented networking hooks.",
   "mixins": [
     "fabric-networking-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json b/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json
index 3a3a27891..e41cbd094 100644
--- a/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json
+++ b/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Networking hooks for block entities.",
   "mixins": [
     "fabric-networking-blockentity-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-networking-v0/src/main/resources/fabric.mod.json b/fabric-networking-v0/src/main/resources/fabric.mod.json
index b5c186463..081e30da0 100644
--- a/fabric-networking-v0/src/main/resources/fabric.mod.json
+++ b/fabric-networking-v0/src/main/resources/fabric.mod.json
@@ -28,5 +28,8 @@
     "fabric-api-base": "*",
     "fabric-networking-api-v1": "*"
   },
-  "description": "Legacy Networking packet hooks and registries, superseded by fabric-networking-api-v1."
+  "description": "Legacy Networking packet hooks and registries, superseded by fabric-networking-api-v1.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json
index 744ae1bc6..6f07272be 100644
--- a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "mixins": [
     "fabric-object-builder-v1.mixins.json"
   ],
-  "accessWidener" : "fabric-object-builder-api-v1.accesswidener"
+  "accessWidener" : "fabric-object-builder-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-object-builders-v0/src/main/resources/fabric.mod.json b/fabric-object-builders-v0/src/main/resources/fabric.mod.json
index e4da46d34..f3a301595 100644
--- a/fabric-object-builders-v0/src/main/resources/fabric.mod.json
+++ b/fabric-object-builders-v0/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Legacy builders for objects vanilla has locked down, superseded by fabric-object-builder-api-v1.",
   "mixins": [
     "fabric-object-builders-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-particles-v1/src/main/resources/fabric.mod.json b/fabric-particles-v1/src/main/resources/fabric.mod.json
index 62ac00ca2..b6fcf47e4 100644
--- a/fabric-particles-v1/src/main/resources/fabric.mod.json
+++ b/fabric-particles-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Hooks for registering custom particles.",
   "mixins": [
     "fabric-particles-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
index c4917633e..c57dea4b7 100644
--- a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
+++ b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
@@ -31,5 +31,8 @@
     "client": [
       "net.fabricmc.fabric.impl.registry.sync.FabricRegistryClientInit"
     ]
+  },
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
   }
 }
diff --git a/fabric-renderer-api-v1/src/main/resources/fabric.mod.json b/fabric-renderer-api-v1/src/main/resources/fabric.mod.json
index 501a70e68..61e4f8592 100644
--- a/fabric-renderer-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-renderer-api-v1/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "mixins": [
     "fabric-renderer-api-v1.mixins.json",
     "fabric-renderer-api-v1.debughud.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-renderer-indigo/src/main/resources/fabric.mod.json b/fabric-renderer-indigo/src/main/resources/fabric.mod.json
index cc58f9fb1..f8a08d113 100755
--- a/fabric-renderer-indigo/src/main/resources/fabric.mod.json
+++ b/fabric-renderer-indigo/src/main/resources/fabric.mod.json
@@ -29,5 +29,8 @@
     "client": [
       "net.fabricmc.fabric.impl.client.indigo.Indigo"
     ]
+  },
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
   }
 }
diff --git a/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json b/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json
index 16a0173c1..2ed23dcb8 100644
--- a/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json
+++ b/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Registries for entity and block renderers.",
   "mixins": [
     "fabric-renderer-registries-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json b/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json
index ccc4e8e39..362f2c0b5 100644
--- a/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Thread-safe hooks for block entity data use during terrain rendering.",
   "mixins": [
     "fabric-rendering-data-attachment-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json b/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json
index 5708d98a6..e0705bbcb 100644
--- a/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json
@@ -25,5 +25,8 @@
   "description": "Hooks for registering fluid renders.",
   "mixins": [
     "fabric-rendering-fluids-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-rendering-v0/src/main/resources/fabric.mod.json b/fabric-rendering-v0/src/main/resources/fabric.mod.json
index 0290e6039..3a9d8eef4 100644
--- a/fabric-rendering-v0/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-v0/src/main/resources/fabric.mod.json
@@ -26,5 +26,8 @@
     "fabric-api-base": "*",
     "fabric-rendering-v1": "*"
   },
-  "description": "Hooks and registries for rendering-related things."
+  "description": "Hooks and registries for rendering-related things.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-rendering-v1/src/main/resources/fabric.mod.json b/fabric-rendering-v1/src/main/resources/fabric.mod.json
index 5b21b99b5..a17c8cd5c 100644
--- a/fabric-rendering-v1/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks and registries for rendering-related things.",
   "mixins": [
     "fabric-rendering-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json
index 291900737..60c01dfbe 100644
--- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json
+++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Asset and data resource loading.",
   "mixins": [
     "fabric-resource-loader-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json b/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json
index 6539d01a1..434523493 100644
--- a/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json
@@ -27,5 +27,8 @@
   "mixins": [
     "fabric-screen-handler-api-v1.mixins.json"
   ],
-  "accessWidener": "fabric-screen-handler-api-v1.accesswidener"
+  "accessWidener": "fabric-screen-handler-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-structure-api-v1/src/main/resources/fabric.mod.json b/fabric-structure-api-v1/src/main/resources/fabric.mod.json
index 7e597d4d9..255dc0742 100644
--- a/fabric-structure-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-structure-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for registering custom structures.",
   "mixins": [
     "fabric-structure-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json b/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json
index 125cb5310..fae990293 100644
--- a/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json
+++ b/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Hooks for tags.",
   "mixins": [
     "fabric-tag-extensions-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-textures-v0/src/main/resources/fabric.mod.json b/fabric-textures-v0/src/main/resources/fabric.mod.json
index 1d3156ebf..9c22c5c3c 100644
--- a/fabric-textures-v0/src/main/resources/fabric.mod.json
+++ b/fabric-textures-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for texture loading and registration.",
   "mixins": [
     "fabric-textures-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json b/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json
index 0e21a2639..d37b5c6ee 100644
--- a/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json
@@ -28,5 +28,8 @@
   "description": "Dynamic atttributes for tools.",
   "mixins": [
     "fabric-tool-attribute-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/gradle/module-validation.gradle b/gradle/module-validation.gradle
new file mode 100644
index 000000000..a1ed31e8b
--- /dev/null
+++ b/gradle/module-validation.gradle
@@ -0,0 +1,61 @@
+import groovy.json.JsonSlurper
+
+/*
+ * This buildscript contains tasks related to the validation of each module in fabric api.
+ *
+ * Right now this task verifies each Fabric API module has a module lifecycle specified.
+ * More functionality will probably be added in the future.
+ */
+
+subprojects {
+	// Create the task
+	task validateModules(type: ValidateModuleTask)
+}
+
+/**
+ * Verifies that each module has the required custom values for module lifecycle in it's FMJ.
+ *
+ * <p>Example:
+ * <pre>{@code
+ * "custom": {
+ *   "fabric-api:module-lifecycle": "stable"
+ * }
+ * }</pre>
+ */
+class ValidateModuleTask extends DefaultTask {
+	ValidateModuleTask() {
+		group = "verification"
+
+		// Hook up validation to check task
+		project.tasks.check.dependsOn(this)
+	}
+
+	@TaskAction
+	void validate() {
+		def json = new JsonSlurper().parse(project.file("src/main/resources/fabric.mod.json") as File) as Map<String, Map<String, String>>;
+
+		if (json.custom == null) {
+			throw new GradleException("Module ${project} does not have a custom value containing module lifecycle!")
+		}
+
+		def moduleLifecycle = json.custom.get("fabric-api:module-lifecycle")
+
+		if (moduleLifecycle == null) {
+			throw new GradleException("Module ${project} does not have module lifecycle in custom values!")
+		}
+
+		if (!moduleLifecycle instanceof String) {
+			throw new GradleException("Module ${project} has an invalid module lifecycle value. The value must be a string but read a ${moduleLifecycle.class}")
+		}
+
+		// Validate the lifecycle value
+		switch (moduleLifecycle) {
+			case "stable":
+			case "experimental":
+			case "deprecated":
+				break;
+			default:
+				throw new GradleException("Module ${project} has an invalid module lifecycle ${json.custom.get('fabric-api:module-lifecycle')}");
+		}
+	}
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 490fda857..e708b1c02 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index be52383ef..1f3fdbc52 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 2fe81a7d9..4f906e0c8 100755
--- a/gradlew
+++ b/gradlew
@@ -82,6 +82,7 @@ esac
 
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
+
 # Determine the Java command to use to start the JVM.
 if [ -n "$JAVA_HOME" ] ; then
     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -129,6 +130,7 @@ fi
 if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
     JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
diff --git a/gradlew.bat b/gradlew.bat
index 62bd9b9cc..ac1b06f93 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,103 +1,89 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem      https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem  Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega