Skip to content

Installation ​

Catnip ships on Signicat’s internal GitLab npm registry and on Signicat’s CDN.

  • npm — For Signicat developers and CI with registry access. Use with a bundler (Vue, React, Vite, webpack). Packages are scoped @signicat/catnip-*.
  • CDN — For anyone with a browser: plain HTML, server-rendered apps, or teams without npm registry access. Production: static.signicat.com/catnip/. Development: static.signicat.dev/catnip/.

Packages are not on the public npm registry today. If you cannot configure the GitLab registry and authenticate, use the CDN — not npm install.

npm ​

Packages are on Signicat’s GitLab registry — configure @signicat before the first install. See Registry.

Components ​

Install @signicat/catnip-components together with @signicat/catnip-css. Components inject their own shadow DOM styles, but they read --catnip-* design tokens (colors, typography, spacing, and so on) from the page. @signicat/catnip-css supplies those variables plus base styles and utilities — without it, components register but will not look correct.

bash
npm install @signicat/catnip-components @signicat/catnip-css
# or
pnpm add @signicat/catnip-components @signicat/catnip-css
# or
yarn add @signicat/catnip-components @signicat/catnip-css

Import both at your app entry point:

js
import "@signicat/catnip-components";
import "@signicat/catnip-css";

Peer dependencies: vue (when using Vue).

Vue compiler ​

Tell Vue that catnip-* tags are custom elements. Without this, the compiler treats them as Vue components (Failed to resolve component: catnip-button).

Vite (vite.config.ts):

ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag.startsWith("catnip-")
        }
      }
    })
  ]
});

Nuxt (nuxt.config.ts):

ts
export default defineNuxtConfig({
  vue: {
    compilerOptions: {
      isCustomElement: (tag) => tag.startsWith("catnip-")
    }
  }
});

Then bind reactive / non-literal values with the leading-dot shorthand (.modelValue, .disabled). See Component API — Vue 3 and Quickstart.

TypeScript ​

Importing @signicat/catnip-components registers the tags and types window.Catnip. Add this to an env.d.ts (or equivalent) in the app:

ts
/// <reference types="@signicat/catnip-components" />

Vue template types still come from isCustomElement above — Catnip hosts are native custom elements, not Vue SFCs. For React, use @signicat/catnip-components-react: generated wrappers include prop and event types.

Editor autocomplete ​

The package ships a VS Code HTML custom data file generated from the Custom Elements Manifest. Point the editor at it so catnip-* tags and kebab-case attributes complete in HTML / Vue templates:

json
{
  "html.customData": ["./node_modules/@signicat/catnip-components/dist/html-custom-data.json"]
}

The same file is published on this docs host as /html-custom-data.json (and the manifest as /custom-elements.json). After install you can also import @signicat/catnip-components/html-custom-data.json and @signicat/catnip-components/custom-elements.json.

React ​

For a normal React application, install the wrapper and CSS packages:

bash
pnpm add @signicat/catnip-components-react @signicat/catnip-css

The default React entry depends on @signicat/catnip-components, starts custom-element registration only in the browser, and is safe to import during SSR. A child micro-frontend whose shell already owns Catnip must import @signicat/catnip-components-react/wrappers instead; that entry does not register another component runtime. See the complete React guide.

Package entry points ​

EntryImportUse case
Default@signicat/catnip-componentsStandard ESM/UMD; use with Vue, design tokens, etc.
FOUC prevention@signicat/catnip-components/foucPrevention.min.cssHides catnip-* elements until they are registered; include before component CSS
Machine API@signicat/catnip-components/custom-elements.jsonCustom Elements Manifest (tags, attributes, events, slots)
HTML editor data@signicat/catnip-components/html-custom-data.jsonVS Code / Cursor html.customData
Agent skill@signicat/catnip-components/SKILL.mdOffline copy of the agent skill

Icons and graphics loading ​

catnip-icon and catnip-graphic download each SVG the first time its name is used, then reuse it for every element on the page. To skip that first request for SVGs visible on first load, preload them at startup:

js
import { preloadIcons, preloadGraphics } from "@signicat/catnip-components";

preloadIcons(["home", "settings"]);
preloadGraphics(["hero/onboarding"]);

Micro-frontend remotes call window.Catnip.preloadIcons / window.Catnip.preloadGraphics instead.

Design Tokens ​

bash
npm install @signicat/catnip-design-tokens

Usually not needed separately if you already import @signicat/catnip-css — that package bundles design tokens. Install tokens on their own only when you want the CSS or JS token files without the full Catnip CSS bundle.

