Lumeo
Performance

How Lumeo stays at 0 KB

What the browser actually downloads — brotli-compressed assembly size, measured 2026-07-11 (4.2.0).

Per-package breakdown

Install only the satellites you use. Each row shows the brotli-compressed size that package adds to your published WASM app.

Lumeocore — 143 components
672 KB
Lumeo.Chartsopt-in satellite
128 KB
Lumeo.DataGridopt-in satellite
120 KB
Lumeo.Editoropt-in satellite
29 KB
Lumeo.Motionopt-in satellite
18 KB
Lumeo.Scheduleropt-in satellite
16 KB
Lumeo.Ganttopt-in satellite
12 KB

What's actually in the core .nupkg

The .nupkg contains more than what reaches the browser. Here's the full inventory.

Lumeo.dll
945 KB

Main Blazor component assembly — 3,076 KB raw IL, zip-compressed to 945 KB inside the .nupkg. The published WASM app brotli-compresses it to the 672 KB the browser actually downloads; the assembly itself is not IL-trimmed internally, so this size is the same whether you use 1 core component or all 143 (see 'What does WASM linker trimming do?' below).

Lumeo.xml
96 KB

XML documentation comments for every public API. Powers IntelliSense in Visual Studio and Rider. Never included in the WASM publish output.

components.js
65 KB

Static web asset: focus traps, scroll lock, element measurement, and third-party canvas wrappers. Automatically injected into host projects via MSBuild StaticWebAssets.

lumeo-utilities.css
35 KB

Tailwind v4 utility bundle, generated at build time from component markup. One flat CSS file — no per-component isolation scopes, no runtime injection.

lumeo.css
16 KB

Theme tokens and dark-mode variable swaps. CSS-only — switching themes is a variable swap, not a C# rebuild.

Lumeo.SourceGenerators.dll
14 KB

Roslyn analyzer and source generator for the opt-in [LumeoForm] attribute. Compile-time only — never reaches the browser.

JS utilities + package metadata
~24 KB

theme.js (5 KB), signature-pad.js (4 KB), toolbar.js (2 KB), README.md (7 KB), MSBuild .props for StaticWebAssets integration (~4 KB), icon.png + .nuspec (~2 KB). Dev-time and discovery artefacts — none reach the browser. Debug symbols ship separately as a .snupkg symbol package and are not included here.

Total: ~1,180 KB in the .nupkg — matches the NuGet "Download package" badge (~1.18 MB). The 672 KB brotli number is just the DLL, which is the only thing the WASM linker ships to the browser.

What's not in core

The dependencies we said no to.

Newtonsoft.Json
AutoMapper
ReactiveUI
Theme-provider JS
CSS-in-JS runtime
Bootstrap CSS
jQuery
MudBlazor dependency tree
Telerik runtime
Syncfusion bloat
Runtime reflection helpers
Source generators in core hot path
Newtonsoft.Json
AutoMapper
ReactiveUI
Theme-provider JS
CSS-in-JS runtime
Bootstrap CSS

How it compares

Brotli-compressed size of each library's core component DLL — managed code only (see note).

Library Core brotli size
FluentUI Blazor
302 KB
You
Lumeo (core)
672 KB
Radzen Blazor
1,003 KB
MudBlazor
1,318 KB
Telerik UI Blazor
1,480 KB

* Brotli (quality 11) of each library's core component DLL — latest stable as of June 2026, .NET 10 target (Telerik: .NET 8, its latest published build). Measured 2026-06-29 and reproducible by brotli-compressing the DLL inside each public .nupkg. This counts the managed assembly only: it excludes app-specific IL trimming (which shrinks every library in a real published app) and the JS/CSS static web assets each library ships separately — some substantial (e.g. Telerik's ~4.8 MB JS bundle, Radzen's multi-theme CSS, and Lumeo's own components.js + lumeo.css). DLL size reflects managed footprint, not features or final shipped size. Only the Lumeo row was re-measured on 2026-07-11 against 4.2.0 — 671.6 KiB (687,723 bytes) brotli of lib/net10.0/Lumeo.dll, rounded to 672 KB above; every other row remains the 2026-06-29 measurement.

Heavy features are opt-in

