This template includes optional Modrinth publishing as part of .github/workflows/release.yml.
After the GitHub release is created, a second job in the same workflow does two things:
- Creates the Modrinth project if a project with slug
mod_iddoes not already exist. - Uploads the built Fabric and NeoForge release jars as Modrinth versions if that
mod_versionhas not already been uploaded.
The Modrinth job is skipped unless the repository has a MODRINTH_TOKEN secret configured.
Create a Modrinth personal access token and add it as a repository secret to the GitHub repository as MODRINTH_TOKEN.
Minimum useful scopes:
PROJECT_CREATEPROJECT_READPROJECT_WRITEVERSION_READVERSION_CREATE
The release workflow uses the Modrinth API directly:
- Project creation:
POST /project - Version upload:
POST /version
The workflow reads:
fabric/src/main/resources/fabric.mod.jsonfor the project slug, title, fallback description, contact links, licence, and side support inferenceREADME.mdfor the long project description- The GitHub repository description for the Modrinth project summary
.modrinth/project.jsonfor optional Modrinth-specific overridesgradle.propertiesformod_versionandminecraft_version
Defaults:
- The Modrinth slug is
fabric.mod.json.id - The project is created as
draft - The GitHub repo URL is used when
fabric.mod.json.contact.sourcesis absent - The GitHub issues URL is used when
fabric.mod.json.contact.issuesis absent - The GitHub wiki URL is used when
fabric.mod.json.contact.wikiis absent - The licence link points at
LICENSEby default fabricis used as the default loader for versions when no override is suppliedutilityis used as the default project category when no override is supplieddiscord_urlis always set tohttps://discord.gg/N4zfhBx8Fm- The workflow syncs the project summary, long description,
issues_url,source_url,wiki_url, andlicense_urlon every release so existing Modrinth projects stay aligned with the repository - Existing Modrinth project icons are only replaced when the current Modrinth icon URL does not already contain the SHA-1 of the local icon file
In practice, .modrinth/project.json can be kept very small. The template only needs it when you want to override defaults such as:
slugcategoriesadditional_categorieswiki_urllicense_urldependency_overrides
Valid values for categories and additional_categories are as follows:
adventurecurseddecorationeconomyequipmentfoodgame-mechanicslibrarymagicmanagementminigamemobsoptimizationsocialstoragetechnologytransportationutilityworldgen
additional_categories uses the same values as categories; the difference is that they are searchable but not shown as primary display categories.
If you do not need any overrides, you can remove .modrinth/project.json entirely and the workflow will fall back to defaults.
Modrinth categories are separate from loaders. Do not use fabric in categories or additional_categories; keep Fabric in version.loaders if you need to override loaders.
Version dependencies are inferred from fabric/src/main/resources/fabric.mod.json:
dependsbecomes Modrinthrequiredrecommendsandsuggestsbecome Modrinthoptionalconflictsandbreaksbecome Modrinthincompatibleminecraft,java, andfabricloaderare ignored
The workflow first tries the Fabric mod ID as a Modrinth slug, then simple normalisations such as replacing _ with -.
If a dependency uses a different Modrinth slug, add an override in .modrinth/project.json:
{
"dependency_overrides": {
"some-mod-id": {
"project_slug": "some-modrinth-slug"
}
}
}You can also override the dependency type, provide a project ID directly, or skip a dependency entirely:
{
"dependency_overrides": {
"some_mod": {
"project_id": "AABBCCDD",
"dependency_type": "optional"
},
"local_only_mod": {
"skip": true
}
}
}Manual extra version dependencies are still supported with version.dependencies if you need to append entries that do not come from fabric.mod.json.
Side support is inferred from fabric.mod.json:
environment=client:client_side=required,server_side=unsupportedenvironment=server:client_side=unsupported,server_side=requiredenvironment=*with a client entrypoint:client_side=required,server_side=requiredenvironment=*without a client entrypoint:client_side=unsupported,server_side=required
You can still override the inferred values in .modrinth/project.json if needed.
The Modrinth changelog is taken from the same annotated tag notes that are used for the GitHub release body. See RELEASE.md for more info.
The release workflow fetches the remote tag object before reading notes so annotated tag messages are preserved in GitHub Actions checkouts.
- The workflow uploads the Fabric release jar and the NeoForge jar (
<archives_base_name>-neoforge-*.jar) frombuild/libsand ignores*-dev.jarand*-sources.jar. - If the Modrinth project already exists, it is reused instead of recreated. When a project is newly created, the separate icon sync step is skipped for that release because the create request already uploads the icon.
- If an existing Modrinth project icon must change and Modrinth rejects the icon replacement, the workflow still publishes the Modrinth version, then fails the job at the end so the stale icon remains visible.
- If the Modrinth version already exists for the current
mod_version, publishing is skipped. - The Modrinth scripts can also be run locally for validation. When they run outside GitHub Actions,
GITHUB_ENVis optional and no step output file is written.