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

@orion-studios/cms

v0.5.3

Published

Orion CMS v2 core engine — JSONB content model on Supabase primitives

Readme

@orion-studios/cms

Orion Studios' CMS engine: a single package that turns a custom Next.js site into a client-editable site. JSONB content on Supabase, a self-contained Studio admin, and a block system where one definition drives everything.

  • No schema migrations for content changes. Pages are JSONB layouts; the eight cms_ tables never change when you add or edit block types.
  • defineBlock() is the single source of truth. A Zod schema + a React component per section type produces: TypeScript types, validation, defaults, the builder palette, the editing panel, inline click-to-edit, and the public-site renderer.
  • Three runtime modes, chosen by env: supabase (production), memory (zero-setup dev/demo, in-process store), static (no CMS at all — renders from site-content.ts; how sites launch before a client buys the CMS).

Install

npm install @orion-studios/cms

Requires Next.js (App Router), React 19, Zod 3. Supabase only in supabase mode.

Entry points

| Import | Contents | | --- | --- | | @orion-studios/cms/blocks | defineBlock, defineGlobal, createBlockRegistry, createGlobalRegistry, field helpers (link, mediaRef, paragraphs), BlockPreviewProps, BlockData | | @orion-studios/cms/server | createCmsRoutes (the whole API as one catch-all route), getServiceClient, resolveUser, runContentSync, getMemoryCms, permission matrix (can, roles) | | @orion-studios/cms/studio | Studio (the full admin UI), LoginView, PasswordInput, UsersView, createStudioApi | | @orion-studios/cms/content | createContentClient — anon-key reads for the public site (getPageByPath, listPublishedPaths, getGlobal) | | @orion-studios/cms/forms | Form config types, processSubmission (validation, honeypot, rate limiting), shared SiteForm renderer | | @orion-studios/cms/sql/bootstrap.sql | The complete idempotent schema (tables, RPCs, RLS, grants) | | @orion-studios/cms/studio/styles.css | Studio styles (self-contained, ost- prefixed) |

The 5-minute wiring (already done in the site template)

// src/app/api/cms/[...path]/route.ts — the entire CMS API
import { createCmsRoutes } from '@orion-studios/cms/server'
import { registry } from '@/cms/registry'
export const { GET, POST, PATCH, DELETE } = createCmsRoutes({
  registry, syncToken: process.env.CMS_SYNC_TOKEN,
})

// src/app/studio/page.tsx — the admin
import { Studio } from '@orion-studios/cms/studio'
import '@orion-studios/cms/studio/styles.css'
export default function Page() {
  return <Studio registry={registry} globals={globals} siteName="Client Co" logoUrl="/logo.png" />
}

Don't start here for a new site — copy templates/site from the orion-cms-packages repo instead; it has all of this wired plus the scripts (bootstrap, create-admin, sync). See NEW-SITE-PLAYBOOK.md at the repo root for the full procedure.

Roles

Four tiers, enforced in the API (src/server/permissions.ts), UI adapts:

  • content — edit text/images on existing sections (no add/remove/reorder)
  • editor: full content control including structure, new pages, exact-version publish, submissions, detailed analytics, and replacement of existing media
  • admin — everything + user management (Users panel in the Studio)
  • developer — full access; the tier Orion Studios keeps for itself

Rank rules: you can only assign roles at or below your own, never change your own role, never delete yourself.

Environment

| Variable | Where | Purpose | | --- | --- | --- | | NEXT_PUBLIC_SUPABASE_URL | local + Vercel | project URL (also selects supabase mode) | | NEXT_PUBLIC_SUPABASE_ANON_KEY | local + Vercel | public reads (RLS: published content only) | | SUPABASE_SERVICE_ROLE_KEY | local + Vercel | server-only; powers the API layer | | DATABASE_URL | local + Vercel | Postgres for bootstrap (use the transaction pooler on Vercel) | | CMS_SYNC_TOKEN | local + Vercel | authorizes POST /api/cms/sync | | CMS_STATIC=true | optional | static mode (no CMS) | | CMS_MEMORY=true | optional | force memory mode |

The memory backend is privileged only outside production. In production it can serve public ephemeral forms and events, but it rejects Studio and guarded routes, the fixed development token, preview fallback, sync, publish cron, notification email, and user management. NEXT_PUBLIC_CMS_MEMORY and other public flags cannot enable the development credential.

Publication contract

Draft title, SEO, and layout are saved together as one immutable page version. Manual publish requires that version's current draft_version_id. Scheduling stores the selected version ID and later draft edits do not change what will go live. A missing, stale, foreign, or already-published version fails with 409. Content roles may create media and edit its metadata. Only editor, admin, and developer roles may replace an existing file or read submissions and detailed analytics.

Run the additive SQL migrations in filename order before deploying code that calls the exact-version RPCs. bootstrap.sql has the same final schema, functions, grants, and published-metadata backfill for new projects. If a release fails after the migration, keep the fail-closed RPCs and roll forward. Do not restore the old mutable publish signature.

Development

npm run typecheck && npm test   # 24 node:test suites
npm run build                    # tsup → dist/
npm pack                         # tarball for vendoring / inspection

The SQL bootstrap is idempotent and runs under restricted Postgres roles: it avoids auth-schema privileges and explicitly grants the PostgREST roles (service_role, anon, authenticated) table access — RLS policies filter rows but do not grant access, and Supabase's default privileges only cover postgres-created tables.