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

lightbase-edge

v0.1.11

Published

The one-liner: full-Node SSR on Cloudflare Pages with ZERO Cloudflare Workers. Drop into any codebase — bundles your server, publishes it to your own Pages CDN, registers a sha-pinned auto-deploy manifest with Lightbase, and generates the preflight-free z

Readme

lightbase-edge — the one-liner (v0.1.1, production/enterprise posture)

BismiLLAH Ar-Rahman Ar-Raheem. Drop this into any codebase and get full-Node SSR on Cloudflare Pages with ZERO Cloudflare Workers. Developers just code normally — no edge-function setup, no codebase changes beyond the build step. Lightbase edge does ALL the server-side work; Cloudflare Pages serves static assets unmetered from its CDN.

Quick start (drop-and-forget)

npm i -D lightbase-edge
npx lightbase-edge init          # detects your framework, wires package.json

init writes lightbase.edge.json and wires your scripts:

"scripts": {
  "lb:deploy": "lightbase-edge deploy",
  "postbuild": "lightbase-edge deploy"
}

From then on, npm run build is the only command you ever run — the postbuild hook bundles, publishes and registers automatically. Without the Lightbase env vars (a plain local build) the hook skips gracefully; on Cloudflare Pages CI it deploys. Set these once in the Pages UI (Settings → Environment variables — editable anytime, never baked into Git):

LIGHTBASE_URL=https://<lightbase-host>
LIGHTBASE_PROJECT_ID=<your-project-id>
LIGHTBASE_DEPLOY_TOKEN=lb_deploy_…        # deploy-scope key (or admin key)
# optional:
LIGHTBASE_EDGE_ENV={"SECRET":"value"}     # server-side-only app env (JSON string)
LIGHTBASE_EDGE_APP_ID=<app-id>            # overrides lightbase.edge.json appId
PUBLIC_SITE_URL=https://<your-pages-url>  # when building outside CF Pages CI

CF Pages build command: npm run build (that's all). GitHub CI is optional — Pages' Git integration builds on every push; without any CI you can run the same build anywhere and npx wrangler pages deploy <staticOut>.

The contract

| You write | What ships | Who runs it | |---|---|---| | A normal Node SSR app (Astro output:'server' + node adapter, Next output:'standalone', Express, Koa, plain http.createServer) | a portable CJS bundle published as static files on your own Pages deployment (/_lb/<app>/<hash>/server.js) | Lightbase edge — fetched at request time, sha256-pinned, executed in a hardened worker runtime; cached in RAM (never on instance disk) | | Nothing else | _redirects + a universal shell + a service-worker reverse proxy | Cloudflare Pages CDN — static layer only, ZERO Workers quota |

lightbase.edge.json — full field reference

Written by init, safe to hand-edit. Every field is optional unless noted.

| Field | Type | Default | Meaning | |---|---|---|---| | appId | string (required) | from LIGHTBASE_EDGE_APP_ID or folder name | Stable app id ([a-z0-9-]). The manifest key on Lightbase and the /_lb/<appId>/ CDN path. | | framework | string | auto-detected | astro | next | nuxt | express | custom. Drives defaults only. | | entry | string | per framework | Path of the BUILT server entry (input to esbuild). Astro: dist/server/entry.mjs; Next: .next/standalone/server.js. | | staticOut | string | dist | The folder that becomes your Pages deployment root. Everything Pages should serve must end up here. | | clientDir | string | — | Astro standalone crucial setting: your build emits client assets into dist/client and the server into dist/server. Set "clientDir": "dist/client" and "staticOut": "dist-pages" — the deploy assembles dist-pages = client assets at the ROOT + /_lb/<app>/<hash>/server.js + bridge files. | | assetPrefixes | string[] | framework defaults | Path prefixes served by the Pages CDN (bypass the SW reverse proxy). Astro defaults: /​_astro/, /fonts/, /images/, /favicon. The deploy also auto-derives every top-level file/dir of staticOut as a prefix. | | name | string | appId | Human name registered on Lightbase. | | corsOpen | boolean | false | true = the SSR gateway answers any Origin (public demos). Keep false for production — origins are pinned automatically to your Pages URL. | | timeoutMs | number | 30000 | Per-request SSR wall clock (max 300000). | | enforced | boolean | false | true = deploy FAILS instead of skipping when Lightbase env vars are absent (use on required-deploy CI). |

Real-world Astro example (as used by all production integrations)

{
  "appId": "my-app",
  "name": "My App",
  "framework": "astro",
  "entry": "dist/server/entry.mjs",
  "staticOut": "dist-pages",
  "clientDir": "dist/client",
  "assetPrefixes": ["/_astro/", "/fonts/", "/images/", "/favicon", "/icons/"],
  "timeoutMs": 60000
}

And the matching astro.config.mjs:

import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
  output: 'server',
  adapter: node({ mode: 'standalone' }),
});

Astro emits dist/client/ + dist/server/; the postbuild hook assembles the Pages root (dist-pages) automatically. In the CF Pages UI, set the build output directory to your staticOut (e.g. dist-pages).

postbuild settings — the automatic part

init wires (and never clobbers an existing chain):

