@makashif/brand
| Install | |
|---|---|
npm install @makashif/brand |
|
| Latest Version: | 1.0.15 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Aug 28, 2026 |
| Links: | GitHub · npm |
@makashif/brand
One identity, every surface. An interactive DevTools console signature, a live on-page brand card, and an ANSI terminal banner — from a single config.
npm i @makashif/brand
That is the whole setup. A postinstall hook detects your framework and wires itself in — it prints exactly what it did, and never touches anything twice.
| Stack | What gets wired | How |
|---|---|---|
| Next.js | instrumentation-client.ts + instrumentation.ts |
new files |
| Nuxt | plugins/brand.client.ts |
new file |
| SvelteKit | src/hooks.client.ts |
new file |
| Astro | astro.config.mjs → integrations: [brand()] |
injected, then verified |
| Vite / React / Vue SPA | one import at the top of your app entry | prepended |
| Express / Node / HTML | prints the one line to add | nothing written |
Not automatic enough, or you skipped install scripts? Same thing, on demand:
npx @makashif/brand init
How the automatic wiring stays safe
Writing to someone's project during an install deserves real caution, so this is deliberately narrow:
- It only ever creates a new file, prepends one import, or edits a config whose result still parses. Config edits are verified with
node --checkand rolled back if they don't. A TypeScript config is never machine-edited —node --checkcan't validate TS, and an unverifiable rewrite of a build config isn't worth the risk, so you get the two lines to paste instead. - It never overwrites. An existing file is reported and left alone; running it again is a no-op.
- It never fails your install. Every path exits 0 — a cosmetic feature must not break
npm install. - It skips CI, so no surprise diffs in a pipeline.
- It skips transitive installs. If another package depends on this one, your project is not touched.
- It tells you how to undo it on every run.
Opt out any of three ways:
MAKASHIF_BRAND_SKIP=1 npm i @makashif/brand
npm i @makashif/brand --ignore-scripts
{ "makashifBrand": { "autowire": false } }
One honest limitation:
postinstallruns in your terminal, not a browser. It can't print to a visitor's console directly — what it does is write the file that makes your app load the branding on every page. And--ignore-scripts, which many teams set globally, skips it entirely;npx @makashif/brand initis the fallback.
Or wire it by hand
One side-effect import, anywhere in your entry:
import '@makashif/brand/auto';
Or drive it explicitly:
import { brand } from '@makashif/brand';
brand();
In a browser that prints the console signature; in Node it prints the terminal banner. Same call — the package routes itself through the node export condition.
What you get
| Surface | Where | What it does |
|---|---|---|
| Console signature | Browser DevTools | Gradient badges, an SVG monogram, collapsible sections, a sortable capability table, live GPU/paint telemetry, and a makashif.* namespace you can drive by hand |
| Brand card | On the page | A self-contained Shadow DOM card with a live FPS meter, expandable disciplines, copy-to-clipboard and a hire button |
| Terminal banner | Node, Express, CI | A truecolor box that sizes itself to its content, honours NO_COLOR, and ships Express/Fastify/Koa middleware |
Automatic, per stack
Each of these is the whole integration — no component to render, no layout to edit. npx @makashif/brand init sets it up for you.
| Stack | File / config | Loaded by |
|---|---|---|
| Next.js | instrumentation-client.ts → import '@makashif/brand/auto' |
Next, on every page before hydration |
| Nuxt | plugins/brand.client.ts |
Nuxt auto-registers plugins/ |
| SvelteKit | src/hooks.client.ts → import '@makashif/brand/auto' |
SvelteKit, on every route |
| Astro | integrations: [brand()] from /astro-integration |
injected into every page |
| Vite (any SPA) | plugins: [brand()] from /vite |
injected into index.html |
| Express | app.use(brandMiddleware()) |
your server entry |
// astro.config.mjs
import brand from '@makashif/brand/astro-integration';
export default defineConfig({ integrations: [brand()] });
// vite.config.ts
import brand from '@makashif/brand/vite';
export default defineConfig({ plugins: [brand()] });
Explicit, per stack
When you want the card in a specific place, or control over where the signature prints.
Next.js / React
// The adapter carries its own 'use client' boundary — a Server Component can
// import it directly, no wrapper file needed.
import { ConsoleBrand, BrandCard } from '@makashif/brand/react';
export default function Layout({ children }) {
return (
<body>
<ConsoleBrand /> {/* renders no DOM */}
{children}
<BrandCard variant="badge" scheme="auto" />
</body>
);
}
Add instrumentation.ts to brand your server boot too:
export async function register() {
const { brand } = await import('@makashif/brand');
brand();
}
Astro
---
import Brand from '@makashif/brand/astro';
---
<Brand variant="badge" scheme="auto" />
Nuxt / Vue
<script setup>
import { ConsoleBrand, BrandCard } from '@makashif/brand/vue';
</script>
<template>
<ConsoleBrand />
<BrandCard variant="badge" />
</template>
Or install both globally:
// plugins/brand.client.ts
import BrandPlugin from '@makashif/brand/vue';
export default defineNuxtPlugin((nuxt) => nuxt.vueApp.use(BrandPlugin));
SvelteKit
<script>
import { brandCard, consoleBrand } from '@makashif/brand/svelte';
consoleBrand();
</script>
<div use:brandCard={{ variant: 'badge' }}></div>
Node / Express / Fastify / Koa
import express from 'express';
import { brandMiddleware } from '@makashif/brand/express';
const app = express();
app.use(brandMiddleware()); // banner on first request + X-Designed-By header
import { brand, brandBanner } from '@makashif/brand/node';
brand(); // print it
const text = brandBanner({ color: false }); // or capture it for a logger
Angular, Solid, Qwik, Rails, Laravel, WordPress, plain HTML
<script type="module">import '@makashif/brand/element';</script>
<brand-card variant="badge"></brand-card>
Or with no build step and no install at all:
<div data-brand></div>
<script src="https://unpkg.com/@makashif/brand"></script>
Make it yours
Every field is optional and overridable — the defaults are just one identity.
brand({
name: 'Your Name',
tagline: 'Designer · Developer',
monogram: 'Y',
links: { portfolio: 'https://example.com', github: '…', email: 'you@example.com' },
chips: ['Svelte', 'Rust', 'WebGPU'],
capabilities: [{ discipline: 'Systems', focus: 'Rust · WASM', level: 'Expert' }],
theme: { brand: '#f43f5e', info: '#f59e0b' },
api: 'me', // → window.me instead of window.makashif
});
The console namespace
Every member is a getter, so no parentheses are needed — and because DevTools shows accessors as click-to-invoke, merely expanding the object never fires a side effect.
Click to run
The banner (and makashif.help) logs a command object you can drive with the mouse:
makashif commands {visit: (…), code: (…), hire: (…), copy: (…), help: (…)}
Expand it and click any (…) — DevTools evaluates the accessor, which runs the command. No typing.
This is the only real click-to-execute mechanism a console has: styled %c text cannot carry a click handler, and no API exists to give it one. Accessor evaluation is the genuine article, and each entry delegates to the same getter on the namespace, so a click and a typed makashif.visit run one code path rather than two that can drift apart.
makashif.help makashif.runtime makashif.hire
makashif.whoami makashif.banner makashif.visit
makashif.stack makashif.card makashif.code
makashif.skills makashif.config makashif.copy
Options
| Option | Default | Notes |
|---|---|---|
name tagline craft domain |
shipped identity | The header block |
monogram |
'M' |
One or two characters. 'M' gets the drawn wordmark |
links |
portfolio/github/email | Any extra key renders as another row |
stack capabilities chips |
shipped content | Arrays replace, they don't merge |
theme |
violet/cyan palette | Merges over the dark defaults |
themeLight |
darkened palette | Light-mode overrides; your theme hues carry over automatically |
scheme |
'auto' |
Console palette: follows prefers-color-scheme, or force 'dark'/'light' |
version env |
auto-detected | env falls back to NODE_ENV |
logo groups telemetry |
true |
telemetry: 'only' skips stack + capabilities |
security |
'auto' |
Self-XSS warning in production only |
api / alias |
'makashif' / 'mk' |
false installs no global |
once |
true |
One print per page/process |
defer |
'load' |
'idle' or 'immediate' |
respectBots |
true |
Silent for crawlers, Lighthouse, webdriver |
variant |
'card' |
'badge' or 'floating' (card only) |
scheme |
'dark' |
'light' or 'auto' (card only) |
live |
true |
The card's FPS loop (card only) |
Built for production
- Never breaks the host app. Every console call is failure-isolated; a styling bug costs a missing line, not a white screen.
- Free at TTI. Printing waits for
load, then browser idle. Paint metrics are populated by then, so telemetry reads real numbers. - Degrades honestly. Chromium gets gradients, padded badges and the monogram; Firefox/Safari get colour only; anything else gets clean plaintext.
- Readable in both console themes.
%cstyles accept no media queries, so a fixed palette means invisible text for half your users. The scheme is resolved at print time and the whole palette swapped — hues included, since#06b6d4cyan on white is about 2:1 contrast. Every line clears WCAG AA in both: measured 4.76:1 minimum on light, 3.5:1 on dark. - No style collisions. The card lives in a shadow root, so your CSS reset and its styles cannot reach each other.
- Quiet for robots. Silent when
navigator.webdriveris set, so Lighthouse audits stay clean. - Battery-aware. The card's FPS loop only runs while the card is actually on screen and the tab is visible.
- SSR-safe. Without a DOM every browser entry no-ops instead of throwing.
- Idempotent. Immune to React StrictMode double-mounts and Fast Refresh.
CLI
npx @makashif/brand # print the terminal banner
npx @makashif/brand init # wire it up automatically — no app-code edits
npx @makashif/brand add # scaffold a component (framework auto-detected)
npx @makashif/brand snippet # print it, write nothing
npx @makashif/brand info # resolved paths, versions, exports
init never overwrites an existing file — run it as many times as you like.
License
MIT © Muhammad Makashif
Related Packages
Flexible passkey authentication for Astro, SvelteKit, NextJS and other framework...
Headless devtools that let a coding agent read and change the state of an open w...
Accessible (WCAG 2.2 AA / ATAG 2.0), RTL-first, CSP-safe rich text editor for an...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.0.15 | >=3.3 | MIT | |
| 1.0.13 | >=3.3 | MIT | |
| 1.0.12 | >=3.3 | MIT | |
| 1.0.11 | >=3.3 | MIT | |
| 1.0.10 | >=3.3 | MIT | |
| 1.0.9 | >=3.3 | MIT | |
| 1.0.8 | >=3.3 | MIT | |
| 1.0.7 | >=3.3 | MIT | |
| 1.0.6 | >=3.3 | MIT | |
| 1.0.5 | >=3.3 | MIT | |
| 1.0.4 | >=3.3 | MIT | |
| 1.0.3 | >=3.3 | MIT | |
| 1.0.2 | >=3.3 | MIT | |
| 1.0.1 | >=3.3 | MIT | |
| 1.0.0 | >=3.3 | MIT |