Skip to content
Merged
Show file tree
Hide file tree
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
Mar 19, 2026
89d5ebf
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
9e467d0
fix: add name type
trueberryless Mar 19, 2026
3907e95
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
8101797
feat: create parameter badge generator
trueberryless Mar 19, 2026
381114c
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
a1821ff
feat: add label formatter and make clipboard robust
trueberryless Mar 19, 2026
ffa83af
Merge branch 'main' into feature/docs-custom-badges-inputs
trueberryless Mar 19, 2026
2d41b40
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
3eff748
refactor: simplify clipboard
trueberryless Mar 20, 2026
18b79c2
fix: suggestions
trueberryless Mar 20, 2026
124dada
feat: support any value
trueberryless Mar 20, 2026
39be64f
Merge branch 'main' into feature/docs-custom-badges-inputs
trueberryless Mar 20, 2026
761b683
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 20, 2026
263bb3f
Merge remote-tracking branch 'origin/main' into feature/docs-custom-b…
ghostdevv Mar 21, 2026
706b3ac
refactor: badge types constant should be shared
ghostdevv Mar 21, 2026
cdd74d3
refactor: use text transform to capitalise
ghostdevv Mar 21, 2026
2b2deec
fix: knip
ghostdevv Mar 21, 2026
0d98502
Revert "refactor: use text transform to capitalise"
ghostdevv Mar 21, 2026
fba0dc5
refactor: typescript
ghostdevv Mar 21, 2026
850618a
refactor: reusable titleCase fn
ghostdevv Mar 21, 2026
a588ac1
Merge remote-tracking branch 'origin/main' into feature/docs-custom-b…
ghostdevv Mar 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions docs/app/components/BadgeGenerator.vue
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',
]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

watch(pkg, () => {
isValid.value = true
})
Comment thread
trueberryless marked this conversation as resolved.
Outdated

const copyToClipboard = async () => {
const markdown = `[![Open on npmx.dev](https://npmx.dev/api/registry/badge/${type.value}/${pkg.value})](https://npmx.dev/package/${pkg.value})`
await navigator.clipboard.writeText(markdown)

copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
}
Comment thread
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"
Comment thread
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>
114 changes: 0 additions & 114 deletions docs/content/2.guide/1.features.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,117 +88,3 @@ Quick access to online development environments detected from package READMEs:
| :icon{name="i-lucide:pen-tool"} [CodePen](https://codepen.io) | Social development environment for front-end |
| :icon{name="i-simple-icons-jsfiddle"} [JSFiddle](https://jsfiddle.net) | Online editor for web snippets |
| :icon{name="i-simple-icons-replit"} [Replit](https://replit.com) | Collaborative browser-based IDE |

### Custom badges

You can add custom npmx badges to your markdown files using the following syntax:

```md
[![Open on npmx.dev](https://npmx.dev/api/registry/badge/TYPE/YOUR_PACKAGE)](https://npmx.dev/package/YOUR_PACKAGE)
```

::tip
Make sure to replace `TYPE` with one of the options listed below and `YOUR_PACKAGE` with the actual package name (e.g., `vue`, `lodash`, or `@nuxt/kit`).
::

#### 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

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/version/nuxt)](https://npmx.dev/package/nuxt)

# License Badge

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/license/vue)](https://npmx.dev/package/vue)

# Monthly Downloads

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/downloads/lodash)](https://npmx.dev/package/lodash)

# Scoped Package (Install Size)

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/size/@nuxt/kit)](https://npmx.dev/package/@nuxt/kit)

# Specific Version

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/version/react/v/18.0.0)](https://npmx.dev/package/react)

# Quality Score

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/quality/pinia)](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`
112 changes: 112 additions & 0 deletions docs/content/2.guide/6.badges.md
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

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/version/nuxt)](https://npmx.dev/package/nuxt)

# License Badge

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/license/vue)](https://npmx.dev/package/vue)

# Monthly Downloads

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/downloads/lodash)](https://npmx.dev/package/lodash)

# Scoped Package (Install Size)

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/size/@nuxt/kit)](https://npmx.dev/package/@nuxt/kit)

# Specific Version

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/version/react/v/18.0.0)](https://npmx.dev/package/react)

# Quality Score

[![Open on npmx.dev](https://npmx.dev/api/registry/badge/quality/pinia)](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`
Loading