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

@symbo.ls/channels

v3.14.678

Published

Symbols platform API/socket channel URLs — single source of truth across sdk, smbls, server, editor, workspace, platform.

Readme

@symbo.ls/channels

Single source of truth for the Symbols platform's per-channel URLs. Every consumer (sdk, smbls, server, editor, workspace, platform, mermaid, preview, CI workflows) resolves channels through this package — no hardcoded https://*.symbols.app / *.symbo.ls literals anywhere else.

channels.json is the schema; index.js exposes accessors. Build-time consumers that can't import JS (Cloudflare wrangler.toml, k8s values.yaml) template the JSON via server/scripts/sync-channels.mjs and CI runs --check to catch drift.

Channels

| Channel | api | shell | preview | mermaidApex | deploy targets | | ------------- | ---------------------------------- | --------------------------------- | -------------------------------------- | ------------------- | ----------------------------------------------------------------- | | local | http://localhost:8080 | http://my.localhost:1355 | http://preview.localhost:1355 | localhost:1355 | — | | development | https://dev.api.symbols.app | https://dev.my.symbols.app | https://dev.preview.symbols.app | dev.symbo.ls | smbls-my-dev, smbls-preview-dev, mermaid-dev | | next | https://next.api.symbols.app | https://next.my.symbols.app | https://next.preview.symbols.app | next.symbo.ls | smbls-my-next, smbls-preview-next, mermaid-next | | test | https://test.api.symbols.app | https://test.my.symbols.app | https://test.preview.symbols.app | test.symbo.ls | smbls-my-test, smbls-preview-test, mermaid-test | | upcoming | https://upcoming.api.symbols.app | https://upcoming.my.symbols.app | https://upcoming.preview.symbols.app | upcoming.symbo.ls | smbls-my-upcoming, smbls-preview-upcoming, mermaid-upcoming | | staging | https://staging.api.symbols.app | https://staging.my.symbols.app | https://staging.preview.symbols.app | staging.symbo.ls | smbls-my-staging, smbls-preview-staging, mermaid-staging | | production | https://api.symbols.app | https://my.symbols.app | https://preview.symbols.app | at.symbo.ls | smbls-my-prod, smbls-preview, mermaid |

Default channel: next (set via defaultChannel in channels.json).

socketUrl mirrors apiUrl for every channel (the API server fronts both HTTP and WebSocket).

Usage

import {
  apiUrl,
  socketUrl,
  shellUrl,
  previewUrl,
  mermaidUrl,
  deployTarget,
  currentChannel,
  resolveChannel,
  channelNames,
  isKnownChannel,
  defaultChannel,
} from '@symbo.ls/channels';

apiUrl(); // → 'https://next.api.symbols.app' (defaultChannel)
apiUrl('production'); // → 'https://api.symbols.app'
socketUrl('staging'); // → 'https://staging.api.symbols.app'
shellUrl(); // → 'https://next.my.symbols.app'
previewUrl('production'); // → 'https://preview.symbols.app'

// Per-project hosted URL — composes user-env + system-channel.
mermaidUrl({ owner: 'toko', key: 'myapp' });
// → 'https://toko--myapp.next.symbo.ls' (current channel = next)
mermaidUrl({ owner: 'toko', key: 'myapp', env: 'staging' }, 'production');
// → 'https://toko--myapp--staging.at.symbo.ls'

deployTarget('next'); // → { shellBucket, previewWorker, mermaidWorker }
currentChannel(); // → 'next' (or env override)
resolveChannel('test'); // → full channel record from channels.json

Mermaid URL composition

mermaidUrl({ owner, key, env? }, channel?) returns the canonical project hosting URL:

{owner}--{key}[--{userEnv}].{mermaidApex}

Two-level env model:

  • user env (env) — the project's published environment slot (production is the default and is omitted from the label; staging, development, custom names are appended as --{env}).
  • system env (channel) — the platform channel currently in scope. Resolved from NODE_ENV / defaultChannel.

