LithoSharp 0.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package LithoSharp --version 0.2.0
                    
NuGet\Install-Package LithoSharp -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LithoSharp" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LithoSharp" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="LithoSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LithoSharp --version 0.2.0
                    
#r "nuget: LithoSharp, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LithoSharp@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LithoSharp&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=LithoSharp&version=0.2.0
                    
Install as a Cake Tool

LithoSharp

build NuGet

English | 日本語

A small, batteries-included static site generator for .NET. Give it Markdown and a bit of site configuration, and it renders a Docusaurus-inspired documentation site by default. The Docs template builds a responsive hierarchy sidebar, page table of contents, and previous/next links. The legacy Blog template remains available when you select it explicitly.

LithoSharp is designed to be embedded in your own console app or build pipeline. Site-specific behavior is injected through a single SiteCustomization object, so the core library has no opinions about your brand, copy, or validation rules.

Features

  • Docusaurus-inspired Docs output by default, with a responsive hierarchy sidebar, H2/H3 table of contents, and previous/next document links
  • An explicit Blog template with listing pages, archives, tags, client-side search, RSS (feed.xml), and sitemap.xml
  • Canonical, Open Graph, and Twitter Card metadata, plus optional favicon and social image assets
  • Front matter validation (title and date required; summary required by default)
  • Optional llms.txt summary for language models
  • Graceful degradation: when favicon or social-image sources are missing, those outputs are skipped and a complete HTML site is still produced

Install

dotnet add package LithoSharp

LithoSharp targets net10.0 and depends on Markdig, YamlDotNet, and SkiaSharp.

Quick start

The whole flow is three calls: read posts, optionally validate, then generate.

using LithoSharp;
using LithoSharp.Configuration;
using LithoSharp.Content;

var site = new SiteSettings
{
    Title = "My Site",
    Description = "A static site generated with LithoSharp.",
    BaseUrl = "https://example.com/",
    Language = "en",
    Author = "Me",
    TimeZone = "UTC"
};

var customization = new SiteCustomization
{
    Theme = new SiteThemeOptions
    {
        BrandPrefix = "my site / ",
        DefaultSocialSubtitle = "Built with LithoSharp",
        AdditionalCss = ":root { --accent: #7c9eff; }"
    },
    GenerateLlmsTxt = true
};

var posts = await new MarkdownPostReader().ReadAllAsync("content");
SiteGenerator.Validate(site, "content", posts, customization);
var result = await new SiteGenerator().GenerateAsync(site, posts, "_site", clean: true, customization);

Console.WriteLine($"Generated {result.PostCount} post(s) into {result.OutputDirectory}.");

A runnable documentation example lives in samples/LithoSharp.DocsSample. The legacy blog layout is shown in samples/LithoSharp.Sample.

dotnet run --project samples/LithoSharp.DocsSample -- --output _site

The default DocsSiteTemplate uses the directory structure under content for its left navigation. intro.md becomes a top-level document and guides/install.md appears under a guides group.

Content and front matter

MarkdownPostReader reads *.md files recursively and orders them by date (descending), then by slug. Each file starts with YAML front matter:

---
title: "Welcome"
date: "2026-01-02T09:00:00Z"
summary: "A short description used in listings and metadata."
sidebar_position: 1
sidebar_label: "Start here"
tags:
  - intro
sources:
  - type: feed
    name: Example Blog
    url: https://example.com/feed.xml
---

Body written in Markdown.

Schema

Field Type Required Notes
title string Yes Post title. Used in listings, the <title>, and metadata.
date string (ISO 8601) Yes Publication date and time. Parsed as a DateTimeOffset.
summary string By default Short description used in listings, the feed, and og:description. Required by the default RequiredSummaryValidator; replace the validator to change this.
sidebar_position integer No Docs navigation order. Lower values come first; unspecified documents are ordered by label and path.
sidebar_label string No Docs navigation label. Falls back to title.
tags list of strings No Free-form tags. Drive the tags page and client-side search.
sources list of objects No Provenance for the post. See below.

Each entry in sources has:

Field Type Required Notes
type string No A free-form label the calling app interprets. There is no fixed set; common conventions are feed, article, repo, doc, or release.
name string No Human-readable name of the source.
url string No Link to the source.

sources is parsed and exposed on MarkdownPost.FrontMatter, but the core generator does not render it. Surface it yourself through a SiteExtraPage or a custom layout if you want a sources list on the site. title and date are validated when posts are read; summary is checked during SiteGenerator.Validate.

Customization