CSS Utilities ​

bash
npm install @signicat/catnip-css

Required alongside @signicat/catnip-components for correctly styled components (see Components). Also provides typography/spacing utilities, grid, and icons CSS.

Icons ​

bash
npm install @signicat/catnip-icons

Registry ​

Catnip packages are published to the Signicat GitLab npm registry only — they are not on npmjs.com or otherwise publicly installable without Signicat credentials.

Inside Signicat (apps, CI, developers with access), configure npm and authenticate:

bash
npm config set @signicat:registry https://gitlab.com/api/v4/projects/75004529/packages/npm/

For authenticated access, use a GitLab personal access token or CI_JOB_TOKEN in CI.

Outside Signicat (or without registry access), you cannot run npm install @signicat/catnip-*. Use the CDN instead — every release mirrors dist/ to static.signicat.com/catnip/ (and static.signicat.dev/catnip/ for dev).

Public npm planned

Publishing to the public npm registry is planned for the future. When that happens, external teams may also use npm install; until then, CDN is the supported path without GitLab access.

One instance (micro-frontends) ​

catnip-* tags register once per document on window.customElements. The first import that runs registration wins; a second copy does not give you a second library. @signicat/catnip-css is the same: tokens and utilities belong on the host document.

This applies to npm and CDN.

Shell / root app — install and import @signicat/catnip-components and @signicat/catnip-css at the application entry (or load the CDN standalone script and CSS once). That mount also publishes JS APIs on window.Catnip (first write wins).

Child micro-frontends — do not import another component runtime or global CSS. The elements are already defined. Use <catnip-button> directly, or React children can import @signicat/catnip-components-react/wrappers for adapters that do not register components. For i18n, config, and helpers, call the host instance — do not import @signicat/catnip-components:

js
// Shell entry — mount once
import "@signicat/catnip-components";
import "@signicat/catnip-css";
html
<!-- Remote — tags work without a second install -->
<catnip-button appearance="primary">Save</catnip-button>
tsx
// React remote — wrappers only; the shell still owns registration and CSS
import { CatnipButton } from "@signicat/catnip-components-react/wrappers";
js
// Remote — same window as the shell (after the shell has mounted Catnip)
window.Catnip.version; // e.g. "1.0.0" — the shell’s mounted library
window.Catnip.registerTranslate((key) => i18n.global.t(key));
window.Catnip.configure({ automaticTypeConversion: true });
const value = window.Catnip.parseEmitDetail(event);

A second bundled copy skips re-defining tags, but its registerTranslate / CatnipConfig are a dead copy and will not affect the mounted components. See Configuration.

Versioning ​

The shell owns the Catnip version. When the root upgrades @signicat/catnip-components / @signicat/catnip-css (or the CDN URL), every remote on that document runs that version. There is no per-MFE component version. Remotes can read window.Catnip.version to see which @signicat/catnip-components build the shell mounted.

Remotes must stay API-compliant with the shell’s version: markup, props, events, slots, and window.Catnip calls have to match what the shell actually mounted.

Bug fixes and patches are the easy path: one shell bump ships the fix to all remotes at once. Prefer that over forked copies in child apps.

Breaking changes are costly in this model. A breaking Catnip release cannot land in the shell until all consuming remotes have been updated. Library authors should treat breaking API changes as last resort; consumers should plan coordinated upgrades across the shell and remotes, not independent version pins.

CDN ​

Every @signicat/catnip-* package is mirrored to the CDN on each release. Load stylesheets with <link> tags. For components without a bundler, use the standalone IIFE (one script tag). The ES build is also on the CDN for advanced setups with an import map.

CDN hosts and URL pattern ​

EnvironmentBase URL
Productionhttps://static.signicat.com/catnip/
Developmenthttps://static.signicat.dev/catnip/

Each package is deployed under its monorepo folder name:

{base}{package}/{version}/{file}
{base}{package}/latest/{file}

Examples (production):

https://static.signicat.com/catnip/components/latest/catnip-components.standalone.js
https://static.signicat.com/catnip/css/0.0.13/styles.css
https://static.signicat.com/catnip/icons/latest/catnip-icons.min.css
Path segmentPackagenpm name
components/Web Components@signicat/catnip-components
components-react/React wrappers@signicat/catnip-components-react
css/Base styles and utilities@signicat/catnip-css
design-tokens/CSS variables and JS tokens@signicat/catnip-design-tokens
icons/Icon webfont and SVG map@signicat/catnip-icons
assets/Fonts, illustrations, flags, logos@signicat/catnip-assets