Owner+key are joined with -- into a single DNS label because wildcard certificates only match one label deep (RFC 4592). One *.{apex} cert per channel covers every project under that channel — no per-project DNS provisioning.

Examples (system production apex at.symbo.ls):

toko + myapp                        → toko--myapp.at.symbo.ls
toko + myapp + env=staging          → toko--myapp--staging.at.symbo.ls
toko + myapp + system=next          → toko--myapp.next.symbo.ls
toko + myapp + env=staging + next   → toko--myapp--staging.next.symbo.ls

Resolution order

For apiUrl() / socketUrl() / shellUrl() / previewUrl() / mermaidUrl():

  1. Explicit name argument (apiUrl('staging'))
  2. NODE_ENV (the deploy-time signal CI passes — production/staging/development/test/next/local map 1:1)
  3. defaultChannel from channels.json

Direct URL overrides (always win, even over an explicit channel name):

  • SYMBOLS_API_URL — overrides apiUrl() output
  • SYMBOLS_SOCKET_URL — overrides socketUrl() output

These escape hatches exist for local proxies, ngrok tunnels, and per-process mirrors. They never persist into committed config.

Switching the default channel

One line. To flip the whole monorepo from nextproduction:

// channels.json
- "defaultChannel": "next"
+ "defaultChannel": "production"

Bump the version (X.Y.0X.Y.1 for an existing-channel URL change, X.(Y+1).0 for a channel add/remove), reinstall at the monorepo root to re-link, redeploy.

Adding a new channel

  1. Add the entry in channels.json with api, socket, shell, preview, mermaidApex, and deploy (shellBucket, previewWorker, mermaidWorker).
  2. Bump version (minor — schema add).
  3. Reinstall at the monorepo root.
  4. Run server/scripts/sync-channels.mjs to refresh the templated wrangler.toml / values.yaml files.

If a consumer references a channel that doesn't exist in channels.json, resolveChannel(name) falls back to defaultChannel. To fail loud instead, gate with isKnownChannel(name) first.

Consumers

| Package | Import path | What it uses | | ----------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- | | @symbo.ls/sdk | import { apiUrl, socketUrl } from '@symbo.ls/channels' | Per-env URL lookup in sdk/src/config/environment.js | | @symbo.ls/cli (smbls) | same + mermaidUrl, previewUrl, currentChannel | bin/start.js, bin/publish.js — published / dev preview link output | | @symbo.ls/server-config | apiUrl, socketUrl | api.publicBaseUrl default in loader.js | | @symbo.ls/screenshot | apiUrl | API_BASE fallback | | @symbo.ls/tauri | apiUrl, socketUrl | Desktop-app prod default | | editor / workspace / platform | full surface | Runtime config injection, cross-app deep links | | mermaid / preview workers | deployTarget, mermaidUrl | Build-time bucket/worker name; per-project URL self-discovery | | CI deploy workflows | deployTarget(NODE_ENV) | Bucket / worker upload destination — kept aligned with channel resolve |

What does NOT belong here

  • Per-channel auth/secret material (JWT keys, DNS API keys, Supabase service tokens) — those stay in env vars / k8s secrets / wrangler secrets.
  • Per-channel auxiliary URLs that aren't channel-shaped (kvUrl, dnsWorkerUrl, grafanaUrl, typesense*, githubClientId) — those stay in their respective per-env config blocks (sdk's environment.js, server's config/<env>.js).
  • CORS allowlists — server's per-env config files compose channel hosts plus server-private allowlist additions.

The package's job is exactly the URL+target shape per channel. Nothing else.

Wrangler / Helm / k8s

Build-time consumers (Cloudflare Workers wrangler.toml, k8s values.yaml) can't import JS at deploy time. For those, run server/scripts/sync-channels.mjs which reads channels.json and templates the generated config files. CI runs --check to catch drift between committed wrangler/helm files and the channel source of truth.