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

foldkit-plus

v0.18.0

Published

Every Foldkit Plus package in one install, `npx foldkit-plus setup`, which tells a coding agent how to start, and `npx foldkit-plus docs`, which answers from the installed docs.

Readme

foldkit-plus

Every Foldkit Plus package in one install, and a setup command for your coding agent.

What it is

Foldkit Plus is a family of packages that extend a Foldkit application to agents, servers, other devices, the URL and design systems without a second place to keep state. Each is published on its own (foldkit-remote, foldkit-sync, …). This package depends on them, so one install brings the set, and re-exports each:

foldkit-remote              ->  foldkit-plus/remote
foldkit-remote/port         ->  foldkit-plus/remote/port
foldkit-remote-server       ->  foldkit-plus/remote-server
foldkit-mixins/theme        ->  foldkit-plus/mixins/theme

A subpath is the package itself, re-exported: foldkit-plus/remote's Remote is foldkit-remote's, so the two can be mixed in one application. This package owns no state and adds no runtime API of its own: what each package owns is in its own guide. What it adds is the setup and docs commands, and two subpaths for testing a running application.

Setup

npx --legacy-peer-deps foldkit-plus setup

Tell your agent to run that in your project. It writes nothing: it prints, for that project, what the agent should run, in order:

  1. Check the project. It reads your package.json and says when effect or foldkit is missing or at a version this release does not support. When no .gitattributes applies to the project, it gives one that keeps text files LF (* text=auto eol=lf), so a Windows checkout does not warn of every file; one the project has is left as it is.
  2. Install Effect, Foldkit and Foldkit Plus with the package manager the project uses, after the version pins described under Versions, and the command that adds each adapter.
  3. Add the agent skill, and paste its AGENTS.md block into the project.
  4. Import: which package does which job.

--legacy-peer-deps only stops npx installing the package's peers beside it, which the CLI never reads (it carries everything it runs on): npx adds a newer foldkit-plus to the tree an older one left in its cache, and their peers' Foldkit versions clash (ERESOLVE) where none is needed.

For a new application, run it in an empty folder. With no package.json it sends the agent to the skill's greenfield guide: ask about the goals, the look (a theme designed at /create) and the domain first, record the answers in the project, map them to these packages with you, plan the architecture, performance, SEO, testing, CI and deployment, and build once you agree. It prints the create-foldkit-app command, at the release that installs this release's Foldkit, for when it is time to scaffold.

Import

The namespaces most applications use come from the root:

import { Projection, Remote, Surface, Sync } from 'foldkit-plus'

The root holds Agent, Bundle, Entity, Expr, Order, Query, Relation, Form, Mirror, the Mixins vocabulary (Style, Slot, Slots, SlotView, Behavior, Capability, Event), Remote, RemoteClient, RemoteData, RemotePolicy, Site, Surface, Projection, MessageSet, Sync, DocumentId and ReplicaId. A name two packages export is left to their subpaths, so nothing at the root is ambiguous. Nothing at the root runs only on a server: import foldkit-plus/ssr, foldkit-plus/remote-server or foldkit-plus/durable where the server is.

What it does not install: adapters

A package that needs a library of its own is an optional peer here, so installing foldkit-plus installs none of those libraries. Its subpath works once you add it with its library:

| Adapter | Library | For | | --- | --- | --- | | foldkit-react | react, react-dom | React interop | | foldkit-react-codegen | typescript | Views compiled to React TSX | | foldkit-remote-drizzle | drizzle-orm | Remote reads answered with Drizzle | | foldkit-cms-drizzle | drizzle-orm | The CMS's server on Drizzle | | foldkit-auth | @yielded/auth | Sign-in and sessions with Yielded Auth | | foldkit-mixins-ui | @foldkit/ui | @foldkit/ui components styled through slots | | foldkit-richtext-code-shiki | shiki | Code blocks highlighted with Shiki | | foldkit-agent-native | @agent-native/core | Agents through Agent Native |

setup lists them with the command that adds each, at the library version the adapter peers on.

foldkit-media is installed, but two of its subpaths need a library that is not: foldkit-plus/media/sharp needs sharp, and foldkit-plus/media/unpic needs unpic.

Docs for the versions you have

npx foldkit-plus docs Data.preload        # a symbol: its declaration and its sections
npx foldkit-plus docs "optimistic delete" # words: the three best sections
npx foldkit-plus docs --list remote       # one topic's headings, with line numbers

