Getting Started
Using the brand assets
@nexub/brand ships the official Nexub files: the mark, the app icon tiles, PNG icons and the favicon. Use these instead of keeping your own copies. They come from the same master artwork as <Logo>; nothing is redrawn.
pnpm add @nexub/brandWhat's in the package
| File | Use it for |
|---|---|
nexub-mark.svg | The mark in brand colours. |
nexub-mark-mono.svg | Single-colour mark (fill="currentColor"). |
app-icon.svg | App icon: the black glass tile with the mark. SVG favicon, launcher tiles. |
app-icon-192.png, app-icon-512.png | Web manifest icons, apple-touch-icon. |
app-icon-account.svg, -192.png, -512.png | The Account tile: same tile, person glyph. |
favicon.ico | 16, 32 and 48 px favicon. |
Every file is at @nexub/brand/<file>. Inside React UI, prefer <Logo> and <NexubMark>: they render the same mark inline, with no extra request.
Why a separate package: the files are static and need no build, so an app that only wants a favicon doesn't install React, and the version still moves in lockstep with the other @nexub/* packages.
Vite: import from code
Importing a file gives you a hashed URL, and Vite copies the file into the build.
import hubIcon from '@nexub/brand/app-icon.svg';
import accountIcon from '@nexub/brand/app-icon-account.svg';
<AppLauncher apps={[
{ id: 'hub', name: 'Command Hub', href: 'https://hub.nexub.ai', icon: hubIcon },
{ id: 'account', name: 'Account', href: 'https://account.nexub.ai', icon: accountIcon, current: true },
]} />Vite inlines imports under 4 KB as data: URLs. img-src 'self' data: allows that; if your policy has no data:, see Strict CSP.
Vite: copy into public/
index.html and the web manifest need fixed URLs, so copy the files into public/brand/ before dev and build. Add public/brand/ to .gitignore: it's build output, not a copy you maintain.
// package.json
"scripts": {
"brand": "node -e \"require('fs').cpSync('node_modules/@nexub/brand/assets', 'public/brand', { recursive: true })\"",
"predev": "pnpm brand",
"prebuild": "pnpm brand"
}<!-- index.html -->
<link rel="icon" href="/brand/favicon.ico" sizes="48x48" />
<link rel="icon" href="/brand/app-icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/brand/app-icon-192.png" />
<link rel="manifest" href="/manifest.webmanifest" />Web manifest
// public/manifest.webmanifest
{
"name": "Nexub Command Hub",
"short_name": "Command Hub",
"icons": [
{ "src": "/brand/app-icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/brand/app-icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}For the Account app, use the app-icon-account* files in these places.
Plain static serving
With no bundler, copy the files next to your HTML in your deploy step (the same cpSync line, with your output folder, e.g. dist/brand) and reference them as /brand/<file>. Self-hosted files are same-origin, so a strict img-src 'self' needs no change.
A tile for another product
Every product uses the same tile with its own glyph; don't edit the tile. In the nexub-ds repo:
- Draw the glyph as an SVG fragment in the 512 × 512 tile space and save it as
packages/brand/glyphs/<product>.svg. Keep it inside roughly x/y 90–422, where the mark sits. Put gradients in a<defs>withid="glyph"(seeglyphs/account.svg). - Add
{ id: '<product>', glyph: read('glyphs/<product>.svg'), halo: '<hex>' }toPRODUCTSinpackages/brand/scripts/build-assets.mjs.halotints the glow behind the glyph. - Run
pnpm --filter @nexub/brand build:assets, commitassets/app-icon-<product>*, and release. The tile then ships as@nexub/brand/app-icon-<product>.svgplus 192 and 512 px PNGs.