-
-
Notifications
You must be signed in to change notification settings - Fork 433
feat(docs): add custom badge generator #2152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ghostdevv
merged 22 commits into
npmx-dev:main
from
trueberryless:feature/docs-custom-badges-inputs
Mar 21, 2026
Merged
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
c062ad6
feat(docs): add custom badge generator
89d5ebf
[autofix.ci] apply automated fixes
autofix-ci[bot] 9e467d0
fix: add name type
trueberryless 3907e95
[autofix.ci] apply automated fixes
autofix-ci[bot] 8101797
feat: create parameter badge generator
trueberryless 381114c
[autofix.ci] apply automated fixes
autofix-ci[bot] a1821ff
feat: add label formatter and make clipboard robust
trueberryless ffa83af
Merge branch 'main' into feature/docs-custom-badges-inputs
trueberryless 2d41b40
[autofix.ci] apply automated fixes
autofix-ci[bot] 3eff748
refactor: simplify clipboard
trueberryless 18b79c2
fix: suggestions
trueberryless 124dada
feat: support any value
trueberryless 39be64f
Merge branch 'main' into feature/docs-custom-badges-inputs
trueberryless 761b683
[autofix.ci] apply automated fixes
autofix-ci[bot] 263bb3f
Merge remote-tracking branch 'origin/main' into feature/docs-custom-b…
ghostdevv 706b3ac
refactor: badge types constant should be shared
ghostdevv cdd74d3
refactor: use text transform to capitalise
ghostdevv 2b2deec
fix: knip
ghostdevv 0d98502
Revert "refactor: use text transform to capitalise"
ghostdevv fba0dc5
refactor: typescript
ghostdevv 850618a
refactor: reusable titleCase fn
ghostdevv a588ac1
Merge remote-tracking branch 'origin/main' into feature/docs-custom-b…
ghostdevv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| <script setup> | ||
| const pkg = useState('badge-pkg', () => 'nuxt') | ||
| const type = useState('badge-type', () => 'version') | ||
| const isValid = ref(true) | ||
| const copied = ref(false) | ||
|
|
||
| const types = [ | ||
| 'version', | ||
| 'license', | ||
| 'size', | ||
| 'downloads', | ||
| 'downloads-day', | ||
| 'downloads-week', | ||
| 'downloads-month', | ||
| 'downloads-year', | ||
| 'vulnerabilities', | ||
| 'dependencies', | ||
| 'created', | ||
| 'updated', | ||
| 'engines', | ||
| 'types', | ||
| 'maintainers', | ||
| 'deprecated', | ||
| 'quality', | ||
| 'popularity', | ||
| 'maintenance', | ||
| 'score', | ||
| 'name', | ||
| ] | ||
|
|
||
| watch(pkg, () => { | ||
| isValid.value = true | ||
| }) | ||
|
trueberryless marked this conversation as resolved.
Outdated
|
||
|
|
||
| const copyToClipboard = async () => { | ||
| const markdown = `[](https://npmx.dev/package/${pkg.value})` | ||
| await navigator.clipboard.writeText(markdown) | ||
|
|
||
| copied.value = true | ||
| setTimeout(() => { | ||
| copied.value = false | ||
| }, 2000) | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| </script> | ||
|
|
||
| <template> | ||
| <div | ||
| class="my-8 p-5 rounded-xl border border-gray-200/60 dark:border-white/5 bg-gray-50/50 dark:bg-white/[0.02] flex flex-col sm:flex-row items-end gap-4" | ||
| > | ||
| <div class="flex flex-col gap-1.5 flex-1 w-full"> | ||
| <label class="text-[11px] font-bold uppercase tracking-wider text-gray-400 ml-1" | ||
| >Package Name</label | ||
| > | ||
| <input | ||
| v-model="pkg" | ||
| type="text" | ||
| spellcheck="false" | ||
| class="w-full h-[42px] px-4 py-2 rounded-lg border border-gray-200 dark:border-white/10 bg-white dark:bg-black/20 focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none text-sm transition-all" | ||
| :class="{ 'border-red-500/50 focus:ring-red-500/10 focus:border-red-500': !isValid }" | ||
| placeholder="e.g. nuxt" | ||
| /> | ||
| </div> | ||
|
|
||
| <div class="flex flex-col gap-1.5 flex-1 w-full"> | ||
| <label class="text-[11px] font-bold uppercase tracking-wider text-gray-400 ml-1" | ||
| >Badge Type</label | ||
| > | ||
| <div class="relative"> | ||
| <select | ||
| v-model="type" | ||
| class="w-full h-[42px] px-4 py-2 rounded-lg border border-gray-200 dark:border-white/10 bg-white dark:bg-black/20 focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none text-sm transition-all appearance-none cursor-pointer" | ||
| > | ||
| <option v-for="t in types" :key="t" :value="t" class="dark:bg-gray-900">{{ t }}</option> | ||
| </select> | ||
| <span | ||
| class="absolute right-3 top-1/2 -translate-y-1/2 i-lucide-chevron-down w-4 h-4 text-gray-400 pointer-events-none" | ||
| /> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div class="flex flex-col gap-1.5 flex-2 w-full"> | ||
| <label class="text-[11px] font-bold uppercase tracking-wider text-gray-400 ml-1" | ||
| >Preview & Action</label | ||
| > | ||
| <div | ||
| class="flex items-center bg-white dark:bg-black/20 border border-gray-200 dark:border-white/10 rounded-lg h-[42px] overflow-hidden" | ||
| > | ||
| <div | ||
| class="flex-1 flex items-center justify-center px-3 border-r border-gray-200 dark:border-white/10 h-full bg-gray-50/50 dark:bg-transparent" | ||
| > | ||
| <img | ||
| v-if="isValid" | ||
| :src="`https://npmx.dev/api/registry/badge/${type}/${pkg}`" | ||
| class="h-[20px]" | ||
| alt="Badge Preview" | ||
| @error="isValid = false" | ||
| /> | ||
| <span v-else class="text-[10px] font-bold text-red-500 uppercase tracking-tighter" | ||
| >Invalid</span | ||
| > | ||
| </div> | ||
|
|
||
| <button | ||
| @click="copyToClipboard" | ||
| :disabled="!isValid" | ||
|
trueberryless marked this conversation as resolved.
Outdated
|
||
| class="px-4 h-full text-[11px] font-bold uppercase tracking-widest transition-all disabled:opacity-20 disabled:cursor-not-allowed min-w-[85px] hover:bg-gray-50 dark:hover:bg-white/5" | ||
| :class=" | ||
| copied | ||
| ? 'text-emerald-500 bg-emerald-50/50 dark:bg-emerald-500/10' | ||
| : 'text-gray-500 dark:text-gray-400' | ||
| " | ||
| > | ||
| {{ copied ? 'Done!' : 'Copy' }} | ||
| </button> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </template> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| --- | ||
| title: Badges | ||
| description: Generate modern markdown badges with the npmx.dev API | ||
| navigation: | ||
| icon: i-lucide:badge | ||
| --- | ||
|
|
||
| npmx.dev offers many different SVG badges with stats about any package via its API. You can get the Markdown code to display an accessible badge which links to the package URL on npmx.dev with the following interactive generator: | ||
|
|
||
| :badge-generator | ||
|
|
||
| ## Available Badge Types | ||
|
|
||
| - **version**: Shows the latest or specific version of the package. :img{src="https://img.shields.io/badge/%233b82f6-3b82f6" class="inline align-middle h-5 w-14"} | ||
| - **license**: Displays the package license (e.g., MIT, Apache-2.0). :img{src="https://img.shields.io/badge/%2322c55e-22c55e" class="inline align-middle h-5 w-14"} | ||
| - **size**: Shows the install size (via Bundlephobia) or unpacked size. :img{src="https://img.shields.io/badge/%23a855f7-a855f7" class="inline align-middle h-5 w-14"} | ||
| - **downloads**: Displays monthly download statistics. :img{src="https://img.shields.io/badge/%23f97316-f97316" class="inline align-middle h-5 w-14"} | ||
| - **downloads-day**: Displays daily download statistics. :img{src="https://img.shields.io/badge/%23f97316-f97316" class="inline align-middle h-5 w-14"} | ||
| - **downloads-week**: Displays weekly download statistics. :img{src="https://img.shields.io/badge/%23f97316-f97316" class="inline align-middle h-5 w-14"} | ||
| - **downloads-month**: Alias for monthly download statistics. :img{src="https://img.shields.io/badge/%23f97316-f97316" class="inline align-middle h-5 w-14"} | ||
| - **downloads-year**: Displays yearly download statistics. :img{src="https://img.shields.io/badge/%23f97316-f97316" class="inline align-middle h-5 w-14"} | ||
| - **vulnerabilities**: Shows the number of vulnerabilities found via OSV. :img{src="https://img.shields.io/badge/%2322c55e-22c55e" class="inline align-middle h-5 w-14"} / :img{src="https://img.shields.io/badge/%23ef4444-ef4444" class="inline align-middle h-5 w-14"} | ||
| - **dependencies**: Lists the total count of package dependencies. :img{src="https://img.shields.io/badge/%2306b6d4-06b6d4" class="inline align-middle h-5 w-14"} | ||
| - **created**: Displays the date the package was first published. :img{src="https://img.shields.io/badge/%2364748b-64748b" class="inline align-middle h-5 w-14"} | ||
| - **updated**: Displays the date of the most recent modification. :img{src="https://img.shields.io/badge/%2364748b-64748b" class="inline align-middle h-5 w-14"} | ||
| - **engines**: Shows the supported Node.js version range. :img{src="https://img.shields.io/badge/%23eab308-eab308" class="inline align-middle h-5 w-14"} | ||
| - **types**: Indicates if TypeScript types are included. :img{src="https://img.shields.io/badge/%233b82f6-3b82f6" class="inline align-middle h-5 w-14"} / :img{src="https://img.shields.io/badge/%2364748b-64748b" class="inline align-middle h-5 w-14"} | ||
| - **maintainers**: Displays the total count of package maintainers. :img{src="https://img.shields.io/badge/%2306b6d4-06b6d4" class="inline align-middle h-5 w-14"} | ||
| - **deprecated**: Shows if the package is active or deprecated. :img{src="https://img.shields.io/badge/%2322c55e-22c55e" class="inline align-middle h-5 w-14"} / :img{src="https://img.shields.io/badge/%23ef4444-ef4444" class="inline align-middle h-5 w-14"} | ||
| - **quality**: NPMS.io quality score based on linting and tests. :img{src="https://img.shields.io/badge/%23a855f7-a855f7" class="inline align-middle h-5 w-14"} | ||
| - **popularity**: NPMS.io popularity score based on downloads and stars. :img{src="https://img.shields.io/badge/%2306b6d4-06b6d4" class="inline align-middle h-5 w-14"} | ||
| - **maintenance**: NPMS.io maintenance score based on activity. :img{src="https://img.shields.io/badge/%23eab308-eab308" class="inline align-middle h-5 w-14"} | ||
| - **score**: The overall NPMS.io combined score. :img{src="https://img.shields.io/badge/%233b82f6-3b82f6" class="inline align-middle h-5 w-14"} | ||
| - **name**: Simple badge displaying the package name. :img{src="https://img.shields.io/badge/%2364748b-64748b" class="inline align-middle h-5 w-14"} | ||
|
|
||
| ## Examples | ||
|
|
||
| ```md | ||
| # Version Badge | ||
|
|
||
| [](https://npmx.dev/package/nuxt) | ||
|
|
||
| # License Badge | ||
|
|
||
| [](https://npmx.dev/package/vue) | ||
|
|
||
| # Monthly Downloads | ||
|
|
||
| [](https://npmx.dev/package/lodash) | ||
|
|
||
| # Scoped Package (Install Size) | ||
|
|
||
| [](https://npmx.dev/package/@nuxt/kit) | ||
|
|
||
| # Specific Version | ||
|
|
||
| [](https://npmx.dev/package/react) | ||
|
|
||
| # Quality Score | ||
|
|
||
| [](https://npmx.dev/package/pinia) | ||
| ``` | ||
|
|
||
| ## Customization Parameters | ||
|
|
||
| You can further customize your badges by appending query parameters to the badge URL. | ||
|
|
||
| ### `labelColor` | ||
|
|
||
| Overrides the default label color. You can pass a standard hex code (with or without the `#` prefix). The label text color is automatically chosen (black or white) based on WCAG contrast ratio, so the badge remains readable. | ||
|
|
||
| - **Default**: `#0a0a0a` | ||
| - **Usage**: `?labelColor=HEX_CODE` | ||
|
|
||
| ### `label` | ||
|
|
||
| Overrides the default label text. You can pass any string to customize the label displayed on the badge. | ||
|
|
||
| - **Default**: Depends on the badge type (e.g., "version", "downloads/mo"). | ||
| - **Usage**: `?label=YOUR_LABEL` | ||
|
|
||
| ### `color` | ||
|
|
||
| Overrides the default strategy color. You can pass a standard hex code (with or without the `#` prefix). The text color is automatically chosen (black or white) based on WCAG contrast ratio, so the badge remains readable. | ||
|
|
||
| - **Default**: Depends on the badge type (e.g., version is blue, downloads are orange). | ||
| - **Usage**: `?color=HEX_CODE` | ||
|
|
||
| | Example | URL | | ||
| | :------------- | :------------------------------------ | | ||
| | **Hot Pink** | `.../badge/version/nuxt?color=ff69b4` | | ||
| | **Pure Black** | `.../badge/version/nuxt?color=000000` | | ||
| | **Brand Blue** | `.../badge/version/nuxt?color=3b82f6` | | ||
|
|
||
| ### `name` | ||
|
|
||
| When set to `true`, this parameter replaces the static category label (like "version" or "downloads/mo") with the actual name of the package. This is useful for brand-focused READMEs. | ||
|
|
||
| - **Default**: `false` | ||
| - **Usage**: `?name=true` | ||
|
|
||
| | Type | Default Label | With `name=true` | | ||
| | ------------- | -------------------- | ---------------- | | ||
| | **Version** | `version \| 3.12.0` | `nuxt \| 3.12.0` | | ||
| | **Downloads** | `downloads/mo \| 2M` | `lodash \| 2M` | | ||
|
|
||
| ### `style` | ||
|
|
||
| Overrides the default badge appearance. Pass `shieldsio` to use the shields.io-compatible style. | ||
|
|
||
| - **Default**: `default` | ||
| - **Usage**: `?style=shieldsio` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.