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

@booklyease/theme-sdk

v0.1.1

Published

Local dev toolkit for Booklyease vendor-site themes: preview a theme with fake data, switch block variants, validate and pack the bundle.

Downloads

37

Readme

@booklyease/theme-sdk

Local dev toolkit for Booklyease site themes (the templates that render a salon's storefront site on vendor-site).

Build a theme on your machine against fake data — no Booklyease backend, no config. Preview it, flip block display variants with one dropdown, then validate and pack it into an upload-ready bundle.

Install

Install once, globally, to get the booklyease-theme command everywhere:

npm install -g @booklyease/theme-sdk

Verify:

booklyease-theme --help

Prefer not to install? Run it on demand with npx @booklyease/theme-sdk <command> (see Quick start). Requires Node.js ≥ 18.

To upgrade later: npm install -g @booklyease/theme-sdk@latest.

Quick start

# preview the bundled example theme
npx @booklyease/theme-sdk dev

# or, if installed globally, from your own theme folder:
cd my-theme
booklyease-theme dev

Open http://localhost:4500. Edit any .liquid file and save — the page live-reloads.

The editor (Window Site simulator)

The preview ships with an editor drawer (⚙, bottom-left) that mirrors the real vendor-site editor a salon uses, so you can build and edit a site exactly as they would — and catch anything that isn't editable before you ship.

  • Блоки — add/remove/reorder/duplicate blocks, pick a variant, and edit every setting through a form generated from the real block registry (text, textarea, toggle, number, range, select, color, image/video URL, link action, and repeaters). Translatable fields edit the current language.
  • Меню — build header & footer navigation, footer columns, social links and contacts (per-language labels + links), just like the real menu builder.
  • Страницы — create pages (slug, title, home, status), edit per-language SEO (meta/OG/canonical/noindex). Each page has its own blocks.
  • Оформление — header/footer toggles, logo/favicon, footer text & social style, and color schemes: the available light/dark modes and the palettes come from your theme.json (modes / palettes), so you test exactly what your theme ships. Pick a scheme or tune any color by hand.
  • Проверка — runs the editability check (below) right in the panel.

Booking page

The booking page (/booking) is driven by the platform booking widget (main.js) — the same code for every theme — which calls /api/booking/*. A theme only ships the booking shell + CSS in pages/booking.liquid; it does not own the wizard markup.

So locally the SDK:

  • serves the real, vendored widget build at /theme/assets/js/main.js, and
  • answers /api/booking/* with a mock API (fake services, staff, locations, time slots, gym classes + occurrences; create/enroll always succeed).

You get the actual production form — both modes via the built-in toggle: Услуга (individual appointment: service → staff → date/time → confirm) and Занятие (group class: class → occurrence → confirm). Nothing is persisted.

What a theme can customize today: all the booking CSS and the surrounding booking.liquid markup (hero, contacts, layout around #bookingApp). What it cannot (yet): the wizard's internal HTML/labels — those come from main.js.

Theme-owned booking + skeleton

To make the whole form theme-owned (structure, classes, labels — not just CSS), a theme writes its booking form directly in pages/booking.liquid using a small declarative contract, and a thin SDK driver (booking-driver.js) supplies the logic (data from the mock API, step flow, submit). The theme owns 100% of the markup — there is no separate route, it's just /booking.

The page shows a skeleton immediately (a [data-bz-skeleton] block); the driver loads, fills the form, then adds .is-ready to [data-bz-app] so CSS swaps skeleton → form with no layout jump — the real loading sequence. Tune the reveal delay with ?delay=<ms> (e.g. /booking?delay=2000). pulse-gym ships a sample. (If a theme's booking.liquid uses the legacy #bookingApp shell instead, the SDK loads the platform widget — same /booking.)

Contract (all attributes optional; the driver adapts):

| Attribute | Meaning | | --- | --- | | data-bz-app data-api-base data-mode | form root | | data-bz-mode="services\|classes" | mode toggle button | | data-bz-screen="service\|staff\|datetime\|class\|occurrence\|contact\|done" | a step | | data-bz-list="service\|staff\|day\|slot\|class\|occurrence" | where items are cloned | | <template data-bz-tpl="…"> | the markup for one item | | data-bz-field="name\|price\|duration\|date\|time\|free\|…" | text slot; data-bz-field-src = img src | | data-bz-pick | makes an item selectable (gets .is-selected) | | data-bz-input="name\|phone\|email\|comment" | contact field | | data-bz-summary="service\|staff\|date\|time\|total" | live summary slot | | data-bz-next data-bz-prev data-bz-submit | navigation |

Edits are saved to <theme>/.bz-editor/state.json (gitignored) so they survive reloads. Every change (and every reset) first snapshots the previous document to <theme>/.bz-editor/backups/ (last 30 kept) — to undo an accidental reset, copy the newest backup over state.json. To run the SDK against throwaway state without touching a theme's editor data, set BZ_STATE_DIR=/tmp/whatever. The eye icon (👁) opens the page without the editor — the published look. Append /ru, /ro, /en to preview a language.

Commands

| Command | What it does | | --- | --- | | booklyease-theme dev [dir] [--port 4500] | Preview + editor simulator with fake data + live reload | | booklyease-theme validate [dir] | Check the bundle (theme.json, layouts, blocks) | | booklyease-theme check [dir] | Verify everything the theme renders is editable | | booklyease-theme pack [dir] [--out file.zip] | Validate, then zip into an upload-ready bundle |

dir defaults to the current directory.

"Is everything editable?" (check)

A frequent bug: a block prints block.s.some_field, but the editor has no control for it — so a salon can never change it. check cross-references every partials/blocks/<type>.liquid against what the editor can actually edit (the block registry, mirrored from vendor-site) and reports:

  • errorblock.s.x is rendered but has no editor field (not editable).
  • warning — the editor exposes a field the template never reads (dead control), or header_settings/footer_settings reads a key the editor doesn't expose.
  • info — a block partial exists but isn't declared in theme.json blocks, so it can't be placed.

Run it in CI: it exits non-zero when any rendered setting isn't editable.

Theme structure (no build step)

theme.json                      # manifest: name (localized), version (semver), blocks
layouts/default.liquid          # page skeleton: uses {{ head }} {{ header }} {{ content }} {{ footer }}
partials/head.liquid            # <head> — put ALL your CSS inline here (no Vite/SCSS)
partials/header.liquid
partials/footer.liquid
partials/blocks/<type>.liquid   # one template per block type (hero, gallery, services, …)
locales/<ru|ro|en>.json         # UI strings for the `t` filter
assets/…                        # images, fonts (served at /theme/assets/…)

A block template receives its data as block.s (settings). Branch on block.s.variant to support multiple display variants:

{% assign v = block.s.variant | default: 'center' %}
<section class="hero hero--{{ v }}">
  <h1>{{ block.s.title }}</h1>
</section>

By default a block's editable fields come from the built-in registry (the same one vendor-site's editor uses). To expose your own fields, declare a rich schema in theme.json instead of a bare type name — the editor (and this SDK) then renders exactly those fields:

{
  "blocks": [
    "hero",
    {
      "type": "promo",
      "label": "Promo banner",
      "variants": [{ "id": "wide" }, { "id": "tall" }],
      "fields": [
        { "key": "title", "type": "text", "translatable": true, "label": "Title" },
        { "key": "image", "type": "image", "translatable": false, "label": "Image" }
      ]
    }
  ]
}

background_color and section_theme are added to every block automatically. Run check to confirm every block.s.* your template renders is declared.

Filters available to themes

Same as production (vendor-site):

  • {{ "nav.book" | t: locale }} — localized UI string from locales/<locale>.json
  • {{ block.s.image | asset_url }} — resolves a media path to its public URL
  • {{ anything | dump }} — debug: pretty-prints a value as JSON

Publishing

  1. booklyease-theme pack → produces my-theme-1.0.0.zip.
  2. In Booklyease admin → Integrations → Developer → Themes → Create theme, fill the marketplace card and upload that ZIP.
  3. Submit for review. Once approved, salons can pick your theme for their site.

Preview uses LiquidJS; production renders with the same Liquid dialect on the server. Keep templates to standard Liquid + the filters above for parity.