npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vex-chat/spire

v5.0.0

Published

Vex server implementation in NodeJS.

Readme

@vex-chat/spire

npm CI Released License Type Coverage Node OpenSSF Scorecard npm audit Socket

Reference server implementation for the Vex protocol.

What's in the box

  • REST API (Express 5) for full e2e messaging including auth, registration, users, servers, channels, invites, and file upload.

Install

Spire is part of the vex-protocol/vex-protocol monorepo. Clone the monorepo and install workspace deps:

git clone [email protected]:vex-protocol/vex-protocol
cd protocol
pnpm install

Spire's source lives at apps/spire/. Most commands below run from the monorepo root.

Running the server (Docker)

The Dockerfile uses the monorepo as build context so the build can resolve workspace:^ deps for @vex-chat/{types,crypto,libvex}. From apps/spire/, with Docker and Docker Compose installed:

cp .env.example .env
# set SPK, JWT_SECRET, DB_TYPE, … (see Configuration)
docker compose up --build

Compose builds the image (context: monorepo root, dockerfile: apps/spire/Dockerfile), starts Spire with a persistent spire-data volume mounted at /data (SQLite + files/, avatars/, emoji/), and fronts it with nginx on host port 16777. Runtime keys and passkey settings come from apps/spire/.env via Compose env_file; they are intentionally not copied into the Docker image.

Running without Docker

For local development or if you installed from npm, Spire runs with node --experimental-strip-types (no separate compile step):

pnpm --filter @vex-chat/spire start
# or, from apps/spire/: pnpm start
# or: node --experimental-strip-types src/run.ts

From an npm install, sources live under node_modules/@vex-chat/spire/src/:

node --experimental-strip-types node_modules/@vex-chat/spire/src/run.ts

Configuration

Spire reads configuration from environment variables. Docker Compose: put them in a .env file next to docker-compose.yml (the env_file entry injects them into the container). Bare Node: dotenv loads .env from the process working directory when you run src/run.ts.

Required

| Variable | Description | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | SPK | Server Ed25519 private key, hex-encoded. Generate it with pnpm --filter @vex-chat/spire gen-spk; the command also prints a separate JWT_SECRET. | | JWT_SECRET | Hex or string used as the HMAC secret for JWTsrequired and must be separate from SPK. pnpm --filter @vex-chat/spire gen-spk emits a dedicated value; do not reuse SPK here. | | DB_TYPE | sqlite3 or sqlite3mem. All values use SQLite via better-sqlite3 (file or :memory:). |

Optional

| Variable | Default | Description | | ------------------------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | API_PORT | (see text) | If unset, Spire listens on 16777. Set explicitly to override. | | NODE_ENV | (unset) | Set to production to disable interactive /docs / /async-docs. If unset or any other value, doc viewers are mounted. helmet() runs in all modes. | | CORS_ORIGINS | (empty) | Comma-separated allowed Origin values. In production, an empty value rejects cross-origin browser requests; same-origin and native clients are unaffected. Development permits only localhost, loopback, Tauri, and Capacitor origins when unset. | | SPIRE_TRUST_PROXY_HOPS | 0 | Number of trusted reverse-proxy hops. Set 1 for the bundled single-nginx topology. This must match the real network path so clients cannot spoof X-Forwarded-For to evade IP rate limits. | | DEV_API_KEY | (empty) | When set, requests that send header x-dev-api-key with the same value (constant-time compare) skip in-process rate limiters. The same gate enables GET /status/process (404 without a valid key): a small JSON snapshot of the Spire Node process (PID, uptime, memoryUsage, cumulative resourceUsage, WebSocket client count). Dev / load-testing only — never set in production. | | CANARY | (unset) | |

Passkeys / WebAuthn

The /auth/passkey/*, /user/:id/passkeys/*, and /passkey/* routes are gated on SPIRE_PASSKEY_RP_ID and SPIRE_PASSKEY_ORIGINS; without them those endpoints return 500 Passkeys are not configured. Spire also serves the CLI WebAuthn bridge at /cli/passkey, which should be loaded from an origin listed in SPIRE_PASSKEY_ORIGINS so browser passkey ceremonies verify against the same RP config as native clients. See .env.example for the full set, including the optional SPIRE_PASSKEY_IOS_APP_IDS, SPIRE_PASSKEY_ANDROID_PACKAGE, and SPIRE_PASSKEY_ANDROID_FINGERPRINTS triple that makes spire serve the WebAuthn well-known association files (/.well-known/apple-app-site-association, /.well-known/assetlinks.json) directly. Those endpoints 404 when their env vars aren't set, so a non-passkey deployment is indistinguishable from one that hasn't enrolled an app.

The same SPIRE_PASSKEY_ANDROID_FINGERPRINTS value is reused by getRpConfig() to derive android:apk-key-hash:<base64url> entries, which it merges into the WebAuthn expectedOrigin allowlist. Native Android Credential Manager sets clientDataJSON.origin to that string instead of the RP host, so without those entries simplewebauthn rejects every native-Android assertion at the origin check (the mobile UI surfaces this as a generic "RP failed" error). Operators only have to publish the cert fingerprints; the base64url math is handled server-side.

For Docker Compose, place the passkey variables in apps/spire/.env beside SPK and JWT_SECRET; the compose file passes that env file into the spire container. Production should use the production RP host, Android package, and EAS signing-certificate fingerprint. Development should use its own host/package/fingerprint so the dev APK is not authorized by the production association file.

Sample .env

# Run `pnpm --filter @vex-chat/spire gen-spk` and paste the two lines it prints (SPK + JWT_SECRET).
SPK=a1b2c3...
JWT_SECRET=d4e5f6...
DB_TYPE=sqlite
# CANARY=true
# API_PORT=        # unset = 16777 unless you override
NODE_ENV=production

Development

From the monorepo root (or use pnpm <script> from apps/spire/):

pnpm install                                  # install workspace deps
pnpm --filter @vex-chat/spire build           # tsc (sanity check — runtime uses --experimental-strip-types)
pnpm --filter @vex-chat/spire lint            # eslint strictTypeChecked
pnpm --filter @vex-chat/spire lint:fix        # eslint --fix
pnpm --filter @vex-chat/spire test            # vitest run

Workspace-wide commands from root: pnpm test, pnpm lint, pnpm format:check, pnpm -r build.

See the root AGENTS.md and this package's AGENTS.md for the release flow (changesets → publish via OIDC) and the rules for writing changesets.

Outside contributors should follow the root CONTRIBUTING.md (including the CLA).

License

Open source default: AGPL-3.0 (full text; see package.json for SPDX). Commercial licenses from Vex Heavy Industries LLC: LICENSE-COMMERCIAL, LICENSING.md, vex.wtf.