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

@forgeco/ext-subscriptions

v0.3.2

Published

Forge extension (SUBSCRIPTIONS): sells a recurring order. The shopper picks a delivery rhythm on the product page (the app's declared `sub_plan` cart-line custom field) and may change it in the checkout summary; the app keeps a CONTRACT of its own — custo

Readme

@forgeco/ext-subscriptions

Recurring purchases as contracts. A shopper picks a delivery rhythm on the product page; each cycle fabricates a normal order — never a recurring one — carrying the mark of the subscription and the cycle it came from.

What the app is, in three faces

  • The engine. A contract of the app's own — customer, store, items, rhythm, next delivery, cycle counter — born from the KERNEL's frozen order line, plus the scheduled run and the idempotency on (contract, cycle).
  • The merchant's screen. A whole admin page the app owns (APP-ADMIN-PAGE): every contract with a status filter, one contract's cycle history with a link to the order each cycle made, and the action that runs a contract's next cycle.
  • The shopper's screens — the half this package publishes: a "buy once × subscribe" picker under the buybox, and a per-line rhythm switcher inside the checkout summary.

The front half — what this package ships to a customer's storefront

import { PlanPickerBlock } from '@forgeco/ext-subscriptions/block/plan-picker';
import { CartPlansBlock } from '@forgeco/ext-subscriptions/block/cart-plans';

Both stand on the kernel and invent nothing. The shopper's choice rides the cart line's own declared custom field (sub_plan), which buys two properties no code here implements:

  • cart.add_line aggregates by sku + custom fields, so the same coffee bought once and subscribed monthly are two lines by construction — a mixed cart needs no special case;
  • checkout.place_order snapshots a line's custom fields into the order line, so the order that is born already carries the rhythm, immutably — which is what the engine mints the contract from.

Changing a rhythm at the checkout is therefore a migration of the line (remove + add), never an edit: the line the shopper wants does not exist yet, and the one they have must stop existing.

What is subscribable — the merchant curates, one SKU at a time

Installing this app makes nothing subscribable. The rhythms are the STORE's (frequencies, the app config), but the OFFER is the SKU's: PlanPickerBlock draws nothing unless the SKU the page is about carries the mark sub_enabled = true in its own metadata bag. Absent, false, null, the string "true" — none of them is a mark. Default false, so a live catalogue does not sprout a subscription control on every product page the moment the app arrives.

The mark is on the SKU, not the product, because a SKU is what is bought: a 250 g bag on a monthly rhythm and a 1 kg sack nobody wants monthly are two SKUs of one product. The picker follows the shopper's variant for free — the product page's selector navigates to ?sku=<code> and the block reads the mark of the SKU that ?sku= names, in the same render that changes the price.

Marking is data, so it goes through the port like any other SKU data — which is also how a merchant marks three hundred of them:

catalog.sku.update { sku_id: "sku_…", metadata: { "sub_enabled": true } }

Why the scope moved to @forgeco/*

This package was @forge/* and private while it carried only the admin face, and its own README said the reason out loud: "nothing here is installable yet… when the engine lands, the app joins the composition list and the scope moves with it." Both happened. The app is in the composition list and it now ships storefront blocks, which are exactly the thing a customer who forks the vitrine has to be able to install. The extension id (subscriptions) is runtime identity and never moved.

The admin half travels in the image and is deliberately absent from publishConfig.exports: an app's admin screen is not something a storefront installs.

Next 15.2 or newer

The next peer range starts at 15.2.0, the same floor every front package in this set declares.

Install

The Forge packages are published as tarballs on the GitHub Release, so install them together — they resolve each other from the sibling files, not from a registry:

npm i ./forgeco-contracts-<version>.tgz ./forgeco-ext-*-<version>.tgz

⚠️ One required line in next.config

This package ships its components as source (.tsx + CSS Modules), so your bundler compiles them along with your own code — that is what keeps the styles, the tokens and the tree-shaking working. Next skips node_modules unless you say otherwise:

// next.config.mjs
export default {
  transpilePackages: ['@forgeco/ext-subscriptions'],
};

Without it the build fails loudly (Module parse failed: Unexpected token) — it never degrades into an unstyled page.

The blocks style themselves in semantic design tokens, never literal colours, so install @forgeco/theme-storefront-vanilla (or provide the same token names from your own theme) and import its tokens.css once in your root layout.

What it does NOT do

  • No discount is applied from the subscriber percentage. The number is stored on the contract for a merchant migrating in, and no surface in this package renders it as money off. A merchant who wants the subscribed line discounted creates a promotion targeting the line's own custom field sub_plan (target: { kind: custom_field, … }) — money said by the kernel's promotion engine, never by this app. See docs/concepts/promocao-por-campo-proprio.md.
  • It never invents a charge mandate. It stores no card. See the two cycle modes in config.ts.

Licence

Apache-2.0. The Forge kernel itself is BUSL-1.1; what you install and compile against is permissive on purpose — your storefront code is yours.