"scripts": {
  "build": "astro build",
  "postbuild": "lightbase-edge deploy"
}
  • Existing postbuild chains are preserved: "<old> && lightbase-edge deploy".
  • npm run build on CF Pages → build → deploy → bridge generation, in one CI pass. New bundle hash ⇒ sha-pinned manifest update ⇒ instant real-time update on the edge (no waiting, no baking).
  • Local builds without Lightbase env vars print one line and exit 0.

Is hosting the bundle on my own Pages CDN secure? (yes — by design)

https://<app>.pages.dev/_lb/<app>/<hash>/server.js is a compiled bundle of your own SSR app, served as a static file from YOUR deployment:

  1. No secrets inside. Env/secrets never enter the bundle — they ride LIGHTBASE_EDGE_ENV (or the manifest env), are sealed AES-256-GCM at rest on Lightbase, and are injected only into the sandbox at execution. Root keys stay server-side; the bundle is exactly as sensitive as the client JS you already ship.
  2. Same trust level as your own static site. It is your code, on your origin, under your deployment's access controls. There is no third-party bucket involved — the CDN path is your own domain.
  3. sha256-pinned, fail-closed. Lightbase fetches files by hash and verifies every byte; a tampered or stale CDN file simply never executes.
  4. Not executable in the browser. It is a Node CJS server bundle (require, node builtins) — browsers cannot run it meaningfully; it is input to the Lightbase worker runtime only.
  5. Enterprise posture. The execution sandbox has no disk, no network sockets beyond the host-provided fetch, no child_process, no worker_threads; per-request wall clocks; adaptive memory gates with relief (never usage caps); every manifest path is traversal-proofed (relative, no ..); origins are allowlisted per app.

This is exactly the posture an Enterprise-grade financial platform needs: secrets server-side, code integrity hash-pinned, zero Workers to audit, and your CDN serves only your own code.

How the zero-Workers SSR bridge works

  1. First visit: Pages serves the shell (CDN-fast, branded loader). The bootstrap fetches the SSR HTML for the current path from the Lightbase gateway (one resilience retry), swaps the FULL document in (head + body, scripts re-instantiated → frameworks hydrate normally), and — in parallel — runs the parse-guard: /sw.js is verified to really be the Lightbase bridge before registration; a stale PWA service worker from an older deployment is unregistered + its caches cleared with one clean reload (no white pages, no ghosts).
  2. Every request after that: the service worker reverse-proxies the request to the gateway with full fidelity — method, body, status codes, redirects (rewritten same-origin so login flows follow correctly), and a durable cookie jar (IndexedDB inside the worker, survives restarts). Static assets bypass the worker and hit the Pages CDN. A network hiccup answers a self-reloading 503 instead of a hard error.
  3. Zero Cloudflare Workers anywhere: the Pages project is a static project (_redirects is asset-layer routing; the service worker runs in the browser, not on Cloudflare).

Wire protocol (preflight-free)

Some PaaS gateways (Zoho Catalyst AppSail among them) intercept CORS OPTIONS preflights at the edge and answer them without Access-Control headers — any browser fetch carrying a custom header dies in preflight (the symptom: blank pages). The bridge therefore sends ONLY CORS-safelisted requests and tunnels everything else through query parameters the gateway strips:

| Tunnel | Meaning | Example | |---|---|---| | __lbjar | the app's cookie jar (encoded) | __lbjar=sid%3Dabc%3Btheme%3Ddark | | __lbmethod | effective HTTP method (PUT/PATCH/DELETE ride a POST) | __lbmethod=DELETE | | __lbct | real content-type (JSON travels as text/plain) | __lbct=application/json |

Native headers still win when present, so server-to-server callers are unaffected. The legacy x-lb-cookie header path is unchanged.

Commands

npx lightbase-edge init     # detect framework → write lightbase.edge.json + wire scripts
npx lightbase-edge build    # esbuild the server entry → portable CJS bundle
npx lightbase-edge deploy   # bundle + publish + register + bridge (the one-liner)
npx lightbase-edge status   # app status + stats from Lightbase
npx lightbase-edge logs     # tail the app's structured log ring

What deploy does (fully automatic)

  1. esbuild-bundles the server entry → portable CJS (node builtins external).
  2. Assembles the Pages root: client assets at the ROOT + the bundle under _lb/<app>/<hash12>/ (hash-versioned directory — instant real-time updates, free rollback history, no CDN staleness).
  3. Registers the sha-pinned manifest with Lightbase (auto-deploy — new content hash ⇒ instant cache invalidation everywhere).
  4. Derives static asset prefixes from your build output (so the service worker knows exactly what is CDN-static vs SSR-dynamic).
  5. Generates the bridge files (_redirects, shell index.html, sw.js) LAST — they win any public/ collision (e.g. an old PWA service worker).

Framework checklist

| Framework | Requirement | |---|---| | Astro | output: 'server' + @astrojs/node({ mode: 'standalone' }); set clientDir: "dist/client" + a dedicated staticOut | | Next | output: 'standalone' | | Express / Koa / custom | set entry in lightbase.edge.json to your server file | | Nuxt | nitro node-server preset (entry = .output/server/index.mjs) |

Honest limits

  • The very first visit needs JS (the shell is a CDN page); after that the service worker serves true SSR documents. JS-rendering crawlers — including Googlebot — index the SSR content.
  • WebSockets are not bridged (SSE streams fine).
  • Third-party-cookie browsers are unaffected: the cookie jar is first-party (localStorage + IndexedDB), never cross-site.