docs answers from what is installed in the project it runs in, so it describes the versions the application has, not main. It reads the README of each Foldkit Plus package that an import from the project would load (one the project names from its own folder; the rest from beside foldkit-plus), the foldkit-plus skill if it is installed in a dot-folder's skills/ (the project's, its repository's, or the home folder's), and for a symbol the package's .d.mts. Each section comes with its file and line, so the rest is one read away. Nothing is indexed ahead of time and nothing is fetched. --json prints the same for a program. A query that matches nothing, a project with no Foldkit Plus package, or one whose package.json names a package that is not installed exits 1 and says which.

Testing a running application

Two subpaths of this package's own drive the tools an application tests with. Those tools are optional peers too: add them as dev dependencies, and a subpath that needs one it cannot find says which.

| Subpath | Needs | For | | --- | --- | --- | | foldkit-plus/testing/workers | wrangler, esbuild | Stack.start: the Worker on a local workerd, configured by its own wrangler.toml, with fresh migrated D1 per stack; Stack.writeBundle: the same bundle where main says, for wrangler deploy | | foldkit-plus/testing/playwright | playwright (types) | Behaviors: a write shows while it is held at the network and after its answer (optimistic), a text never shows during some steps, even for one frame (neverShows), and the page's errors (consoleErrors) |

import { Stack } from 'foldkit-plus/testing/workers'

const stack = await Stack.start<Env>({
  wrangler: 'wrangler.toml', // bindings, compatibility date and flags, D1 migrations
  entry: 'src/worker.ts', // bundled into what `main` names; `no_bundle = true`
  vars: origin => ({ ORIGIN: origin }), // or a plain record; a function is given the stack's origin
})
await fetch(stack.origin)
stack.logs() // what the Worker wrote to its console since the last call; also printed as it arrives
await stack.stop()

The Worker's console is printed here as it arrives, each line with Node's console method of its level and prefixed [worker], so a 500 shows the error behind it with its stack; console: 'quiet' keeps the lines for logs() alone. The lines travel beside the response, not on it, so a test reading what one request wrote polls (expect.poll(() => stack.logs())).

stack.watch({ onSwap, onRefused, onStopped }) is the dev loop. It rebuilds on every change to a file the bundle read, and rereads wrangler.toml when it changes. Each change is started first on a workerd of its own, with fresh storage and its D1 migrated. Only a change that starts is swapped in at the same origin, over the same D1, R2 and Durable Object storage, and the migrations not yet applied are applied. A change that does not build, or builds a Worker that does not start, or a configuration the stack refuses, goes to onRefused, and the Worker running keeps answering. onStopped is the rest: a swap that failed after its trial started, which takes Wrangler's harness down with its storage.

import { Behaviors } from 'foldkit-plus/testing/playwright'

const errors = Behaviors.consoleErrors(page)
await Behaviors.neverShows(page, {
  text: 'Loading…',
  during: () =>
    Behaviors.optimistic(page, {
      act: () => page.getByRole('button', { name: 'Add' }).click(),
      shows: page.getByRole('button', { name: 'Buy milk', exact: true }),
    }),
})
expect(errors()).toEqual([])

These check the drawn page over the real network. consoleErrors lists console.error and uncaught exceptions, which includes every error diagnostic the default Diagnostics reporter logs. To find which Message makes a read blink, foldkit-plus/remote/testing's Trace runs update and Remote's Subscriptions without a browser and records every Model. examples/cloudflare uses both subpaths.

Versions

effect and foldkit are peers: this release targets Effect 4.1 (^4.1.0) and Foldkit 0.170, and setup installs the Foldkit and the Effect this repository tests (package.json's setup field). Foldkit and its Vite plugin take one Effect minor (~4.1.0), and each @effect/* release peers on an effect at least its own, so setup first has the project pin every Effect package to the tested one, which keeps one copy of each:

  • npm: overrides, and the project's own Effect dependencies set to the same release, since npm overrides a direct dependency only where the project names that version;
  • pnpm: overrides with peerDependencyRules, at the workspace root, the only place pnpm reads them (its pnpm-workspace.yaml, or its package.json where that already holds a pnpm field);
  • Yarn: resolutions; Bun: overrides.

That also holds foldkit-durable's @effect/sql-sqlite-node, whose every release peers on an effect at least its own version. Each release of foldkit-plus pins the release of every package it brings, so the set is one tested combination; the release matrix lists them.

In this repository

The re-exports, the manifest's exports and dependencies, and the tsconfigs' references are generated from the workspace:

pnpm --filter foldkit-plus generate   # then pnpm install and pnpm paths

test/generated.test.ts fails until it has run after a package or an entry point is added, moved or removed, and when the setup guide's list of adapters or jobs leaves a package out.