Universal package registry and CDN — WinGet registry, npm, GitHub, JSR, cdnjs, WordPress. Built in Rust for speed.
Nexus is a high-performance ESM CDN and package proxy written in Rust (axum + tokio). It proxies npm / JSR / GitHub / cdnjs / WordPress packages, converts them to browser-native ESM, and caches the results. It also serves a complete WinGet package search and manifest API backed by SQLite + the winget-pkgs GitHub source.
- ⚡ Rust + axum — async, low-overhead HTTP server on tokio
- 🪟 WinGet REST API — search, package metadata, versions, installers, locales, and full manifests (RESTSource 1.9.0 compatible)
- 📦 Universal CDN — npm, GitHub, JSR, cdnjs, WordPress
- 🔧 ESM Bundling — npm packages bundled to browser-native ESM via rolldown, with bare imports rewritten to CDN paths
- 🔒 SRI Support — SHA-256 Subresource Integrity for every cached file
- 💾 Pluggable storage — filesystem for dev, S3 for distributed deployments
# Get package entry file
curl https://nexus.funish.net/cdn/npm/react
# Get specific version (supports ranges: 18, 18.3, ^18.3.1)
curl https://nexus.funish.net/cdn/npm/react@18
# Get specific file
curl https://nexus.funish.net/cdn/npm/react@18/index.js
# Directory listing (trailing slash)
curl https://nexus.funish.net/cdn/npm/react@18.3.1/
# Get bundled ESM module
curl https://nexus.funish.net/cdn/npm/d3@7/+esmVersion resolution (npm-flavored semver via node-semver): react → latest · react@18 → latest 18.x · react@18.3 → latest 18.3.x · react@18.3.1 → exact.
ESM Bundling (+esm): bundles an npm package into a single ESM module with external dependencies rewritten to CDN URLs:
<script type="module">
import { scaleLinear } from "https://nexus.funish.net/cdn/npm/d3@7/+esm";
</script># Repository files (latest tag by default)
curl https://nexus.funish.net/cdn/gh/vuejs/core
# Specific tag/version (supports ranges and v-prefix)
curl https://nexus.funish.net/cdn/gh/vuejs/core@v3.4.0/dist/vue.global.jscurl https://nexus.funish.net/cdn/jsr/@std/path@1.1.4/mod.ts# @ format (recommended) — supports version ranges
curl https://nexus.funish.net/cdn/cdnjs/jquery@3.7/jquery.min.js
# List all files for a version
curl https://nexus.funish.net/cdn/cdnjs/jquery@3.7.1/# Plugin from a tagged version
curl https://nexus.funish.net/cdn/wp/plugins/wp-slimstat/tags/4.6.5/wp-slimstat.js
# Plugin from trunk (latest development)
curl https://nexus.funish.net/cdn/wp/plugins/wp-slimstat/trunk/wp-slimstat.js
# Theme
curl https://nexus.funish.net/cdn/wp/themes/twentytwentyfour/1.0/style.cssConcatenate several npm/gh files into a single response (comma-separated, each prefixed with npm/ or gh/):
curl "https://nexus.funish.net/cdn/combine/npm/jquery@3/dist/jquery.min.js,gh/twbs/bootstrap@3/dist/js/bootstrap.min.js"The combined result is cached long-term (immutable); the Content-Type is taken from the first file.
Every cached file gets a SHA-256 integrity hash, exposed in directory listings for use as an ETag and for SRI:
curl https://nexus.funish.net/cdn/npm/react@18.3.1/
# {
# "name": "react",
# "version": "18.3.1",
# "files": [
# { "name": "index.js", "size": 12345, "integrity": "sha256-ABC123..." }
# ]
# }<script
src="https://nexus.funish.net/cdn/npm/react@18.3.1/index.js"
integrity="sha256-ABC123..."
crossorigin="anonymous"
></script>Conditional requests are honored: send If-None-Match: <integrity> to get a 304 Not Modified.
A complete Windows Package Manager REST API, compatible with the WinGet RESTSource 1.9.0 specification. Package search is backed by the SQLite index.db; per-version manifests are assembled from the microsoft/winget-pkgs GitHub YAML files.
# Server information
GET https://nexus.funish.net/api/winget/information
# List all packages (paginated)
GET https://nexus.funish.net/api/winget/packages
# Search packages (GET or POST)
GET https://nexus.funish.net/api/winget/manifestSearch?query=vscode&matchType=Fuzzy&maximumResults=5
POST https://nexus.funish.net/api/winget/manifestSearch # body: {"Query":{"KeyWord":"chrome","MatchType":"Fuzzy"}}
# Package metadata & versions
GET https://nexus.funish.net/api/winget/packages/{id}
GET https://nexus.funish.net/api/winget/packages/{id}/versions
# Per-version manifest data
GET https://nexus.funish.net/api/winget/packages/{id}/versions/{version}/installers
GET https://nexus.funish.net/api/winget/packages/{id}/versions/{version}/installers/{installer}
GET https://nexus.funish.net/api/winget/packages/{id}/versions/{version}/locales
GET https://nexus.funish.net/api/winget/packages/{id}/versions/{version}/locales/{locale}
# Full merged manifest (supports ?Version, ?Channel, ?Market filters)
GET https://nexus.funish.net/api/winget/packageManifests/{id}Example:
curl https://nexus.funish.net/api/winget/packages/Microsoft.VisualStudioCode/versions- Rust (stable, 1.88+ for edition 2024 + let-chains)
cargo build --release # build the optimized binary
cargo run --release # run it
# or during development
cargo runThe server listens on 0.0.0.0:3000 by default (override with PORT).
cp .env.example .env
# edit .env to configure GITHUB_TOKEN / S3 / etc.
docker compose up -d
docker compose logs -f appdocker pull funish/nexus:latest
docker run -d \
--name nexus \
-p 3000:3000 \
--env-file .env \
--restart unless-stopped \
funish/nexus:latestdocker build -t nexus .
docker run -d --name nexus -p 3000:3000 --env-file .env nexusAll configuration is via environment variables (see .env.example):
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
HTTP listen port |
CACHE_DIR |
./.cache |
Filesystem cache directory (used when S3 is not configured) |
GITHUB_TOKEN |
— | Optional; raises GitHub API rate limits for WinGet manifest/tree fetching |
S3_ACCESS_KEY_ID |
— | S3 access key (enables S3 storage when all S3_* are set) |
S3_SECRET_ACCESS_KEY |
— | S3 secret key |
S3_ENDPOINT |
— | S3 endpoint URL |
S3_REGION |
— | S3 region |
S3_BUCKET |
— | S3 bucket name |
This project is licensed under the MIT License — see the LICENSE file for details.
Built with ❤️ by Funish