Lumeo

dotnet new Templates

Lumeo ships a NuGet package of dotnet new templates — one full Blazor WebAssembly app starter plus item templates for pages, forms, and components — so you can scaffold projects that follow the conventions in these docs without copy-pasting boilerplate. The package is called Lumeo.Templates.

Install

Install the templates globally on your machine:

dotnet new install Lumeo.Templates

After install, dotnet new list lumeo lists the five templates below. To remove them, run dotnet new uninstall Lumeo.Templates.

Template Short name Kind
Lumeo Blazor WASM App lumeo-app project
Lumeo Full-Stack App lumeo-fullstack project
Lumeo Page lumeo-page item
Lumeo Form lumeo-form item
Lumeo Component lumeo-component item

lumeo-app

Scaffolds a complete Blazor WebAssembly app that boots styled and dark-mode-ready with zero manual setup. There is no Tailwind build and no asset copying — the prebuilt CSS/JS ship inside the Lumeo NuGet package and are linked straight from _content/Lumeo/.

Command

dotnet new lumeo-app -n MyApp cd MyApp dotnet run

What you get

  • AddLumeo() wired in Program.cs; the OKLCH default (Zinc) theme + all dark-mode variables from lumeo.css.
  • A collapsible Sidebar app shell — a 64 px icon rail with centred pills and collapsed-state tooltips — plus a working dark-mode toggle (Ctrl+B collapses the rail).
  • Five pages, including the Microsoft-template bridge: Counter and Weather are the pages you know from the standard Blazor template, rebuilt with Lumeo (a Button/Badge/Select counter; a sortable DataGrid forecast with a loading skeleton). Plus Home (KPI cards + a DataGrid), Form (a validated <Form>), and Settings (Tabs + inputs).
  • Icons from the built-in LumeoIcons set — no separate icon package.
  • A README explaining the three ownership paths: NuGet, CLI vendoring, and a NuGet-free eject.

References Lumeo and Lumeo.DataGrid at the current lockstep version.

Authentication (--auth)

Like the Microsoft Individual Accounts templates, lumeo-app scaffolds an auth story via a choice option — dotnet new lumeo-app --auth <value>. All three variants share one seam: a single AuthenticationStateProvider behind the Blazor authorization primitives (<AuthorizeView>, [Authorize], <AuthorizeRouteView>, <RedirectToLogin>).

--auth What you get
demo
default
A full auth UI — /login, /register, /forgot-password built from Lumeo's auth blocks in a full-screen auth layout — backed by an in-browser localStorage provider. No backend: any email + any password ≥ 6 chars signs in. The whole app is protected and the sidebar footer shows the signed-in user with a Profile / Sign-out dropdown.
none No authentication — the original starter with public pages and a static sidebar user card.
oidc Real OIDC/OAuth wiring — Microsoft.AspNetCore.Components.WebAssembly.Authentication + AddOidcAuthentication + a RemoteAuthenticatorView route styled inside the same Lumeo auth layout. Configure your authority in wwwroot/appsettings.json.

The demo variant is the showcase path; its swap seam (the AuthenticationStateProvider) and pointers to real providers (OIDC, an ASP.NET Core Identity API, Auth0 / Entra) are documented in the generated project's README.md under “Demo auth — swap the provider”.

lumeo-fullstack

Where lumeo-app --auth demo is a client with a fake backend, lumeo-fullstack is the real thing — a two-project solution pairing the same polished Lumeo shell with an actual API, database, and email, wired together with docker-compose.

Command

dotnet new lumeo-fullstack -n MyApp cd MyApp docker compose up -d --build # app :8081 · API/Scalar :8080 · MailHog :8025

What you get

  • MyApp.Api — ASP.NET Core Identity via MapIdentityApi (register / login / refresh / confirm-email / 2FA), EF Core + PostgreSQL (Npgsql, auto-migrated on startup in Development), a Scalar OpenAPI reference at /scalar, an IEmailSender sending real SMTP to MailHog, CORS, /health, and a seeded /api/orders endpoint.
  • MyApp.Client — the lumeo-app shell, but auth talks to the real Identity endpoints (bearer token + silent refresh); register triggers a confirmation email and a "check your inbox" state, login is blocked until the email is confirmed, and the dashboard grid loads live /api/orders with loading + error states.
  • Email confirmation is required (RequireConfirmedEmail = true), so the MailHog sign-up flow is real end to end.
  • A docker-compose.yml (Postgres + MailHog + API + nginx-served client) and a .env for every port and credential — plus a documented hybrid dev loop (compose up postgres mailhog + dotnet run both apps).

