Lumeo

Customize a vendored component

Vendoring is only worth it if you actually change the source. Once a component lives in your project it is a plain .razor file — edit it like any other. This guide edits a vendored Button, shows how lumeo diff surfaces the drift, and how to pull upstream changes without silently clobbering your edits.

Picking up from Vendor a component: you have Components/Ui/Button/Button.razor and a clean lumeo diff button.

Step 1 — Edit the source

Say your design language calls for pill-shaped, heavier-weight buttons. Open Button.razor and change the base classes — swap rounded-md for rounded-full and font-medium for font-semibold:

// Components/Ui/Button/Button.razor
- private const string BaseClasses = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ...";
+ private const string BaseClasses = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-semibold ...";

That is it. No re-registration, no build step, no fork to maintain — the file is yours. It compiles against the Lumeo package's runtime exactly as before.

Step 2 — See the drift

lumeo diff button compares every file of the component against the registry version and summarizes what moved. Your edited file now reports as drifted:

$ lumeo diff button
  drift   Components\Ui\Button\Button.razor

Button: 0 in sync, 1 drifted, 0 missing.
Run lumeo update button to pull upstream, or lumeo add button --force to reset.

To see the drift line-by-line, run lumeo add button --diff. It prints a unified diff and writes nothing — - is your local file, + is the registry version:

$ lumeo add button --diff
  diff    Components\Ui\Button\Button.razor
  ...
      private string LinkCssClass => Cx.Merge(CssClass, Cx.When(IsLoading || Disabled, "pointer-events-none opacity-50"));

-     private const string BaseClasses = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-semibold transition-colors ...";
+     private const string BaseClasses = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors ...";

      private string? PressEffectClass => PressEffect switch
  ...
  ok      Components\Ui\Spinner\Spinner.razor

PREVIEW Added Button (+1 dep) - 0 files written to Components/Ui/

Step 3 — Update without losing changes

When Lumeo ships a Button fix upstream, you decide whether and how to take it. Nothing is ever overwritten silently.

Check for drift in CI

lumeo update button --check reports drift and exits 1 if any file differs — perfect for a pipeline gate.

$ lumeo update button --check
Button
  drift   Components\Ui\Button\Button.razor

Drift: 1 file(s) differ from registry.
# exit code 1

Take upstream interactively

lumeo update button stops on every drifted file and asks what to do — so your edit is never lost by default:

$ lumeo update button
Button

Components\Ui\Button\Button.razor has upstream changes.
  [o]verwrite  [s]kip  [d]iff:
  • [d]iff — review the change first, then choose.
  • [s]kip — keep your file untouched (the safe default for a customized component).
  • [o]verwrite — take the upstream version, discarding your edit.

The reconcile workflow

There is no auto-merge — you own the file, so you own the merge. The dependable pattern for a component you have customized:

  1. Run lumeo add button --diff to read exactly what upstream changed.
  2. With your edit committed to git, [o]verwrite to land the upstream version, then let git diff replay your customization on top — or re-apply the one or two lines by hand.
  3. Or, if your change and theirs do not overlap, [s]kip and cherry-pick their hunk manually.

To throw your edits away and snap back to the pristine registry version, use lumeo update button --force-reset (or lumeo add button --force). Both replace your file wholesale — reach for them only when you want the reset.

Rules of thumb

  • Commit the vendored files to git before editing — your version history is the real safety net.
  • Keep customizations small and localized; the smaller your diff, the cleaner every future update.
  • Run lumeo update --check in CI to get told when upstream moves, on your schedule.

See also