NuGet feed
A read-only NuGet v3 feed backed by one or more folders of nupkgs.
SharpDocs exposes a NuGet v3 feed at /v3/index.json. It implements the subset of v3 needed for dotnet restore to work against a folder of nupkgs.
What gets indexed
- Every
*.nupkgdirectly under each configured artifacts folder is opened as a zip. - The root
.nuspecis parsed (id, version, description, authors, tags, dependencies). - Files ending in
.symbols.nupkgare skipped. - Packages are grouped by id; versions are sorted ascending so the last entry is "latest".
In single-project mode there is one artifacts folder, configured via SharpDocs:ArtifactsRoot. In multi-project mode there are N folders — one per project, declared in each project's sharpdocs.json. They merge into one feed; (id, version) collisions across folders are resolved first-wins by project order.
There is no caching layer between the feed and disk. Restart the host to pick up new packages.
Endpoints
| Route | Purpose |
|---|---|
GET /v3/index.json |
Service index |
GET /v3/flatcontainer/{id}/index.json |
Version list |
GET /v3/flatcontainer/{id}/{version}/{id}.{version}.nupkg |
Download the nupkg |
GET /v3/flatcontainer/{id}/{version}/{id}.nuspec |
Download the nuspec |
GET /v3/registration/{id}/index.json |
Registration (metadata + deps) |
GET /v3/search?q=&skip=&take=&prerelease= |
Search |
GET /v3/autocomplete?q=&take= |
Id autocomplete |
See Reference: NuGet v3 endpoints for the full shape.
Base URL
Absolute URLs in feed responses are derived from the incoming request (Scheme, Host, PathBase). The feed works unmodified behind a reverse proxy or on any host — no configuration needed.
See Host behind a reverse proxy for the forwarded-headers setup.
Consuming the feed
dotnet nuget add source https://your-site.example/v3/index.json --name my-feed
dotnet add package MyPackage
Browsing packages
/packages lists every id with its latest version, and /packages/{id} shows version history, dependencies, and a download link. In multi-project mode the listing is unified — every project's artifacts folder is merged into the same view, with no per-project filter. This UI is local-only — it does not enumerate upstream packages.
Composite mode (upstream feeds)
You can layer one or more upstream NuGet v3 feeds behind your own. Every /v3/* endpoint then merges local artifacts with live results from the upstreams. Clients see a single feed — yours — and never need to configure the upstreams directly.
builder.Services.AddSharpDocs(builder.Configuration)
.AddUpstream("https://api.nuget.org/v3/index.json")
.AddUpstream("https://other-feed.example/v3/index.json");
Upstreams can also come from appsettings.json:
"SharpDocs": {
"Upstreams": [ { "Url": "https://api.nuget.org/v3/index.json" } ]
}
Behavior:
- Version lists merge local + upstream versions, dedup, sort.
- Registration responses merge leaves; every
packageContentURL is rewritten to point back at your feed, so downloads always come through you. - Search and autocomplete fan out; local ids win on collision, then first upstream wins.
- Downloads (
.nupkg,.nuspec): if the local artifact exists, it's served from disk; otherwise the request is proxy-streamed from the first upstream that has the version. Bytes flow through your server — no 302 redirects, no on-disk cache. - Local always wins on
id+versioncollisions. - A slow or failed upstream is logged and treated as empty — it never blocks the whole response.
Service-index URLs for each upstream are resolved once at startup (not per request). Upstream package data is fetched live on every request; there is no cache layer.
Tune the per-upstream HTTP timeout (default 10s) via:
"SharpDocs": {
"UpstreamTimeoutSeconds": 5
}