Design picks

Decision Choice
Token vs cookie Bearer — the cleanest cross-origin WASM flow; the provider silently refreshes before falling back to anonymous.
Client serving nginx proxy (same-origin, no CORS) in Docker; CORS for the two-origin hybrid loop.
Auth seam The same single AuthenticationStateProvider as lumeo-app — swap it for OIDC / Auth0 / Entra without touching the UI.

The generated project's README.md documents the quickstart URLs, the hybrid loop, changing ports via .env, and migration notes.

lumeo-page

Scaffolds a new .razor page with an @page directive, a Container + Stack layout, a Heading + Lumeo.Text header, and a starter Card with buttons.

Command

dotnet new lumeo-page --name Dashboard --route dashboard

Produces Dashboard.razor

@page "/dashboard" <PageTitle>Dashboard</PageTitle> <Container MaxWidth="5xl"> <Stack Gap="6" Class="py-8"> <Stack Gap="2"> <Heading Level="1" Size="3xl">Dashboard</Heading> <Lumeo.Text Size="base" Color="muted"> Replace this with your page description. </Lumeo.Text> </Stack> <Card> <CardHeader><Heading Level="3" Size="lg">Get started</Heading></CardHeader> <CardContent> <Button Variant="Button.ButtonVariant.Default" OnClick="HandleClick">Click me</Button> </CardContent> </Card> </Stack> </Container>

Parameters

Name Description Default
--name Page class + file name (PascalCase). NewPage
--route URL route, without leading slash. new-page

lumeo-form

Scaffolds a POCO annotated with [LumeoForm] plus a page that renders it. The generated RenderForm wires a Lumeo <Form> to the built-in DataAnnotationsFormValidator, so an invalid submit shows per-field errors automatically. See the [LumeoForm] Generator for the full type → component mapping.

Command

dotnet new lumeo-form --ModelName Feedback --PageName FeedbackPage --route feedback

Produces FeedbackModel.cs

using System.ComponentModel.DataAnnotations; using Lumeo; [LumeoForm(Title = "Feedback", SubmitLabel = "Submit")] public partial class FeedbackModel { [Required(ErrorMessage = "Name is required.")] [StringLength(80, MinimumLength = 2)] [Display(Name = "Name", Description = "Your full name.")] public string Name { get; set; } = string.Empty; [Required(ErrorMessage = "Email is required.")] [DataType(DataType.EmailAddress)] [Display(Name = "Email", Description = "We'll never share your address.")] public string Email { get; set; } = string.Empty; [StringLength(2000, ErrorMessage = "Message must be 2000 characters or fewer.")] [Display(Name = "Message")] public string? Message { get; set; } }

The generated FeedbackPage.razor renders it with @FeedbackModel.RenderForm(_model, …). Prefer a hand-laid-out form? Delete the [LumeoForm] attribute and compose <Form> + <FormField> yourself.

Parameters

Name Description Default
--ModelName Model class + file name (PascalCase). ContactForm
--PageName Page class + file name (PascalCase). ContactFormPage
--route Page route, without leading slash. contact

lumeo-component

Scaffolds a reusable .razor component following the Lumeo contract — an explicit @namespace, a Class parameter, an AdditionalAttributes splat, and Variant / Size / Disabled parameters flowing through a class-merging builder.

Command

dotnet new lumeo-component --ComponentName Hero --namespace MyApp.Components

Produces Hero.razor

@namespace MyApp.Components <div class="@CssClass" @attributes="AdditionalAttributes"> @ChildContent </div> @code { [Parameter] public RenderFragment? ChildContent { get; set; } [Parameter] public HeroVariant Variant { get; set; } = HeroVariant.Default; [Parameter] public HeroSize Size { get; set; } = HeroSize.Medium; [Parameter] public bool Disabled { get; set; } [Parameter] public string? Class { get; set; } [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; } // Variant / Size switch into the CssClass builder… public enum HeroVariant { Default, Outline, Subtle } public enum HeroSize { Small, Medium, Large } }

Parameters

Name Description Default
--ComponentName Component class + file name (PascalCase). MyComponent
--namespace Target namespace. MyApp.Components