This site provides a machine-readable index at /llms.txt.

Skip to main content Skip to navigation

Drop a Razor component into a markdown page

To place a Razor component tag — <Badge>, <Card>, or one of your own — directly inside a .md file instead of authoring raw HTML, write the tag where CommonMark allows an HTML block. Mdazor matches the tag against the registered component types, binds attribute values to [Parameter] properties by case-insensitive name, and renders inner content through the markdown pipeline. To author a brand-new component from scratch, see Author a custom Razor component for markdown.

Assumptions

  • A working Pennington site that renders markdown (see Create your first Pennington site if not).
  • The host calls AddDocSite, AddBlogSite, or AddPennington. The first two register seven of the eight Pennington.UI components automatically (everything but CodeBlock, which is Razor-page-only); bare AddPennington requires the one-line registration shown under "Register components on a bare host" below.
  • Component tag names start with an uppercase letter and match the Razor component type name — case-sensitive on the leading character (<Card>, not <card>).

The seven built-in components

AddDocSite and AddBlogSite pre-register <Badge>, <BigTable>, <Card>, <CardGrid>, <LinkCard>, <Step>, and <Steps>. Each H3 below shows the source markdown above the rendered output for the most common authoring shapes.

Inline a built-in tag

Place the tag anywhere CommonMark allows an HTML block. Attribute values bind to [Parameter] properties by case-insensitive name match.

<Badge>Preview</Badge>

Preview

Pass markdown as ChildContent

Whatever appears between the open and close tags becomes the component's ChildContent render fragment and is parsed as markdown — **bold**, links, and nested components all work inside the body.

<Card Title="What's new">
The **v2 pipeline** ships with [unified dev and build](xref:explanation.core.dev-vs-build).
</Card>

What

The v2 pipeline ships with unified dev and build.

Bind primitive attributes

Only primitive parameter types (strings, numbers, booleans) bind from markdown attributes — the value arrives as a raw string and Mdazor converts it via reflection. For complex data, pack it into a delimited string and parse inside the component, or use ChildContent for rich content.

<Card Title="Fast" Href="xref:explanation.core.dev-vs-build" Variant="primary">
Pages render in a single SSR pass.
</Card>

Fast

Pages render in a single SSR pass.

Register components on a bare host

AddPennington wires the component registry via AddMdazor() but does not register any components — that falls to the AddDocSite and AddBlogSite templates. Chain one AddMdazorComponent<T>() call per component that should be available in markdown.

using DocSiteKitchenSinkExample.Components;
using Mdazor;
using Pennington.DocSite;
  
var builder = WebApplication.CreateBuilder(args);
  
// Kitchen-sink DocSite host. The configuration surface is deliberately wide —
// two areas, two locales, a custom color scheme, font preloads, extra CSS,
// a bespoke Mdazor component, a custom footer, and a GitHub URL — so each
// how-to page can `xmldocid,bodyonly` fence into one of the small helper
// methods on `ServiceConfiguration` to show exactly the surface that how-to
// teaches.
builder.Services.AddDocSite(DocSiteKitchenSinkExample.ServiceConfiguration.BuildDocSiteOptions);
  
// Register the custom Mdazor component used by `Content/main/ui-components-in-markdown.md`.
// `AddMdazorComponent<T>()` is the one DI line needed — Mdazor's registry
// discovers the tag at markdown render time.
builder.Services.AddMdazorComponent<FeatureCallout>();
  
var app = builder.Build();
  
app.UseDocSite();
  
await app.RunDocSiteAsync(args);

For the shape DocSite uses internally, see the Mdazor chain under Content components.

What the renderer emits

Mdazor parses the component tag out of the HTML block, instantiates the matching Razor component, binds attribute values to [Parameter] properties, and renders the result inline — the original <Badge> (or other tag) literal disappears from the output. If the tag does not match a registered component on a bare AddPennington host, it falls through unchanged and renders as literal text, which is the fastest way to confirm whether the registration is what activates a tag.