Multi-project sites

Host N libraries under one site, one feed, with a per-project sidebar each.


A SharpDocs site can serve one project (the default) or N. Multi-project mode lets you host several sibling libraries — each with its own docs and packages — under a single domain, behind a single landing page, with a single NuGet feed.

Switch it on

A site goes multi-project when its root sharpdocs.json has a projects array:

{
  "title": "Codezerg Libraries",
  "description": "Three libraries under one roof.",
  "projects": [
    { "id": "alpha", "path": "../codezerg-alpha" },
    { "id": "beta",  "path": "../codezerg-beta" },
    { "id": "gamma", "path": "../codezerg-gamma" }
  ]
}

Each path is resolved relative to the root docs folder.

Per-project sharpdocs.json

Every referenced project keeps its own sharpdocs.json next to its markdown:

{
  "title": "Alpha",
  "description": "First library.",
  "github": "https://github.com/example/alpha",
  "artifacts": "./artifacts",
  "sidebar": [
    {
      "label": "Overview",
      "items": [
        { "label": "Introduction", "slug": "index" }
      ]
    }
  ]
}
Field Purpose
title Project title — shown on the landing page card and per-page subtitle.
description Optional — shown on the landing page card.
github Optional — kept for symmetry with the root config.
artifacts Optional — folder of *.nupkg files for this project. Default ./artifacts, relative to the project.
sidebar Same shape as single-project. Slugs reference markdown under the project's path.

URL shape

URL What
/ Landing picker with a card per project. With exactly one healthy project and an index slug in its sidebar, renders that project's index page directly; otherwise the picker is shown.
/docs/{projectId}/{slug} A page from that project.
/docs/{projectId}/search?q= Search scoped to that project.
/v3/index.json The unified NuGet feed (all projects' artifacts).
/packages Package browser, listing all local + upstream packages.

/search at the root is not routed in multi-project mode — search is always scoped to a project. The search box in the navbar hides on the landing page (no project context) and posts to the active project's URL elsewhere.

Project ids

Each project's id is the URL segment under /docs/. Ids are normalized at load time:

  • Lowercased.
  • Anything outside [a-z0-9-] is stripped.
  • Runs of - are collapsed; leading/trailing - is trimmed.

So "id": "Codezerg.AutoRepo" becomes codezergautorepo, and "id": "Foo Bar!" becomes foobar. Pick clean ids upfront and the URL stays predictable.

The ids search, packages, v3, api, and docs are reserved (they collide with top-level routes). A project using a reserved id is degraded — it appears on the landing page with an error message, but doesn't crash the site.

Failure isolation

A bad project never blocks startup:

  • Missing project directory or sharpdocs.json → degraded card, error logged.
  • Sidebar references a slug that doesn't exist → degraded card, error logged.
  • Duplicate id (after sanitization) → second occurrence silently dropped.

The rest of the site boots normally. This is the same posture as upstream feed resolution.

A degraded project still appears on the landing page as a card, but with a warning panel showing the error message instead of a link. Its routes (/docs/{id}/...) are not served, its pages don't appear in any nav, and its artifacts folder isn't merged into the feed. Fix the underlying issue and restart to bring it back.

NuGet feed

The feed is shared across projects. LocalFolderSource scans every project's artifacts folder and merges them into one view. Duplicate (id, version) across projects is resolved first-wins by projects[] order. Clients see a single NuGet feed at /v3/index.json.

When not to use multi-project mode

If your goal is just "host these N libraries on one domain" and you don't need unified docs navigation under one URL, deploy N separate single-project sites instead. They're independent pods, fail independently, and need zero new code. Reach for multi-project mode when you specifically want a single docs URL — the landing page, the shared header, the unified package browser.