Don't need charts? ECharts never touches your build. Don't need a data grid? ClosedXML and QuestPDF aren't downloaded.

128 KB

Charts

Lumeo.Charts

ECharts lazy-loaded only when a chart component mounts — never included unless you reference the package.

120 KB

DataGrid

Lumeo.DataGrid

Full virtualization, group-by, and export. Since v3.7.0 the export backend (ClosedXML + QuestPDF, ~1.65 MB brotli) ships in a separate bundled DLL — opt-in lazy-load on WASM keeps it out of the first paint. Lazy setup →

29 KB

Rich Text Editor

Lumeo.Editor

TipTap JS lazy-loaded at component mount time. The DLL is only 26 KB — the heavy JS only streams when the editor renders.

Why brotli, not .nupkg?

NuGet shows ~1.18 MB for the core .nupkg — here's what that actually means.

Developer experience

Hot Reload that actually works

Six architectural choices that keep dotnet watch fast and reliable on Lumeo apps — the same choices most Blazor UI libs make differently and pay for in slow rebuilds, stale styles, or forced full-restart loops.

No Blazor CSS isolation

Lumeo styles every component via Tailwind utility classes composed directly in markup. Tailwind v4 watch mode regenerates the single utility bundle in under 100 ms; the browser swaps it without losing state.

What other libs do
Libraries that rely on Blazor's per-component .razor.css isolation generate a new scoped-class hash on every change, force the SDK to re-emit the static-web-assets manifest, and often invalidate browser caches mid-session.

Theme is CSS variables — not a C# object

Switching themes in Lumeo means swapping --color-primary, --color-background, etc. in lumeo.css. No C# rebuild needed. dotnet watch picks up the CSS change and the browser re-paints with the new tokens.

What other libs do
MudThemeProvider passes a C# MudTheme record via CascadingValue. Editing colors requires recompiling C#, which triggers a delta-rebuild and re-render of every consuming component — Hot Reload often falls back to full restart.

No source generators in the runtime hot path

Lumeo.SourceGenerators only emits code for the opt-in [LumeoForm] attribute. Normal component edits never re-run a generator, so the dotnet watch inner loop is just Roslyn incremental compile + DOM patch.

What other libs do
Libraries that wrap every component in a base-class source generator (or AOT-style codegen) re-run the generator on every keystroke — multi-second incremental builds, and Hot Reload often gives up entirely.

No reflection in the render path

DataGridColumn<T>.GetValue is a compiled Expression<Func<TItem,object?>> cached per field (rc.44). Component parameters are strongly typed records. Hot Reload can swap method bodies without invalidating any cached type-handle metadata.

What other libs do
Reflection-heavy libs (PropertyInfo.GetValue, Activator.CreateInstance in render) cache Type instances that don't refresh on Hot Reload — you get "works after restart" bugs because old reflection caches are still alive.

CascadingValue composition, not inheritance

Compound components like Select / SelectTrigger / SelectContent share state via a record passed through CascadingValue. Each Razor file is independent and Hot Reload swaps it in isolation.

What other libs do
Libs with deep inheritance (MyButton : MudFormComponent<T,U> : MudComponentBase) force the runtime to rebuild the whole class table when a base changes. Hot Reload prints "unable to apply edits" and you lose state.

Razor SDK + Tailwind watch — one CSS bundle

lumeo.css + lumeo-utilities.css are two files generated by Tailwind from your source. dotnet watch + npm run watch:css run in parallel; CSS swaps don't go through Blazor at all. No virtual-DOM diff for visual-only changes.

What other libs do
CSS-in-JS libs (or libs shipping a JS theme runtime) need to re-execute JS to recompute styles on every component touch — slower, and sometimes blocked by Blazor's circuit lifecycle.
The net effect

Edit a Razor component → DOM patches in ~120 ms. Edit lumeo.css or a theme variable → CSS swaps in ~50 ms with zero C# rebuild. Edit a Lumeo source-of-truth record (e.g. DataGridColumn<T>) → delta build + DOM patch in under a second. No "Hot Reload not supported, restarting" spinner on the inner loop.

See it for yourself

Add Lumeo to a project, publish it, and measure. We believe the numbers.