| name | version-badge-pattern |
| description | Version badge UI showing build version, git commit, and changelog in a tooltip. Use when adding version visibility for support or debugging. Works with React, Vue, Svelte, and JS. |
| user-invocable | false |
| allowed-tools | Bash, Read, Write, Edit, Grep, Glob, TodoWrite |
| created | "2025-02-03T00:00:00.000Z" |
| modified | "2026-05-09T00:00:00.000Z" |
| reviewed | "2026-02-08T00:00:00.000Z" |
Version Badge Pattern
A reusable UI pattern for displaying application version with build metadata and recent changes.
When to Use This Skill
| Use this skill when... | Use alternative when... |
|---|
| Adding version display to app header/footer | Just need version in package.json |
| Want tooltip with changelog info | Only need static version text |
| Need accessible, keyboard-navigable version info | Building a non-interactive display |
| Implementing across React/Vue/Svelte | Using server-rendered only (no JS) |
Pattern Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ App Header v1.43.0|004ddd9 โ Trigger (always visible)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ (on hover/focus)
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Build Information โ
โ Version: 1.43.0 โ
โ Commit: 004ddd97e8... โ
โ Built: Dec 11, 10:00 โ
โ Branch: main โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Recent Changes โ
โ v1.43.0 โ
โ โจ New feature X โ
โ ๐ Fixed bug Y โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
Data Flow
CHANGELOG.md โ parse-changelog.mjs โ ENV_VAR โ Component
package.json version โโโโโโโโโโโโโโโโโโโโโโ
git commit SHA โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Build Script
Create scripts/parse-changelog.mjs:
#!/usr/bin/env node
import { readFileSync, existsSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const CHANGELOG_PATH = join(__dirname, '..', 'CHANGELOG.md');
const MAX_VERSIONS = 2;
const MAX_FEATURES = 3;
const MAX_OTHER = 2;
const CHANGE_TYPES = {
feat: { icon: 'sparkles', label: 'Feature' },
fix: { icon: 'bug', label: 'Bug Fix' },
perf: { icon: 'zap', label: 'Performance' },
breaking: { icon: 'warning', : },
: { : , : },
: { : , : },
};
() {
(!()) {
.(.([]));
;
}
content = (, );
lines = content.();
versions = [];
currentVersion = ;
( line lines) {
versionMatch = line.();
(versionMatch) {
(currentVersion) {
versions.(currentVersion);
}
(versions. >= ) ;
currentVersion = {
: versionMatch[],
: [],
: [],
: [],
};
;
}
(!currentVersion) ;
changeMatch = line.();
(changeMatch) {
[, type, description] = changeMatch;
changeType = [type.()] || .;
entry = {
: type.(),
: changeType.,
: description.(),
};
(type.() === && currentVersion.. < ) {
currentVersion..(entry);
} (type.() === && currentVersion.. < ) {
currentVersion..(entry);
} (currentVersion.. < ) {
currentVersion..(entry);
}
}
}
(currentVersion) {
versions.(currentVersion);
}
.(.(versions.(, )));
}
();
React + Tailwind + shadcn/ui Implementation
Component: components/version-badge.tsx
'use client';
import { useMemo } from 'react';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { cn } from '@/lib/utils';
interface BuildInfo {
version: string;
commit: string;
branch: string;
buildTime: string;
}
interface ChangeEntry {
type: string;
icon: string;
description: string;
}
interface VersionEntry {
version: string;
features: ChangeEntry[];
fixes: ChangeEntry[];
other: ChangeEntry[];
}
const ICON_MAP: Record<string, string> = {
sparkles: 'โจ',
bug: '๐',
zap: 'โก',
warning: ,
: ,
: ,
};
(): {
[iconName] || ;
}
() {
buildInfo = useMemo< | >( {
{
raw = process..;
raw ? .(raw) : ;
} {
;
}
}, []);
changelog = useMemo<[]>( {
{
raw = process..;
raw ? .(raw) : [];
} {
[];
}
}, []);
(!buildInfo?. || buildInfo. === ) {
;
}
shortCommit = buildInfo.?.(, ) || ;
formattedDate = buildInfo.
? (buildInfo.).(, {
: ,
: ,
: ,
: ,
: ,
: ,
})
: ;
(
</>
);
}
Next.js Config: next.config.mjs
import { execSync } from 'child_process';
function getBuildInfo() {
const version = process.env.npm_package_version || 'dev';
const commit = process.env.VERCEL_GIT_COMMIT_SHA
|| process.env.GITHUB_SHA
|| execSyncSafe('git rev-parse HEAD')
|| 'local';
const branch = process.env.VERCEL_GIT_COMMIT_REF
|| process.env.GITHUB_REF_NAME
|| execSyncSafe('git branch --show-current')
|| 'local';
return { version, commit, branch, buildTime: new Date().toISOString() };
}
function execSyncSafe(cmd) {
try {
return execSync(cmd, { encoding: 'utf-8' }).trim();
} catch {
return null;
}
}
function getChangelog() {
try {
return execSync('node scripts/parse-changelog.mjs', { : }).();
} {
;
}
}
nextConfig = {
: {
: .(()),
: (),
},
};
nextConfig;
For Vue 3, Svelte, and plain CSS implementations, as well as accessibility checklist, see REFERENCE.md.
Agentic Optimizations
| Context | Action |
|---|
| Quick implementation | Use /components:version-badge command |
| Check compatibility | /components:version-badge --check-only |
| Custom placement | /components:version-badge --location footer |
Quick Reference
| Framework | Env Prefix | Config File |
|---|
| Next.js | NEXT_PUBLIC_ | next.config.mjs |
| Nuxt | NUXT_PUBLIC_ | nuxt.config.ts |
| Vite | VITE_ | vite.config.ts |
| SvelteKit | PUBLIC_ | svelte.config.js |
| CRA | REACT_APP_ | N/A (eject or craco) |