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

@bettercms-ai/sveltekit

v0.4.0

Published

BetterCMS for SvelteKit: settings from PUBLIC_BCMS_*, the read client per request with draft mode, the editor's draft routes, and the page sections server-rendered by BetterCMS.

Readme

@bettercms-ai/sveltekit

BetterCMS for SvelteKit. Your own components stay your own: they spread a few attributes onto their elements, and every element becomes editable in the BetterCMS visual editor. Pages stay current when content is published.

npm i @bettercms-ai/sveltekit
// src/lib/bcms.ts
import { env as pub } from "$env/dynamic/public";
import { env as priv } from "$env/dynamic/private";
export const bcms = createBcms({ env: { ...pub, ...priv } });

// src/hooks.server.ts: drafts, <html data-bcms-draft>, <meta name="generator">
export const handle = bcmsHandle(bcms); // or sequence(bcmsHandle(bcms), yourHandle)

// src/routes/api/draft/+server.ts: the path the editor's "Preview on site" opens
export const GET = ({ request }) => bcms.draftEnable(request);

// src/routes/+page.server.ts: drafts while the editor previews
export const load = async ({ request }) => ({ post: await (await bcms.client(request)).getEntry("hello-world") });
<!-- src/routes/+layout.svelte: a publish, and the editor's re-render request, re-run `load` -->
<script>
  import { onMount } from "svelte";
  import { invalidateAll } from "$app/navigation";
  import { env } from "$env/dynamic/public";
  import { startBcmsLive } from "@bettercms-ai/sveltekit";
  onMount(() => startBcmsLive({ refresh: invalidateAll, src: env.PUBLIC_BCMS_LIVE_URL }));
</script>
<slot />

<!-- your own markup, bound to its content -->
<article {...entryAttrs(data.post)}>
  <h1 {...entryField(data.post, "title")}>{data.post.data.title}</h1>
  <img {...imageAttrs(data.post.data.cover, { sizes: "100vw" })} {...entryField(data.post, "cover")} class="cover" />
  <div {...entryField(data.post, "body")}>{@html rich(data.post.data.body)}</div>
</article>

| Helper | What it binds | |---|---| | fieldAttrs(path, page.fieldStyles) | A page field. It also applies the field's stored style, which turns on the editor's Align, Size and Weight controls. | | entryAttrs(entry) | A collection entry's card. | | entryField(entry, path) | A field of that entry. | | sectionRootAttrs(block) | A section root (its spacing and design). | | sectionColumnAttrs(block) | The section's content column. | | imageAttrs(value, { path, sizes }) | An optimized <img> with a srcset, alt text, the focal point and the field binding. | | rich(value), lines(value), plain(value) | Rich text as HTML, a one-line value, or plain text for attributes. |

Sections

A page built from sections in BetterCMS renders as the hosted renderer draws it, so forms, sliders and tabs work exactly as they do on a BetterCMS-hosted site. Pass the request and the editor's session gets the draft, with every section and value clickable:

// src/routes/+page.server.ts
export const load = async ({ fetch, request }) => ({ sections: await bcms.sections("home", fetch, request) });
<div use:bcmsSections={data.sections}>{@html sectionsMarkup(data.sections)}</div>

Your own sections in the CMS order

A page that draws its own sections can let BetterCMS order them, and draw sections added in the editor between them: name the page's sections (slots, in source order) and loop over sectionItems. npx @bettercms-ai/convert --sections writes this for you.

// src/routes/+page.server.ts
const bcmsSlots = ["hero", "code:features"];
export const load = async ({ fetch, request }) => ({
  bcmsSections: sectionItems(await bcms.sections("home", fetch, request, { slots: bcmsSlots }).catch(() => null), bcmsSlots, "home"),
});
{#each data.bcmsSections as item (item.key)}
  {#if item.slot === "hero"}<section class="hero" {...item.root}>…</section>
  {:else if item.slot === "code:features"}<div {...item.box}><Features /></div>
  {:else if item.slot === null}<div data-bcms-rendered="platform" use:bcmsSections={item.html}>{@html item.html}</div>
  {/if}
{/each}

root goes on a section's own root element (its placement's data-bcms-block and style); box on a wrapper when the section is a component. With no answer, every slot renders in source order.

Settings

Options are read first, then PUBLIC_BCMS_*, then BCMS_*, the same precedence as every adapter:

| Variable | Purpose | |---|---| | PUBLIC_BCMS_API_URL | The API to read from. | | PUBLIC_BCMS_WORKSPACE | Your workspace. | | PUBLIC_BCMS_PROJECT_ID | Your project. | | PUBLIC_BCMS_LIVE_URL | The live stream. Optional. | | BCMS_DRAFT_SECRET | Signs the draft cookie. |

The sections run small inline scripts (forms, sliders and tabs), so a Content-Security-Policy must allow inline scripts.