Skip to main content

NetPrints docs + release research (2026-09-25)

Status: the owner approved the recommended stack on 2026-09-25; it is folded into the P1 spec.

0. What exists locally​

  • netprints: only .github/workflows/ci.yml (Linux build/test/format/CLI smoke + E2E Xvfb job), actions pinned by SHA. (src: .github/workflows/ci.yml)
  • Directory.Build.props already sets Deterministic=true, ContinuousIntegrationBuild on CI; no SourceLink/pack metadata, no NuGet.config, no Directory.Build.targets. (src: repo root files)
  • NetPrints.Core.csproj hard-codes <Version>0.0.7</Version>, MIT, Copyright Robin Kahlow 2018. Cli is plain Exe (no PackAsTool). Desktop is WinExe with NetPrintsLogo.ico. No GenerateDocumentationFile anywhere. (src: src//.csproj)
  • global.json SDK 10.0.100 rollForward latestFeature; MTP test runner. Avalonia 12.1.3, Nodify.Avalonia 2.0.0.
  • docs/: adr/ (ADR 0001), research/2026-09-25-* with PNGs and prototype csproj folders (these prototypes must be excluded from any docs build/glob). specs/ = Spec Kit 001, 002.
  • kicad-sharp release.yml: tag v* -> pack job (VER from tag ${GITHUB_REF_NAME#v}, default hard-coded) -> publish-nuget (environment release, id-token: write, NuGet/login@v1 with secrets.NUGET_USER, dotnet nuget push --skip-duplicate) + release job (softprops/action-gh-release@v3, generate_release_notes). workflow_dispatch = dry run. NuGet.config adds git-ignored local-packages feed; scripts/use-local-libs.sh packs sibling repo with 0.1.0-local.<timestamp>. Directory.Build.targets packs README when IsPackable. (src: kicad-sharp files)

1. NUKE: site and build tool status​

2. What well-known .NET OSS projects use for docs (checked 2026-09-25 via gh api repo trees)​

ProjectDocs toolSource
AvaloniaDocusaurus 3 (docusaurus.config.ts, @docusaurus/core ^3.8.1), separate repo avalonia-docs; API reference generated by a dotnet-apiref tool from NuGet packages (apiref.json) and committedhttps://github.com/AvaloniaUI/avalonia-docs (README "API Reference Generation", package.json)
NodifyMarkdown in docs/ (Home.md, wiki-style names) synced to the GitHub wiki with newrelic/wiki-sync-action on push to docs/**; landing site miroiu.github.io/nodify built with Astro (/_astro/ assets)https://github.com/miroiu/nodify/blob/master/.github/workflows/sync-docs.yml , https://miroiu.github.io/nodify
CommunityToolkit (dotnet)Microsoft Learn (MicrosoftDocs/CommunityToolkit, Learn = DocFX-based pipeline); repo uses version.json (NBGV)https://github.com/CommunityToolkit/dotnet (homepage), https://github.com/MicrosoftDocs/CommunityToolkit
Spectre.ConsoleSeparate spectreconsole/website repo, a .NET app on Pennington ("A content engine for .NET that turns Markdown into static sites", 11 stars, v0.1.8) incl. Pennington.ApiMetadata.Reflection; repo builds with build.cs (file-based C# app)https://github.com/spectreconsole/website (Spectre.Docs.csproj), https://github.com/usepennington/pennington
NUKE / FalloutDocusaurussee section 1
StrideDocFX (en/docfx.json with metadata from Stride csprojs, TargetFramework net10.0), separate stride-docs repohttps://github.com/stride3d/stride-docs
MonoGameEleventy 2 + Bootstrap (monogame.github.io package.json)https://github.com/MonoGame/monogame.github.io
Silk.NETDocusaurus (documentation/sidebars.ts imports @docusaurus/plugin-content-docs); builds with NUKE (.nuke, build.sh)https://github.com/dotnet/Silk.NET
AvaloniaEditNo docs site (README only; azure-pipelines.yml)https://github.com/AvaloniaUI/AvaloniaEdit
DocFX itselfvery active: v2.81.0 released 2026-09-25, v2.80.1 2026-09-18gh api repos/dotnet/docfx/releases

Takeaway: Docusaurus is the most common choice among the big .NET projects checked (Avalonia, NUKE, Fallout, Silk.NET); DocFX where API reference is central (Stride, MS Learn).

3. Docs generators, state in Sep 2026​

Recommendation (docs site)​

  • Pick: Docusaurus 3 in website/ reading ../docs (plus generated api/), deployed with the official Pages actions. Reasons: it is what nuke.build looked like (the thing the owner liked), it is what Avalonia, Silk.NET and Fallout use, it is mature (3.x, 66k stars), broken-link checks are on by default, and markdown.format: 'detect' lets plain .md from docs/ and DocFX-generated markdown render without MDX breakage.

  • Runner-up: DocFX alone (modern template) — one .NET tool (dotnet tool manifest, no Node), best-in-class API reference with xrefs; weaker look/customization. Choose it if the owner prefers zero Node toolchain.

  • Avoid for now: MkDocs Material (maintenance mode, support window ending ~Nov 2026), Zensical (0.0.x), VitePress 2 (alpha), Starlight (fine, but no .NET API story and 0.x).

  • awesome-dotnet "Documentation" section lists only Sandcastle, SourceBrowser, Swashbuckle, F# Formatting, DocFX, DocNet, HubDocs — DocFX is the only maintained general .NET API doc generator listed. (src: https://github.com/quozd/awesome-dotnet README, "## Documentation")

4. Pages + wiki from one source​

  • Wiki facts (GitHub docs): "Search engines will only index wikis with 500 or more stars that you configure to prevent public editing"; "If you need search engines to index your content, you can use GitHub Pages"; soft limit 5,000 files; by default only users with write access can edit; wiki is a git repo REPO.wiki.git, only pushes to its default branch go live; filename = page title; _Sidebar.md / _Footer.md give sidebar/footer. (src: https://docs.github.com/en/communities/documenting-your-project-with-wikis/about-wikis , .../adding-or-editing-wiki-pages , .../creating-a-footer-or-sidebar-for-your-wiki)
  • Andrew-Chen-Wang/github-wiki-action v5.0.6 (2026-07-11), 111 stars, active: mirrors a folder to .wiki.git with default GITHUB_TOKEN + permissions: contents: write; you must create a first wiki page manually to initialize the wiki repo; preprocess: true (default) renames README.md -> Home.md, rewrites links to bare page names; "GitHub serves wiki pages flat by basename, so cross-directory page links are rewritten to bare page names"; repo-relative links become blob/ URLs and images raw/ URLs pinned to the commit; images inside the wiki folder stay relative; ignore, strategy: clone|init (init force-pushes), disable-empty-commits, dry-run, and direction: pull (+ gollum trigger) to turn wiki UI edits into a PR. Titles come from filenames with - -> space. (src: https://github.com/Andrew-Chen-Wang/github-wiki-action README)
  • Alternatives: newrelic/wiki-sync-action (last release v1.0.1 2022-05, used by Nodify with a PAT secret DOCS_TOKEN), SwiftDocOrg/github-wiki-publish-action (archived), OrlovM/Wiki-Action (2022), spenserblack/actions-wiki (rc since 2023). (src: gh api repos/*; https://github.com/miroiu/nodify/blob/master/.github/workflows/sync-docs.yml)
  • NetPrints-specific problem: docs/ is nested (adr/README.md, research/<date>-*/README.md x2) — three pages share the basename README, which collide in the flat wiki namespace (and README.md -> Home.md). Research folders also contain .csproj/.cs prototypes and many PNGs that a wiki mirror would carry. (src: local ls -R docs; flat-namespace rule from the action README above)

Recommendation (wiki)​

  • Pick: Pages site is the single source of truth; the wiki is a 2-page pointer (Home.md + _Sidebar.md linking to the site sections, API reference, Releases, Discussions), published from .github/wiki/ by github-wiki-action with strategy: init, or simply disable the Wiki tab. Reasons: the wiki is not search-indexed below 500 stars, it flattens the directory tree (basename collisions above), cannot host the API reference, and a second rendered copy drifts (wiki UI edits are overwritten by the next push).
  • Runner-up: full mirror of a curated subset (docs/guide/**) via github-wiki-action with preprocess: true + ignore for research/prototypes and unique file names — only if the owner explicitly wants the wiki reader UI. Keep edit restricted to collaborators.

5. API reference from XML docs​

  • DocFX metadata: reads csproj via Roslyn; outputFormat mref (default, for docfx build) / apiPage / markdown. BUT the maintainers' aggregated issue #10039 (open since 2024-06): "currently docfx's markdown output format is intended to be used for docfx build command input", with known issues for external tools (e.g. #9720 empty <a id=...></a> in every H1, #10268 generics missing Derived section, #10489 property values). So feeding DocFX markdown into Docusaurus is fragile. (src: https://github.com/dotnet/docfx/issues/10039 , https://github.com/dotnet/docfx/issues/9720 , https://github.com/dotnet/docfx/issues/10268 , https://github.com/dotnet/docfx/issues/10489)
  • DocFX-to-Docusaurus converters: Jan0660/DocFxMarkdownGen (36 stars, last release v0.4.1 2023-07), k-wojcik/DocFxToTemplate — stale. (src: gh api; https://github.com/Jan0660/DocFxMarkdownGen)
  • DefaultDocumentation (Doraku): active (1.2.5 on 2026-05-10, pushed 2026-09-21), MSBuild task package DefaultDocumentation or dotnet tool DefaultDocumentation.Console (net8/9/10); plain Markdown per namespace/type/member (GeneratedPages), LinksOutputFilePath/LinksBaseUrl/ExternLinksFilePaths for cross-linking, plugin API, UrlFactories. (src: https://github.com/Doraku/DefaultDocumentation README; nuget flatcontainer)
  • xmldocmd (ejball/XmlDocMarkdown): last NuGet release 2.9.0 on 2023-01-02 — stale. (src: nuget registration API; https://github.com/ejball/XmlDocMarkdown)
  • Avalonia's Docusaurus uses a dotnet-apiref tool that reads apiref.json and NuGet packages, output committed; not found as a documented public tool. (src: https://github.com/AvaloniaUI/avalonia-docs README)
  • Prereq in NetPrints: no project sets GenerateDocumentationFile today (src: local csproj files), so XML docs must be switched on for packable projects (also needed for IntelliSense in NuGet packages); expect CS1591 warnings on legacy Core/Reflection -> NoWarn CS1591 there until P1 documents them.

Recommendation (API ref)​

  • Pick: DocFX (modern template) builds only the API reference as a sub-site at /api/ of the same Pages artifact: docfx metadata + docfx build from docs/api/docfx.json -> _site, copied into website/build/api/ before actions/upload-pages-artifact. Docusaurus navbar gets an external-style link /netprints/api/. Robust (DocFX's native pipeline, xrefs to .NET BCL via Microsoft xrefmap, own search), no markdown-conversion bugs.
  • Runner-up: DefaultDocumentation MSBuild task writing Markdown into website/api/ (git-ignored, generated in CI) as a second Docusaurus docs plugin instance — one look and one search, but verify escaping of generics under markdown.format: 'detect'.

6. Desktop binaries (Avalonia 12 editor)​

.NET publish facts​

NetPrints-specific caveats (from the code)​

  • Trimming / Native AOT: do not enable. The editor compiles graphs with Roslyn against arbitrary assemblies and uses reflection heavily (MetadataReference.CreateFromFile in src/NetPrints.Core/Compilation/CodeCompiler.cs:26 and src/NetPrints.Reflection/ReflectionProvider.cs:196, Activator.CreateInstance in src/NetPrints.Editor/Graph/NodeGraphVM.cs:240, Type.GetType in src/NetPrints.Editor/Graph/Pins/NodePinVM.cs:226, DataContractSerializer with KnownTypes). Trimming would remove BCL types user graphs call.
  • Single-file breaks compilation today. ReferenceAssemblyResolver.FindRuntimeAssemblyPaths() enumerates *.dll in RuntimeEnvironment.GetRuntimeDirectory() (src/NetPrints.Core/Core/ReferenceAssemblyResolver.cs:134-141). In a single-file bundle the BCL DLLs are not on disk, so the fallback reference set would be empty. In a self-contained folder publish it enumerates the app folder (BCL + Avalonia + NetPrints DLLs: works, but references the editor's own assemblies too). Fix options: ship reference assemblies explicitly, e.g. Basic.Reference.Assemblies.Net100 (1.8.12 on NuGet, "NuPkg files that have .NET Reference assemblies as resources", works in-memory) — that is P1 "real reference-pack resolution" work anyway. (src: nuget flatcontainer basic.reference.assemblies.net100; https://github.com/jaredpar/basic-reference-assemblies)
  • Running compiled graphs needs the dotnet host: resolver doc comment says "Compiled executables then need a runtime configuration file and are started through the dotnet host" (ReferenceAssemblyResolver.cs:33-36). A self-contained editor on a machine without .NET installed can compile but not run the result -> document as a requirement or run in-process via AssemblyLoadContext later.
  • => First release: self-contained, folder (non-single-file), untrimmed publishes, zipped/tarred.

Packaging tools​

Checksums and signing​

  • actions/attest@v4 (v4.2.2, 2026-08-04) generates Sigstore-signed SLSA build provenance; actions/attest-build-provenance v4 "is simply a wrapper on top of actions/attest" and new implementations should use actions/attest. Permissions: id-token: write, attestations: write, artifact-metadata: write; subject-path accepts globs (<=1024 subjects) or subject-checksums. Free for public repos. Verify with gh attestation verify <file> -R danielmeza/netprints. (src: https://github.com/actions/attest README, https://github.com/actions/attest-build-provenance README)
  • Plus a SHA256SUMS.txt (sha256sum *.zip *.tar.gz > SHA256SUMS.txt) attached to the Release.
  • Windows Authenticode: unsigned zip triggers SmartScreen; Azure Artifact Signing ~$10/month is the cheapest route. Apple: Developer ID needs the Apple Developer Program. Both are paid -> defer.

Recommendation (desktop)​

  • Minimum first step: a desktop matrix job in release.yml: dotnet publish src/NetPrints.Desktop -c Release -r <rid> --self-contained -p:PublishSingleFile=false -p:PublishTrimmed=false -p:Version=$VER -o out/<rid> on ubuntu-latest (linux-x64, win-x64) and macos-latest (osx-arm64, so the apphost gets ad-hoc signed), archive as NetPrints-<ver>-linux-x64.tar.gz (preserves +x), -win-x64.zip, -osx-arm64.tar.gz (or zipped .app), SHA256SUMS.txt, actions/attest over all archives, upload to the GitHub Release. Document "unsigned; macOS: Open Anyway" in release notes.
  • Next (pick): Velopack — one tool for Win Setup.exe, macOS .pkg/.app and Linux AppImage plus auto-update from GitHub Releases; add signing when certificates exist. Runner-up: PupNet Deploy for Linux .deb/.rpm/AppImage/Flatpak + Windows Setup (no auto-update, no macOS).

7. Build automation: NUKE vs Cake vs plain workflows​

  • NUKE: unmaintained since 2025-12 (see section 1); website down. Successor Fallout v10.4.0 (2026-08), 161 stars, single maintainer, rebranded APIs (fallout-migrate). (src: https://github.com/nuke-build/nuke/discussions/1564 , https://github.com/Fallout-build/Fallout)
  • Cake: active, v6.3.0 (2026-09-14), 4.2k stars. Spectre.Console's build.cs is a .NET 10 file-based app starting with #:sdk Cake.Sdk@6.2.0 (no bootstrapper, no separate build project) and its publish workflow runs dotnet make publish after dotnet tool restore; Spectre versions with MinVer + Microsoft.SourceLink.GitHub. (src: https://github.com/spectreconsole/spectre.console/blob/main/build.cs , .github/workflows/publish.yaml , src/Directory.Build.props; gh api cake-build/cake/releases)
  • Plain GitHub Actions YAML: what kicad-sharp and netprints CI already use; nothing to install, SHA-pinned actions, dependabot already configured in netprints.

Recommendation (pipeline)​

  • Pick: plain GitHub Actions workflows, with non-trivial logic in small scripts/*.sh (kicad-sharp pattern: scripts/check-natives.sh, scripts/use-local-libs.sh). The release is ~4 jobs; a C# build DSL adds a dependency without removing YAML (you still need the workflow for OIDC, environments, attestations, Pages deploy).
  • Runner-up: Cake.Sdk file-based build.cs (the modern "C# instead of YAML" option, actively maintained) if the scripts grow; not NUKE (unmaintained) and not Fallout yet (young, single maintainer) — revisit Fallout in 6-12 months.

8. Versioning and changelog​

  • MinVer: 8.0.0 (2026-09-05), tag-driven (MinVerTagPrefix=v), untagged commits get x.y.z-alpha.0.<height>, AssemblyVersion = {Major}.0.0.0; needs full history (fetch-depth: 0, shallow-clone FAQ); README criticizes NBGV for using git height as patch. Used by Spectre.Console. (src: https://github.com/adamralph/minver README; nuget registration; Spectre src/Directory.Build.props)
  • Nerdbank.GitVersioning: v3.10.94 (2026-08-28); version in version.json, height-based; used by CommunityToolkit and Fallout. (src: gh api; CommunityToolkit/dotnet and Fallout trees contain version.json)
  • GitVersion: 6.8.2 (2026-07-10), branch-model driven, most config. (src: gh api GitTools/GitVersion)
  • kicad-sharp: hard-coded VER=0.1.1 in workflow, overridden by tag ${GITHUB_REF_NAME#v}; netprints Core hard-codes <Version>0.0.7</Version>. (src: local files)
  • Release notes: GitHub generated notes = merged PRs + contributors + full-changelog link, configurable via .github/release.yml (changelog.exclude.labels/authors, categories[].labels, * catch-all). release-drafter v7.7.0 (drafts continuously from labels); release-please v17 / action v5 (conventional commits, opens release PRs, owns tags); git-cliff v2.14.2 (conventional-commit changelog generator). (src: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes ; gh api releases)

Recommendation (versioning)​

  • Pick: MinVer with MinVerTagPrefix=v in Directory.Build.props for packable projects. It keeps the exact kicad-sharp flow (push tag v1.2.3 -> version 1.2.3) but removes the hard-coded default and the -p:Version plumbing, and gives CI builds between tags a meaningful prerelease (0.1.0-alpha.0.N). Checkout needs fetch-depth: 0. Remove <Version>0.0.7</Version> from NetPrints.Core.csproj; set MinVerMinimumMajorMinor=0.1 for the first release.
  • Runner-up: keep kicad-sharp's -p:Version=${GITHUB_REF_NAME#v} (zero dependencies).
  • Notes: GitHub generated notes + .github/release.yml categories (labels: breaking, feature, bug, docs, dependencies; exclude dependabot from the main list or group it). Add release-drafter only if a curated draft is wanted; skip release-please (it wants to own tagging, conflicts with manual v* tags).

9. NuGet hygiene​

10. FINAL SUMMARY (see handback report for the full list of files/steps/risks)​

Docs: Docusaurus 3 (runner-up DocFX-only). API: DocFX sub-site at /api (runner-up DefaultDocumentation markdown). Wiki: pointer only (runner-up curated mirror via github-wiki-action). Pipeline: plain Actions + scripts (runner-up Cake.Sdk build.cs; not NUKE). Desktop: self-contained folder zips + SHA256SUMS + actions/attest first; Velopack next (runner-up PupNet). Versioning: MinVer v-prefix (runner-up tag -> -p:Version). Notes: generated notes + .github/release.yml.