Versioned vs latest

  • {package}/{version}/ — immutable for that release. Prefer this in production so upgrades are explicit.
  • {package}/latest/ — always points at the newest release. Convenient for prototypes; pin a version when you ship.

Components ​

The standalone IIFE bundles Vue, all catnip-* custom elements, and lazy-loaded icon/illustration SVG maps. You do not need npm, a bundler, a separate Vue import, or an import map.

catnip-components.standalone.js is not on npm (it is built in CI and deployed to the CDN only). The ES/UMD builds on npm expect a bundler.

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- Design tokens + icon webfont + Inter + utilities (required for styled components) -->
    <link rel="stylesheet" href="https://static.signicat.com/catnip/css/latest/styles.css" />
    <!-- Optional: hide catnip-* tags until the components are registered -->
    <link rel="stylesheet" href="https://static.signicat.com/catnip/components/latest/foucPrevention.min.css" />
  </head>
  <body>
    <catnip-button appearance="primary">Save</catnip-button>
    <catnip-icon name="tick" size="32"></catnip-icon>

    <script src="https://static.signicat.com/catnip/components/latest/catnip-components.standalone.js" defer></script>
  </body>
</html>

Script tag, not module

The standalone build is an IIFE assigned to the global CatnipComponents. Use a classic <script src="…" defer> — not type="module".

The standalone script injects component styles (layout, states, and so on). You still need @signicat/catnip-css on the page (via the <link> tags above) so --catnip-* tokens resolve — see CSS, tokens, and icons — CDN.

Versioned URLs (EndUI-style) ​

Pin a release the same way EndUI did with version in the path:

html
<script src="https://static.signicat.dev/catnip/components/0.0.31/catnip-components.standalone.js" defer></script>

Use latest/ only for prototypes; ship with {version}/ in production.

Why not catnip-components.umd.js with one script tag? ​

Catnip also publishes catnip-components.es.js and catnip-components.umd.js on the CDN (same files as npm). A single script tag like EndUI’s endui-components.umd.js is not equivalent today:

FileOne <script>Notes
catnip-components.standalone.js✅ RecommendedIIFE; Vue + icon/illustration maps inlined
catnip-components.umd.js⚠️ PartialClassic <script defer> (not type="module"); expects the SVG loader modules as globals (CatnipIconsSvg, CatnipAssetsIllustrations, CatnipAssetsCountryFlags)
catnip-components.es.js❌ Incomplete aloneImports the SVG loader modules by bare specifier, so it needs an import map to load

EndUI’s bundle was self-contained under one URL. Catnip’s standalone build is the same idea; umd.js / es.js are the slimmer npm-oriented builds.

Advanced: ES module + import map ​

If you prefer catnip-components.es.js, map lazy SVG entry points with an import map (Vue is already bundled in the ES file):

html
<script type="importmap">
  {
    "imports": {
      "@signicat/catnip-icons/svg": "https://static.signicat.com/catnip/icons/latest/svg-map.mjs",
      "@signicat/catnip-assets/illustrations/svg": "https://static.signicat.com/catnip/assets/latest/illustrations-svg.mjs",
      "@signicat/catnip-assets/countries": "https://static.signicat.com/catnip/assets/latest/countries/index.js",
      "@signicat/catnip-assets/countries/flags/svg": "https://static.signicat.com/catnip/assets/latest/country-flags-svg.mjs"
    }
  }
</script>
<script type="module" src="https://static.signicat.com/catnip/components/latest/catnip-components.es.js"></script>

Pin versioned CDN URLs in production. Without the import map the ES file fails to load, because it imports these loader modules directly.

CSS, tokens, and icons ​

Required with components — load @signicat/catnip-css so --catnip-* tokens, the icon webfont, Inter, and utilities are on the page. Components read these variables; the standalone script does not replace this CSS.

On CDN, styles.css is self-contained (tokens, icons, Inter with ./fonts/inter/… next to the file):

html
<link rel="stylesheet" href="https://static.signicat.com/catnip/css/latest/styles.css" />

Optional extras from the same CDN base:

NeedFile
Dark modeAlready in styles.css — set data-theme="dark" on <html> — see Theming — CDN
EndUI (whitelabel)design-tokens/latest/css/endui.css on <html>, or endui-scoped.css on a wrapper, plus data-theme="endui" — see Theming — EndUI
Global resetcss/latest/global-reset.css (load before styles.css)
Bootstrap gridcss/latest/bs-grid.css
Icon webfont onlyicons/latest/catnip-icons.min.css (when you are not loading styles.css)

