Curiosity

INodeRenderer recipe

Source: 05_NodeRenderer/ · take over node rendering for a custom node type — define a schema, register it with the workspace, and implement INodeRenderer for the cards / preview / detail page.

Files

File Responsibility
RecipeBookSchema.cs Compile-time constants for the node type and its fields. Mirrors the auto-generated Schema.cs you'd get from Manage → Interface → Download template.
NodeRendererSchema.cs Creates the schema on the workspace at startup via Mosaik.API.Schemas.Create(...). Admin-only — the call is a no-op for everyone else.
RecipeBookRenderer.cs The INodeRenderer implementation. Mosaik discovers it automatically via App.AutoDiscoverViews().
NodeRendererView.cs The recipe's landing page — explains the wiring and shows a live SearchArea filtered to RecipeBook.

The schema-creation flow

The HTTP call that creates a schema used to live inline inside Mosaik.FrontEnd.Admin/.../SchemaEditor.cs:

await REQ.New("schema").WithBody(schema).PutAsync();

It has been moved to Mosaik.FrontEnd.API so any front-end can call it:

// Mosaik.FrontEnd.API/API.Schemas.cs
public static async Task Create(SchemaDefinition schema)
    => await REQ.New("schema").WithBody(schema).PutAsync();

SchemaEditor.cs now calls API.Schemas.Create(schema) directly, and so does this recipe:

await Mosaik.API.Schemas.Create(new SchemaDefinition(name, type, key, fields));

The recipe gates the call behind CurrentUser.IsAdmin — non-admins still see existing nodes rendered, the schema just isn't auto-provisioned for them.

The renderer contract

INodeRenderer is three methods:

public interface INodeRenderer : INodeStyle
{
    CardContent       CompactView(Node node);
    Task<CardContent> PreviewAsync(Node node, Parameters parameters);
    Task<IComponent>  ViewAsync(Node node, Parameters parameters);
}
Method Where it shows up
CompactView Search results, dense lists, the side panel. Keep this tight.
PreviewAsync The modal that opens when a user clicks "Quick look" on a card.
ViewAsync The dedicated detail page when the user navigates to the node directly.

In this recipe, PreviewAsync and ViewAsync share a body — the only difference is whether the header and body get merged into a single page (.Merge()).

Seeding the data

To see the custom renderer in action you need a few RecipeBook nodes in the workspace. Ingest them with any of the Connector Recipes — point a CSV or JSON connector at a book dataset and map columns to the Title / Author / Year / Genre / ISBN fields.

See also

Referenced by

© 2026 Curiosity. All rights reserved.