Lunet is a powerful static website generator built with .NET, powered by Scriban.
Paths/commands below are relative to this directory.
- CLI entry point:
src/Lunet/- thinExe(PackAsTool, commandlunet), delegates toLunet.Application. - App bootstrap:
src/Lunet.Application/-LunetAppregisters all 24 plugin modules, createsSiteApplication, runsSiteRunner. - Core library:
src/Lunet.Core/- foundation:SiteObject, content pipeline, scripting, plugin base classes. All plugins depend on this. RootNamespace =Lunet. - Plugin libraries:
src/Lunet.{PluginName}/- each is a small self-contained library implementing one feature. - Tests:
src/Lunet.Tests/(NUnit 4.4, classic assert aliases). References Core, Yaml, Api.DotNet.Extractor. - Docs:
readme.mdandsite/**/*.md- keep in sync with behavior. - Default template:
../templates/(sibling checkout of https://github.com/lunet-io/templates). Thelunet initskeleton insrc/Lunet.Core/shared/.lunet/new/site/extends this template. Changes to the init skeleton may require coordinating with the templates repo. - Solution:
src/lunet.slnx. Central package management viasrc/Directory.Packages.props. All projects targetnet10.0(exceptLunet.Api.DotNet.Extractor->netstandard2.0).
Must read: site/architecture.md - dependency graph, plugin system, class hierarchy, content pipeline, virtual file system, Scriban templating, and shared/ folder conventions.
# from the project root (this folder)
cd src
dotnet build -c Release
dotnet test -c Release
# build the website with the local lunet build (dogfooding)
cd ../site
dotnet ../src/Lunet/bin/Release/net10.0/lunet.dll --stacktrace build --devAll tests must pass and docs must be updated before submitting. Do not use a globally installed lunet to validate site/ in this repository.
- Keep diffs focused; avoid drive-by refactors/formatting and unnecessary dependencies.
- Follow existing patterns and naming; prefer clarity over cleverness.
- New/changed behavior requires tests; bug fix = regression test first, then fix.
- All public APIs require XML docs (avoid CS1591) and should document thrown exceptions.
- Naming:
PascalCasepublic/types/namespaces,camelCaselocals/params,_camelCaseprivate fields,I*interfaces. - Style: file-scoped namespaces;
usingoutside namespace (Systemfirst);varwhen the type is obvious. - Nullability: enabled - respect annotations; use
ArgumentNullException.ThrowIfNull(); preferis null/is not null; don't suppress warnings without a justification comment. - Exceptions: validate inputs early; throw specific exceptions (e.g.,
ArgumentException/ArgumentNullException) with meaningful messages. - Async:
Asyncsuffix; noasync void(except event handlers); useConfigureAwait(false)in library code; considerValueTask<T>on hot paths.
- Minimize allocations (
Span<T>,stackalloc,ArrayPool<T>,StringBuilderin loops). - Keep code AOT/trimmer-friendly: avoid reflection; prefer source generators; use
[DynamicallyAccessedMembers]when reflection is unavoidable. - Use
sealedfor non-inheritable classes; preferReadOnlySpan<char>for parsing.
- Follow .NET guidelines; keep APIs small and hard to misuse.
- Prefer overloads over optional parameters (binary compatibility); consider
Try*methods alongside throwing versions. - Mark APIs
[Obsolete("message", error: false)]before removal once stable (can be skipped while pre-release).
- Commits: commit after each self-contained logical step; imperative subject, < 72 chars; one logical change per commit; reference issues when relevant; don't delete unrelated local files.
- Checklist: each self-contained step is committed; build+tests pass; docs updated if behavior changed; public APIs have XML docs; changes covered by unit tests.