See also CSS overview — CDN for how this maps to optional modules.

Assets and fonts ​

CDN css/latest/styles.css already loads Inter from css/latest/fonts/inter/. You do not need a separate @font-face block for the default Catnip typeface on CDN.

For npm, @signicat/catnip-css references Inter through @signicat/catnip-assets (a dependency); your bundler resolves the font files — no manual @font-face unless you opt out of the CSS package faces.

Illustrations, flags, and pictograms are under assets/latest/… — see Assets overview — CDN.

Configuration ​

After the standalone script loads, JS APIs are on window.Catnip (same object the shell mounted). Prefer that in micro-frontends. The IIFE also exposes named exports on CatnipComponents (an alias, not a second instance):

html
<script src="https://static.signicat.com/catnip/components/latest/catnip-components.standalone.js"></script>
<script>
  window.Catnip.configure({
    automaticTypeConversion: true,
    nativeFormBehaviour: true
  });

  window.Catnip.registerTranslate((key) => myTranslations[key] ?? key);
</script>

The script is not deferred here so window.Catnip exists when the inline script runs; an inline script placed after a defer script runs before it.

With the ES build and import map, a shell may import { CatnipConfig } in a module script — remotes should still use window.Catnip. See Configuration.

Package file reference ​

@signicat/catnip-components → components/ ​

FilePurpose
catnip-components.standalone.jsCDN-only IIFE — recommended without a bundler
catnip-components.es.jsESM build (CDN: needs import map for SVG maps; npm: use with bundler)
catnip-components.umd.jsUMD build (needs bundler or global Vue)
foucPrevention.min.cssHide catnip-* until they are registered
style.cssComponent stylesheet (usually not needed with standalone)
custom-elements.jsonCustom Elements Manifest for tooling
html-custom-data.jsonVS Code / Cursor HTML custom data (html.customData)
SKILL.mdAgent skill (also at this docs host /skills/catnip/SKILL.md)

@signicat/catnip-css → css/ ​

FilePurpose
styles.cssCDN main bundle (inlined tokens + icons, Inter via ./fonts/inter/…)
fonts/inter/…Inter files for CDN styles.css (not in the npm tarball)
catnip-icons.woff2 / .woff / .ttfIcon font files for CDN (not in the npm tarball)
global-reset.cssOptional CSS reset
bs-grid.cssOptional Bootstrap grid

npm installs styles.npm.css (@import for design-tokens + icons; Inter via @signicat/catnip-assets).

@signicat/catnip-design-tokens → design-tokens/ ​

FilePurpose
css/default.cssLight theme CSS variables on :root
css/dark.cssDark semantic overrides (with data-theme="dark")
css/endui.cssEndUI / whitelabel overrides for data-theme="endui" on <html>
css/endui-scoped.cssEndUI plus dependent tokens, for data-theme="endui" on a wrapper
js/default.js / js/dark.js / js/endui.jsToken objects for JavaScript

@signicat/catnip-icons → icons/ ​

FilePurpose
catnip-icons.min.cssIcon webfont only (also inlined into css/…/styles.css)
catnip-icons.woff2Font file (referenced by the CSS)
svg-map.mjsLazy SVG map (inlined in standalone; external in ES build)

@signicat/catnip-assets → assets/ ​

PathPurpose
fonts/inter/…Inter variable font files
illustrations-svg.mjsLazy illustration map for catnip-graphic
country-flags-svg.mjsLazy flag SVG map
countries/index.jsCountry metadata (name, code, dial_code, …)
illustrations/…Static SVG files
countries/flags/…Country flag SVGs

CDN vs npm ​

CDN (standalone)npm + bundler
Setup<script defer> + optional <link>npm install + import
VueBundled in standalonePeer dependency
Icon / illustration chunksInlined in standaloneLazy-loaded via bundler
TypeScriptNo types from CDNFull types from packages
ReactUse @signicat/catnip-components-react via npmRecommended path

Self-hosting ​

CI builds catnip-components.standalone.js with pnpm run build:standalone (after pnpm build) and uploads every package’s dist/ to GCS. You can copy dist/ from a release and serve it from your own static bucket — keep the same relative paths if you mirror multiple packages (so icon font URLs in catnip-icons.min.css keep working).

Next Steps ​

Catnip Design System by Signicat