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

@geenius/pricing

v0.17.0

Published

Geenius Pricing — SaaS pricing page components and plan management (React + SolidJS)

Readme

@geenius/pricing

Production-ready FSL pricing plans, comparison tables, billing controls, and admin helpers for Geenius apps.

Installation

pnpm add @geenius/pricing

Imports

import { DEFAULT_PRICING, configurePricing } from "@geenius/pricing";
import { DEFAULT_SAAS_PRICING, sortPlansByOrder } from "@geenius/pricing";
import { PricingTable, PricingPage, usePricing } from "@geenius/pricing/react";
import { PricingTable as CssPricingTable, cx } from "@geenius/pricing/react-css";
import "@geenius/pricing/react-css/styles.css";
import { createPricing, PricingPage as SolidPricingPage } from "@geenius/pricing/solidjs";
import { PricingTable as SolidCssPricingTable } from "@geenius/pricing/solidjs-css";
import "@geenius/pricing/solidjs-css/styles.css";
import { createConvexPricingProvider, schema } from "@geenius/pricing/convex";
import { createNeonPricingProvider } from "@geenius/pricing/neon";
import { createCloudflareKVPricingProvider } from "@geenius/pricing/cloudflareKV";
import { createMemoryPricingProvider } from "@geenius/pricing/memory";

Variant class helpers are intentionally local. @geenius/pricing/react-css exports cx for composing its package-scoped BEM classes, while the React Tailwind variant keeps cn internal and does not export it as portable API. The CSS variants keep .gn-pricing-* class names for selector isolation, but their styles consume the unprefixed --gn-* design tokens from @geenius/tokens.

Usage

Direct (props-driven)

import { PricingTable } from "@geenius/pricing/react";

const plans = [
  {
    id: "starter",
    name: "Starter",
    tier: "starter",
    tagline: "For the first production workflow.",
    monthlyPrice: 2900,
    yearlyPrice: 27840,
    currency: "USD",
    features: [
      { id: "projects", name: "Projects", availability: "included", value: "3 active projects" },
    ],
    limits: { users: 5, projects: 3 },
    order: 0,
    active: true,
  },
];

export function PricingRoute() {
  return (
      <PricingTable
        plans={plans}
        currentPlan="starter"
        onSelect={({ plan, interval, price }) =>
          console.info("upgrade", plan.id, interval, price)
        }
      />
    );
  }

Provider-backed (recommended for full pages)

import { PricingProvider, PricingPage, usePricing } from "@geenius/pricing/react";
import { DEFAULT_SAAS_PRICING } from "@geenius/pricing";

export function App() {
  return (
    <PricingProvider initialPlans={DEFAULT_SAAS_PRICING} initialInterval="yearly">
      <PricingPage onSelect={({ plan, interval }) => startCheckout(plan.id, interval)} />
    </PricingProvider>
  );
}

React + Vanilla CSS

import { useState } from "react";
import { DEFAULT_SAAS_PRICING } from "@geenius/pricing";
import { PricingTable, cx } from "@geenius/pricing/react-css";
import "@geenius/pricing/react-css/styles.css";

export function CssPricingRoute() {
  const [interval, setInterval] = useState<"monthly" | "yearly">("monthly");

  return (
      <PricingTable
        className={cx("pricing-shell", "pricing-shell--css")}
        plans={DEFAULT_SAAS_PRICING}
        interval={interval}
        onIntervalChange={setInterval}
        showComparison
        currentPlan="starter"
        onSelect={({ plan }) => console.info("upgrade", plan.id)}
      />
    );
  }

DB provider wiring

import { DEFAULT_SAAS_PRICING } from "@geenius/pricing";
import { createConvexPricingProvider } from "@geenius/pricing/convex";
import { createNeonPricingProvider, applyPricingMigrations } from "@geenius/pricing/neon";
import {
  createCloudflareKVPricingProvider,
  createMemoryKVNamespace,
} from "@geenius/pricing/cloudflareKV";
import { createMemoryPricingProvider } from "@geenius/pricing/memory";

const memoryProvider = createMemoryPricingProvider({ plans: DEFAULT_SAAS_PRICING });
const convexProvider = createConvexPricingProvider({ client: convexClient });
const neonProvider = createNeonPricingProvider({ executor });
await applyPricingMigrations(executor);

const kvProvider = createCloudflareKVPricingProvider({
  namespace: createMemoryKVNamespace(),
});

Public surface map

| Surface | Import | | --- | --- | | Shared types/utilities | @geenius/pricing | | React (Tailwind, default) | @geenius/pricing/react | | React (vanilla CSS) | @geenius/pricing/react-css + @geenius/pricing/react-css/styles.css | | SolidJS | @geenius/pricing/solidjs | | SolidJS (vanilla CSS) | @geenius/pricing/solidjs-css + @geenius/pricing/solidjs-css/styles.css | | DB providers | @geenius/pricing/{convex,neon,cloudflareKV,memory} |

Themed React, React Native, and themed SolidJS variants may appear in package metadata, but they are deferred until their variants.json entries switch to inScope: true. The current supported matrix is the four UI surfaces listed above plus the four DB providers.

The canonical Cloudflare KV consumer subpath is @geenius/pricing/cloudflareKV. Private workspace metadata may use @geenius/pricing-cloudflare-kv, but application imports and docs should not.

See .docs/DOCS/PACKAGES/PRICING.md for full component / hook / token reference.

Storybook

Pricing follows the V2 Storybook matrix: one stock Storybook v10 app per UI variant under apps/storybook-<variant>/. Use the package scripts to exercise the full app set instead of running only the reference React and Solid apps:

pnpm run test:storybook:build
pnpm run test:storybook

The CSS variants also publish explicit stylesheet entrypoints at @geenius/pricing/react-css/styles.css and @geenius/pricing/solidjs-css/styles.css.

Testing

The package gauntlet is driven by variants.json. Scripts that need package, Storybook, Playwright, size, or coverage fanout read that manifest instead of maintaining their own variant lists.

  • pnpm test:gauntlet runs the PR-blocking source checks, type checks, package tests, publishing checks, size budgets, supply-chain audit, and license check.
  • pnpm test:all extends the gauntlet with Storybook, db conformance, e2e, accessibility, visual, performance, and coverage layers.
  • pnpm test:visual checks the Chromium visual baselines for the in-scope UI variants.
  • pnpm test:mutation runs the Stryker mutation pass for pure logic and is intended for the slower scheduled lane.

Contributing tests

Add or update variants in variants.json first, then add the variant source package, Storybook app, and e2e coverage that the manifest points to. Do not hardcode variant arrays in scripts, Playwright config, package scripts, or tests; import scripts/_variants.mjs or use the existing helper scripts.

When adding behavior, cover the nearest subpackage unit tests first, then add root parity or packed-smoke assertions if the change affects public exports, subpaths, or variant alignment.

License

FSL-1.1-Apache-2.0. See LICENSE.