Skip to content
nexubDesign System
v2.4.0

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/brand

What's in the package

FileUse it for
nexub-mark.svgThe mark in brand colours.
nexub-mark-mono.svgSingle-colour mark (fill="currentColor").
app-icon.svgApp icon: the black glass tile with the mark. SVG favicon, launcher tiles.
app-icon-192.png, app-icon-512.pngWeb manifest icons, apple-touch-icon.
app-icon-account.svg, -192.png, -512.pngThe Account tile: same tile, person glyph.
favicon.ico16, 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:

  1. 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> with id="glyph" (see glyphs/account.svg).
  2. Add { id: '<product>', glyph: read('glyphs/<product>.svg'), halo: '<hex>' } to PRODUCTS in packages/brand/scripts/build-assets.mjs. halo tints the glow behind the glyph.
  3. Run pnpm --filter @nexub/brand build:assets, commit assets/app-icon-<product>*, and release. The tile then ships as @nexub/brand/app-icon-<product>.svg plus 192 and 512 px PNGs.