Lumeo

Vendor a component

The Lumeo NuGet gives you every component for free — but sometimes you want to own the source. The lumeo CLI copies a component's .razor file straight into your project — rewritten to your namespace, yours to edit — exactly the way shadcn/ui does for React. This guide takes a brand-new Blazor project from zero to a vendored, editable Button.

Before you start

Install the CLI as a global dotnet tool. It exposes a single command, lumeo.

dotnet tool install -g Lumeo.Cli
lumeo --help

This walkthrough assumes a fresh Blazor WebAssembly app that already references the Lumeo NuGet (<PackageReference Include="Lumeo" />). That is the default, recommended setup — the package ships the CSS tokens, utility classes and JS interop the vendored source needs, so there is nothing extra to wire up. (No Lumeo package? See Go fully standalone, which vendors the runtime too.)

Step 1 — Initialize

From your project root, run lumeo init. It walks up looking for a .csproj, detects the Lumeo package, and writes a lumeo.json. The namespace is auto-derived from your project (<AssemblyName>.Components); pass --namespace / --path to override, or -y to accept every default without prompts.

$ lumeo init
Lumeo NuGet detected - no extra CSS/JS setup needed.

OK Wrote lumeo.json
  namespace       VendorDemo.Components
  componentsPath  Components/Ui
  registry        https://lumeo.nativ.sh/registry.json

Next: lumeo add button

The resulting lumeo.json is the CLI's memory of your project — where components land, which registry to pull from, and which components are installed at what version.

{
  "namespace": "VendorDemo.Components",
  "componentsPath": "Components/Ui",
  "registry": "https://lumeo.nativ.sh/registry.json",
  "components": {},
  "standalone": false
}

Step 2 — Add a component

lumeo add button fetches Button.razor from the registry, rewrites its @namespace to yours, and writes it under your components path. Dependencies are resolved automatically — Button pulls in Spinner for its loading state — and the tool records every install in lumeo.json.

$ lumeo add button
  +   Components\Ui\Button\Button.razor
  +   Components\Ui\Spinner\Spinner.razor

OK Added Button (+1 dep) - 2 files written to Components/Ui/

CSS variables used:
  --color-accent, --color-accent-foreground, --color-background, --color-destructive,
  --color-destructive-foreground, --color-input, --color-primary, --color-primary-foreground,
  --color-ring, --color-secondary, --color-secondary-foreground, --radius

What landed where

Each component becomes a folder under Components/Ui/ (your configured componentsPath). The .gitkeep and README.md are seeded by init.

Components/Ui/
├─ .gitkeep
├─ README.md
├─ Button/
│  └─ Button.razor
└─ Spinner/
   └─ Spinner.razor

The very first line of the vendored file proves the rebrand — it is your namespace now, not Lumeo:

@namespace VendorDemo.Components
@implements IAsyncDisposable
@inject Lumeo.Services.IComponentInteropService Interop

Reference it like any local component — bring the namespace into _Imports.razor once, then use the tag:

@using VendorDemo.Components

<Button Variant="Button.ButtonVariant.Primary">Save</Button>

Inspect before you write

Every mutating command has a look-first mode, so nothing is a surprise:

Command What it does
lumeo list List every available component grouped by category. Filter with --category Forms.
lumeo view button Print the component's source to stdout without writing anything.
lumeo add button --dry-run Show which files would be written — no changes made.
lumeo info Print project state: config paths, registry, and every installed component with its version.

If a file already exists, add prompts [o]verwrite  [s]kip  [d]iff  [a]ll-overwrite  [A]bort. For non-interactive runs use --force (overwrite all) or --skip-existing.

Staying current: diff & update

Because you own the file, updates are opt-in. Two commands keep you in control:

  • lumeo diff button — compare your files against the registry version. A freshly vendored component is in sync.
  • lumeo update button — pull upstream changes (prompts before touching anything). Add --check for a CI-friendly drift report (exit 1 on drift), or omit the name to update everything installed.
$ lumeo diff button

Button: 1 in sync, 0 drifted, 0 missing.

Once you start editing the vendored source, diff becomes your drift radar — that is the subject of the next guide.

See also