@konduktor/version-badge
v0.1.0
Published
React component that displays version + build number. Consumes @konduktor/build-info-next metadata.
Readme
@konduktor/version-badge
React components that display a version + build number in a consistent Wombat-style badge. Pairs with @konduktor/build-info-next which injects the build metadata at build time.
Two components
| Component | Use when | Positioning | Staging pill |
|-----------|----------|-------------|--------------|
| <FixedVersionBadge /> | Most projects — just drop it into your root layout | Pinned to a viewport corner | Auto-detected |
| <VersionBadge /> | Unusual placements (sidebar footer, top nav, about page) | You position it yourself | You render it yourself |
Default recommendation: use <FixedVersionBadge />. Zero config, matches the Wombat look, handles staging detection automatically.
Installation
pnpm add @konduktor/version-badge @konduktor/build-info-nextPeer dependency: react ^18 || ^19.
Usage — <FixedVersionBadge /> (recommended)
Drop it into your root layout once and forget about it:
import { FixedVersionBadge } from "@konduktor/version-badge";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<FixedVersionBadge />
</body>
</html>
);
}On a production build, it renders:
v0.23.1 · #743Pinned to the bottom-right corner in monospace gray.
On a staging / preview build, it also shows an amber "Staging" pill above the version text:
[ STAGING ]
v0.23.1 · #743Staging auto-detection
The badge shows the Staging pill when any of these are true:
process.env.NEXT_PUBLIC_APP_ENV === "staging"or"preview"process.env.NEXT_PUBLIC_APP_URLcontains"staging"process.env.NEXT_PUBLIC_VERCEL_ENV === "preview"(Vercel auto-sets this)VERCEL_ENV === "preview"(server-side Vercel)- Build number is
"0","dev", or missing (local dev fallback) - You explicitly set the
stagingHintprop
For Vercel projects, NEXT_PUBLIC_VERCEL_ENV is the cleanest signal — set it in your next.config.ts via withBuildInfo() or process.env pass-through.
Customisation
<FixedVersionBadge
corner="top-right" // bottom-right (default), bottom-left, top-right, top-left
offset={{ x: 20, y: 16 }} // distance from viewport edges in px
showStagingPill={false} // or true / "auto" (default)
stagingHint // force staging pill on regardless of env
stagingLabel="Preview Build" // custom pill text
renderStagingPill={(isStaging) => // completely custom pill node
<MyCustomPill active={isStaging} />
}
className="font-mono text-xs text-slate-400" // override the default badge text class
href="/api/health" // make badge click through to health endpoint
/>Usage — <VersionBadge /> (unusual placements)
When you need the badge inside a sidebar footer, mobile nav, or an "About" page, use the low-level primitive:
import { VersionBadge } from "@konduktor/version-badge";
export function SidebarFooter() {
return (
<div className="sidebar-footer">
<VersionBadge className="text-xs text-muted" />
</div>
);
}Renders as:
v0.23.1 · #743This is just a <span> with the label — no positioning, no staging pill. You own the placement.
Link it to your health endpoint
<VersionBadge href="/api/health" />Clicking the badge opens your health endpoint. One-click way to verify you're looking at the build you think you are.
Custom formatting
<VersionBadge prefix="build " separator=" / " />
// Renders: build 0.23.1 / 743Manual info override (for tests or static pages)
<VersionBadge info={{ version: "1.0.0", buildNumber: "42" }} />Props reference
<FixedVersionBadge />
| Prop | Type | Default | Description |
|---|---|---|---|
| corner | "bottom-right" \| "bottom-left" \| "top-right" \| "top-left" | "bottom-right" | Which viewport corner to pin to |
| offset | { x?: number; y?: number } | { x: 12, y: 8 } | Distance from edges in px |
| showStagingPill | boolean \| "auto" | "auto" | Show the Staging pill: always / never / auto-detect |
| stagingHint | boolean | — | Explicit override (useful when host app knows it's staging) |
| stagingLabel | string | "Staging" | Label inside the pill |
| renderStagingPill | (isStaging: boolean) => ReactNode | — | Fully custom pill node |
| className | string | "font-mono text-[11px] text-gray-500" | Override badge text class |
| style | CSSProperties | — | Inline style overrides on the badge text |
| Plus all VersionBadgeProps | | | prefix, separator, info, href, children |
<VersionBadge />
| Prop | Type | Default | Description |
|---|---|---|---|
| prefix | string | "v" | Prefix label before the version |
| separator | string | " · #" | Separator between version and build number |
| className | string | — | Additional className (Tailwind, CSS modules, etc.) |
| style | CSSProperties | — | Inline style overrides |
| info | object | auto from env | Manual override of build info |
| href | string | — | If provided, renders as an anchor linking to this URL |
| children | ReactNode | — | Extra content rendered next to the label |
How it gets the build info
Both components call getBuildInfo() from @konduktor/build-info-next, which reads NEXT_PUBLIC_* env vars injected at build time. Make sure you've wired withBuildInfo() into your next.config.ts:
import { withBuildInfo } from "@konduktor/build-info-next";
export default withBuildInfo({
reactStrictMode: true,
});Without that wiring, the badges render v0.0.0 · #0.
License
MIT © CryptoWombat
