Contributing to the Registry
██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗ ██╗ ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝ ██████╔╝█████╗ ██║ ███╗██║███████╗ ██║ ██████╔╝ ╚████╔╝ ██╔══██╗██╔══╝ ██║ ██║██║╚════██║ ██║ ██╔══██╗ ╚██╔╝ ██║ ██║███████╗╚██████╔╝██║███████║ ██║ ██║ ██║ ██║ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
Thank you for contributing to the DankMaterialShell registry! This guide covers how to submit plugins and themes to the dms-plugin-registry repository.
Contributing a Plugin
How to Add Your Plugin
-
Fork the repository
- Go to AvengeMedia/dms-plugin-registry and click Fork
-
Create a new JSON file in the
plugins/directory:plugins/{github-username}-{plugin-name}.json- Use lowercase letters
- Separate words with hyphens
- Examples:
daniel-42-z-powerusage.json,rochacbruno-worldclock.json
-
Fill in your plugin information using this schema:
{
"id": "pluginId",
"name": "PluginName",
"capabilities": ["dankbar-widget"],
"category": "monitoring",
"repo": "https://github.com/yourusername/your-plugin-repo",
"path": "optional/path/in/monorepo",
"author": "Your Name",
"description": "Brief description of what your plugin does",
"dependencies": ["dependency1", "dependency2"],
"compositors": ["niri", "hyprland"],
"distro": ["any"],
"screenshot": "https://url/to/screenshot.png"
}
Plugin Field Descriptions
| Field | Required | Description |
|---|---|---|
id | Yes | Unique identifier in camelCase (e.g., worldClock). Must match your plugin.json |
name | Yes | Display name. Must match your plugin.json |
capabilities | Yes | Array like ["dankbar-widget"] |
category | Yes | One of: monitoring, utilities, appearance, system, etc. |
repo | Yes | Full GitHub URL to your plugin repository |
path | No | Subdirectory path if plugin is in a monorepo |
author | Yes | Your name or GitHub username |
description | Yes | Clear, concise description of the plugin's purpose |
dependencies | Yes | Array of dependencies, use [] if none |
compositors | Yes | Supported compositors: ["niri", "hyprland"], ["any"] |
distro | Yes | Supported distributions: ["any"], ["fedora"], ["arch"], etc. |
screenshot | No | Direct URL to a screenshot image |
i18n | No | true once approved for central translation — see Plugin Translations. Not for initial submissions |
The id and name fields must exactly match the corresponding fields in your plugin repository's plugin.json file.
- Validate your plugin locally:
python3 .github/generate.py --validate
python3 .github/validate_links.py
- Submit a Pull Request
Plugin Feedback & Ranking
When your plugin is merged, a tracking issue is automatically opened for it in the registry. This issue is the plugin's home for feedback:
-
Upvoting — anyone can give the issue a 👍 reaction. The plugin directory ranks plugins by upvotes, so reactions directly affect visibility.
-
Status — maintainers flag plugins by commenting commands on the issue, shown as badges in the directory:
Command Badge /broken//workingMarks (or clears) Broken /unmaintainedMarks Unmaintained /deprecatedMarks Deprecated /review//unreviewMarks (or clears) Reviewed /similar #<issue> [#<issue> ...]//unsimilar #<issue>Links (or unlinks) related plugins Moderators can't
/reviewor/unreviewa plugin they authored — only Owners can.Plugin authors can run
/unmaintainedand/deprecatedon their own plugin without being a moderator. Use/unmaintainedwhen you're looking for a new maintainer, and/deprecatedwhen the plugin is superseded by another plugin or a built-in DMS feature. Other commands remain moderator-only./similarreferences one or more plugin tracking issues by number (e.g./similar #530or/similar #403 #411) and links them to this plugin both ways — each issue lists the others under Related plugins, and the directory and DMS surface the relationship. Use/unsimilar #<issue>to remove a link.
The directory links to each plugin's issue from its Discuss button.
Plugin Translations
Any plugin can ship its own translations — a translations/ directory with one JSON file per locale, loaded by DMS automatically. No approval needed, no registry involvement. See Translations in the development guide for the file format and the I18n.trFor API.
On top of that, registry plugins can apply to join the central DMS POEditor project — the same one community translators use for DMS itself, currently covering 21 languages. Approved plugins get their strings translated alongside the shell, and finished translations come back to the plugin repo as PRs.
Before applying:
- Your plugin is listed in this registry and actively maintained
- Every user-facing string goes through
I18n.trFor("<your plugin id>", ...), with the id as a literal string exactly matching theidin yourplugin.json— the extraction tooling reads call sites, so a variable there means your strings never get picked up
Applying:
- Open a PR setting
"i18n": truein your plugin's registry JSON. Include a short note: what the plugin does, roughly how many strings - On approval, a maintainer adds your repo to the translation sync. Your English strings get uploaded to POEditor, tagged with your plugin id
- As translators finish languages, you get PRs adding
translations/<locale>.jsonfiles to your repo — merge them and the translations ship with your next plugin update
Once your strings are in POEditor, renaming a term is a delete-plus-add — the old term's translations across every language are discarded. Keep English strings stable.
Contributing a Theme
How to Add Your Theme
-
Fork the repository
- Go to AvengeMedia/dms-plugin-registry and click Fork
-
Create a new folder in the
themes/directory:themes/{theme-id}/theme.json- Use lowercase letters and hyphens for the folder name
- Examples:
tokyonight/,gruvbox-dark/,catppuccin-mocha/
-
Create your
theme.jsonwith this schema:
{
"id": "themeId",
"name": "Theme Name",
"version": "1.0.0",
"author": "Your Name",
"description": "Brief description of your theme",
"dark": {
"primary": "#7aa2f7",
"primaryText": "#16161e",
"primaryContainer": "#7dcfff",
"secondary": "#bb9af7",
"surface": "#1a1b26",
"surfaceText": "#73daca",
"surfaceVariant": "#2f3549",
"surfaceVariantText": "#cbccd1",
"surfaceTint": "#7aa2f7",
"background": "#16161e",
"backgroundText": "#d5d6db",
"outline": "#787c99",
"surfaceContainerLowest": "#121319",
"surfaceContainerLow": "#262c3c",
"surfaceContainer": "#2f3549",
"surfaceContainerHigh": "#444b6a",
"error": "#f7768e",
"warning": "#ff9e64",
"info": "#7dcfff"
},
"light": {
"primary": "#2e7de9",
"primaryText": "#d0d5e3",
"primaryContainer": "#007197",
"secondary": "#9854f1",
"surface": "#e1e2e7",
"surfaceText": "#387068",
"surfaceVariant": "#c4c8da",
"surfaceVariantText": "#1a1b26",
"surfaceTint": "#2e7de9",
"background": "#cbccd1",
"backgroundText": "#1a1b26",
"outline": "#4c505e",
"surfaceContainerLowest": "#fefeff",
"surfaceContainerLow": "#fcfcff",
"surfaceContainer": "#dfe0e5",
"surfaceContainerHigh": "#9699a3",
"error": "#f52a65",
"warning": "#b15c00",
"info": "#007197"
}
}
Theme Metadata Fields
| Field | Required | Description |
|---|---|---|
id | Yes | Unique identifier in camelCase (e.g., tokyoNight, gruvboxDark) |
name | Yes | Display name of your theme |
version | Yes | Semver version (e.g., 1.0.0) |
author | Yes | Your name or username |
description | Yes | Brief description of the theme |
Theme Color Fields
Both dark and light objects require these color properties:
| Field | Description |
|---|---|
primary | Primary accent color |
primaryText | Text color on primary backgrounds |
primaryContainer | Container using primary color |
secondary | Secondary accent color |
surface | Main surface/card background |
surfaceText | Text on surfaces |
surfaceVariant | Alternative surface color |
surfaceVariantText | Text on variant surfaces |
surfaceTint | Tint overlay color |
background | App background color |
backgroundText | Text on background (matugen-only — see note) |
outline | Border/divider color |
surfaceContainerLowest | Lowest elevation container (darkest in dark mode, lightest in light mode) (matugen-only — see note) |
surfaceContainerLow | Low elevation container, between surface and surfaceContainer (matugen-only — see note) |
surfaceContainer | Container background |
surfaceContainerHigh | Elevated container background |
error | Error state color |
warning | Warning state color |
info | Info state color |
:::note Not all colors are used by DMS itself
surfaceContainerLowest, surfaceContainerLow, and backgroundText are not rendered by
DankMaterialShell's own UI. They complete the Material palette and are exported to matugen
templates (VS Code, KDE, Firefox, Zed, etc.), so external apps themed via DMS use them. They
are still required for a valid theme — pick sensible values that fit your palette.
:::
For more details on how these colors are used, see Custom Themes.
- Validate your theme locally:
python3 .github/validate_themes.py
python3 .github/generate.py --validate
- Submit a Pull Request
- Commit only your
theme.jsonfile (previews are auto-generated) - A preview will be generated and posted as a comment on your PR
- After merge, the preview SVG will be committed automatically
- Commit only your
Guidelines
For Plugins
- Keep descriptions concise and informative
- Ensure your repository has proper documentation
- Test that your plugin works with the specified compositors and distros
- Include a screenshot when possible
For Themes
- All color values must be 6-digit hex codes (e.g.,
#7aa2f7) - Both
darkandlightvariants are required - The
idmust be camelCase (starts lowercase, alphanumeric only) - Version must follow semver format (
X.Y.Z) - Test your colors for readability and contrast
Questions?
If you have questions about the contribution process, please open an issue in the registry repository.