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

@nascencestudio/tapestry

v0.4.0

Published

Drag-and-drop component page building for Astro + StudioCMS

Readme

@nascencestudio/tapestry

Drag-and-drop, component-based page building for Astro + StudioCMS.

Register your own Astro components with a typed prop schema; editors compose pages from them in the StudioCMS dashboard on a live canvas of the real page. Pages are stored as validated JSON and rendered on the server as your components, with no client JavaScript unless a component opts in.

  • Visual canvas with drag and drop, inline text editing, keyboard navigation
  • Drafts, publishing, scheduled publishing, version history and comparison
  • Rich text (ProseMirror, per-field toolbars), links, media (with @nascencestudio/medialibrary), lists and objects, named slots
  • Patterns (saved sections), translations, component permissions, migrations
  • Interactive components (Astro islands) when a component opts in
  • SEO with @nascencestudio/tapestry-seo: an SEO button in the editor for each page's search title, description and social image, robots.txt and a sitemap

Inspired by Drupal Canvas. The editor is built with Preact (about 35 KB gzipped on first load, dashboard only); page content is treated as untrusted input: strict schema validation, size and depth limits, URL scheme allowlists and an element allowlist on the rendered output (security).

Requirements

  • Node ≥ 22.12, Astro 7, StudioCMS 0.6
  • An on-demand (SSR) Astro adapter, as StudioCMS requires

Install

pnpm add @nascencestudio/tapestry

Set up

1. Define components (any .astro file can be one):

// src/tapestry.config.mjs
import { defineComponent } from "@nascencestudio/tapestry";

export const components = [
  defineComponent({
    type: "hero",
    label: "Hero",
    component: "./src/components/Hero.astro",
    props: {
      heading: { type: "text", label: "Heading", required: true },
      link: { type: "link", label: "Button link" },
    },
  }),
];

2. Register the plugin and Tapestry's component registry entries (StudioCMS plugins can't add those themselves):

// studiocms.config.mjs
import tapestry, { tapestryComponentRegistry } from "@nascencestudio/tapestry";
import { defineStudioCMSConfig } from "studiocms/config";
import { components } from "./src/tapestry.config.mjs";

export default defineStudioCMSConfig({
  componentRegistry: { ...tapestryComponentRegistry() },
  plugins: [tapestry({ components })],
});

3. Load pages with getPage() in your page route. It enforces draft visibility (StudioCMS's own bySlug returns drafts) and picks the published version for visitors:

---
// src/pages/[...slug].astro
import { StudioCMSRenderer } from 'studiocms:renderer';
import { getPage } from '@nascencestudio/tapestry/page';
import AdminBar from '@nascencestudio/tapestry/AdminBar.astro';

const result = await getPage(Astro);
if (!result) return new Response(null, { status: 404 });
const { page, viewer, publishing } = result;
---
<html lang="en">
  <body>
    <AdminBar viewer={viewer} page={page} publishing={publishing} />
    <StudioCMSRenderer data={page} />
  </body>
</html>

Then create a page of type Tapestry (visual builder) in the dashboard and build it on its Page Content tab.

Optional companions, picked up automatically when installed and registered as StudioCMS plugins: @nascencestudio/medialibrary (media props, images in rich text; option mediaLibrary) and @nascencestudio/tapestry-seo (the editor's SEO button; option seo).

Interactive components need a StudioCMS patch

StudioCMS 0.6.1 removes every <script> that components render from page content, so islands (client: 'visible' etc.) never become interactive and <script>s in your components don't run. Until StudioCMS changes this, apply the small patch that ships with this package (it only affects page types that opt in, like Tapestry):

mkdir -p patches
cp node_modules/@nascencestudio/tapestry/patches/[email protected] patches/
# pnpm-workspace.yaml
patchedDependencies:
  [email protected]: patches/[email protected]

Then pnpm install. (With npm, use patch-package with the same file.) Sites without interactive components don't need it.

Documentation

Development

Requires Node ≥ 22.12 and pnpm ≥ 12 (pnpm only; the supply-chain policies in pnpm-workspace.yaml apply to every install).

pnpm install
pnpm build      # dist/
pnpm test       # unit tests (Vitest)
pnpm typecheck && pnpm lint

The dev site, browser tests and deployment setup live in nascencestudio/tapestry-playground. See Contributing and development.

How Tapestry is built

Tapestry is developed with an AI coding assistant (Anthropic's Claude), directed by its maintainer at Nascence Studio, who sets the requirements, makes the decisions and checks the results. Commits written with its help say so (Co-Authored-By).

What keeps that accountable:

  • Decisions are written down. Every significant choice has a decision record in docs/decisions, with the alternatives considered and why they lost. A devlog records each working session, mistakes included.
  • Behaviour is tested. Unit tests cover the plugin's logic, with adversarial cases for everything that handles untrusted input (validation, URLs, rich text). Browser tests drive the real editor in Chrome, including drag and drop, publishing and an accessibility audit in both dashboard themes; they live in tapestry-playground.
  • Security is designed in. Page content is treated as untrusted input from start to finish, and the threat model is in docs/security.md. Dependencies are minimal, pinned and reviewed before they're added; pnpm's supply-chain checks run on every install.
  • Releases are traceable. Versions are published from GitHub Actions with npm provenance, and each one is approved by a person with two-factor authentication.

Found a problem? Please open an issue.

NOTE: This is mostly an expirement of co-authoring something with AI. If you find it useful, awesome.

License

MIT © Nascence Studio