SiteCustomization is the one-way extension point. LithoSharp never references your application code; you push behavior in through these members:

  • Text — UI strings. SiteText.English and SiteText.Japanese are included. Search status messages are templates that use {count}, {tag}, {query}, and {shown} placeholders, so the client-side search reads in the configured language.
  • Template — the rendering contract. DocsSiteTemplate is the default. Set new BlogSiteTemplate() to retain the legacy blog URLs, posts, RSS, search, and sitemap.
  • ThemeSiteThemeOptions with BrandPrefix, ThemeColor, DefaultSocialSubtitle, and AdditionalCss. The default markup and CSS are kept as-is; CSS from AdditionalCss is appended last and wins, so you can override :root variables and selectors without touching the markup.
  • Validators — your own IContentValidator instances. When empty, only the default RequiredSummaryValidator runs.
  • ExtraPages — additional pages emitted alongside the standard ones.
  • FaviconSourceDirectory — where to read favicon assets from. When omitted, a favicon directory next to the executable is used if present.
  • GenerateLlmsTxt — opt in to writing an llms.txt summary (off by default).

Selecting the Blog template

var customization = new SiteCustomization
{
    Template = new BlogSiteTemplate()
};

Writing a custom template

Implement ISiteTemplate to generate HTML and text assets. SiteTemplateContext provides rendered pages, headings, previous/next links, and a directory-based navigation tree. Use RenderDocument when the standard metadata, header, and footer fit your layout, and RenderTableOfContents to render the supplied page headings. LithoSharp validates every returned path, writes it safely beneath the output directory, and rejects a collision with common artifacts such as llms.txt, favicon files, and social images.

public sealed class LandingTemplate : ISiteTemplate
{
    public Task<SiteTemplateResult> RenderAsync(
        SiteTemplateContext context,
        CancellationToken cancellationToken = default)
    {
        var page = context.Pages[0];
        var body = $"<h1>{Html.Encode(page.Post.FrontMatter.Title)}</h1>{page.ContentHtml}";
        return Task.FromResult(new SiteTemplateResult(
        [
            new SiteTemplateFile
            {
                RelativePath = "index.html",
                Content = context.RenderDocument(new SiteTemplateDocument
                {
                    Title = context.Site.Title,
                    RelativePath = "index.html",
                    BodyHtml = body
                })
            },
            new SiteTemplateFile
            {
                RelativePath = "assets/site.css",
                Content = "body { font-family: sans-serif; }"
            }
        ]));
    }
}

var customization = new SiteCustomization { Template = new LandingTemplate() };

Public API

  • new SiteGenerator().GenerateAsync(SiteSettings site, IReadOnlyList<MarkdownPost> posts, string outputDirectory, bool clean, SiteCustomization? customization = null, CancellationToken ct = default)
  • static SiteGenerator.Validate(SiteSettings site, string contentDirectory, IReadOnlyList<MarkdownPost> posts, SiteCustomization? customization = null)
  • new MarkdownPostReader().ReadAllAsync(string contentDirectory)
  • SiteCustomization, SiteThemeOptions, SiteText, SiteExtraPage
  • ISiteTemplate, SiteTemplateContext, SiteTemplateResult, SiteTemplateFile, SiteTemplatePage, SiteTemplatePageLink, SiteTemplateHeading, SiteTemplateNavigationNode, SiteTemplateDocument
  • DocsSiteTemplate, BlogSiteTemplate
  • IContentValidator, ContentValidationContext, RequiredSummaryValidator

Namespaces: LithoSharp, LithoSharp.Configuration, LithoSharp.Content, LithoSharp.Validation, LithoSharp.Search.

Notes on assets and fonts

Favicon and social-image sources are optional. Open Graph images are drawn with SkiaSharp using system fonts: SocialImageGenerator looks for a preferred font (such as Consolas) and falls back to the default typeface. On hosts without those fonts, rendering may differ and CJK glyphs can render as tofu.

Build and test

Requires the .NET 10 SDK.

dotnet restore LithoSharp.slnx --locked-mode
dotnet build LithoSharp.slnx --no-restore -c Release
dotnet test --solution LithoSharp.slnx --no-build -c Release
dotnet run --project samples/LithoSharp.DocsSample -- --output _site
dotnet run --project samples/LithoSharp.Sample -- --output _site

Tests use TUnit on the Microsoft.Testing.Platform runner.

Versioning

LithoSharp follows SemVer. While the version is 0.x, the public API may change.

License

MIT. See LICENSE. Third-party dependencies are listed in THIRD-PARTY-NOTICES.md.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on LithoSharp:

Package Downloads
LithoSharp.Images

Declared, cached responsive image transforms for LithoSharp.

LithoSharp.Testing

Framework-independent site and DOM assertions for LithoSharp.

LithoSharp.Mdx

Opt-in official MDX and React static rendering for LithoSharp.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 145 9/15/2026
0.3.1 157 9/9/2026
0.3.0 144 9/8/2026
0.2.0 330 8/18/2026
0.1.0 363 6/30/2026

Adds the default Docs template, an explicit Blog template, extensible template APIs, hierarchical navigation, and separate Docs and Blog samples.