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

@storesynk/elements

v0.1.0-beta.13

Published

Universal Storesynk web components — drop-in Shopify storefront UI for any site.

Readme

@storesynk/elements

Drop-in Shopify storefront web components for any site — product pages, collections, search, and a cart — built on @storesynk/core. One self-contained script, no build step, works anywhere HTML does (plain HTML or any framework).

🧪 Early development — APIs may change. Full docs: docs.storesynk.com

Install

npm install @storesynk/elements

Pre-1.0 prereleases (0.1.0-beta.N) are published to npm's latest tag, so a plain install gets the current release. Do not install @beta: that dist-tag is frozen at an old build.

Import it once anywhere in your bundle and every tag registers itself:

import '@storesynk/elements';

Self-hosting instead of bundling? Copy the entire dist/ folder — storesynk.js is the entry and lazy-loads sibling chunks (collection.js, pixels.js, …) relative to its own URL.

Use via a script tag

<script type="module" src="https://cdn.storesynk.io/elements/0.1/storesynk.js"></script>

<storesynk-store token="YOUR_PUBLIC_TOKEN" domain="your-store.myshopify.com">
  <storesynk-product handle="my-product" class="product">

    <h1 class="product__title"><show-title></show-title></h1>
    <p class="product__price"><show-price class="price"></show-price></p>

    <change-option group="1" class="options">
      <value-option class="options__value"><show-label></show-label></value-option>
    </change-option>

    <change-quantity min="1" class="quantity">
      <decrease-quantity class="quantity__btn">−</decrease-quantity>
      <input-quantity class="quantity__field"></input-quantity>
      <increase-quantity class="quantity__btn">+</increase-quantity>
    </change-quantity>

    <add-to-cart class="button button--primary">Add to cart</add-to-cart>

  </storesynk-product>
</storesynk-store>

Wrap the components in your own semantic HTML and classes — they only set the content, you own the structure and styling. Every functional piece is its own tag; attributes only ever carry context. (In HTML, custom elements need closing tags — <show-title></show-title>, not <show-title/>.)

Variant URLs (sync-url)

Add sync-url to a page's main <storesynk-product> to mirror the variant selection in the URL: the initial selection is read from the URL, option clicks replaceState it, and back/forward re-derives it. Two link styles are read either way, matching Liquid storefronts and Hydrogen: ?variant=<numeric id> (the reserved variant param, never an option name; it wins when both are present) and one param per option (?color=red, matched case-insensitively). The attribute value picks what gets written:

<storesynk-product handle="my-product" sync-url>            <!-- writes ?color=red&size=m -->
<storesynk-product handle="my-product" sync-url="variant">  <!-- writes ?variant=41820371452004 -->

sync-url="variant" writes the shareable Liquid-style link (falling back to option params while the selection does not resolve to a variant). Stale option params and the variant param are scrubbed before each write, other params (?ref=campaign) survive. Never put sync-url on list or search card templates: they would all fight over one URL.

Components (selection)

  • Context: storesynk-store, storesynk-product
  • Displayers: show-title, show-price, show-compare-price, show-image, show-media, show-sku, show-stock, … (hide themselves when empty)
  • Variant options: change-option, value-option, show-label, show-swatch
  • Quantity: change-quantity, increase-quantity, decrease-quantity, input-quantity, show-quantity
  • Actions: add-to-cart, buy-now, product-link
  • Lists: storesynk-list (simple collection), search-result-list + search-input, predictive-search
  • Collections (filterable grid, see below): storesynk-collection, product-list, filter-list, change-filter, change-price, change-sort, load-more, clear-filters, active-filter-list, show-result-count
  • Cart: storesynk-cart, cart-line-list, cart-line, show-line-*, increase-line-quantity, decrease-line-quantity, remove-cart-line, open-cart, close-cart, show-cart-count, show-cart-total, checkout-link
  • Pixels (analytics, optional): enable with <storesynk-store track-events> — forwards commerce events to Meta, GA4, TikTok, Pinterest, Reddit, Klaviyo + Shopify native. When on, it loads Shopify's Customer Privacy API and storefront analytics scripts from cdn.shopify.com; consent is always enforced (the old require-consent is accepted but no longer needed). Shopify's standard-actions CDN script is never loaded: Storesynk is that runtime. See PIXELS.md (shipped with the package).

Collections (product listing)

<storesynk-collection> renders a filterable, sortable, paginated product grid driven entirely by the Shopify Storefront API — filtering, sorting and cursor pagination happen server-side, so it stays fast on any catalog size. It loads on demand as a separate collection.js chunk the first time a <storesynk-collection> appears on a page, so pages that don't list products never download it.

<storesynk-collection handle="shoes" page-size="24">

  <change-sort>
    <select>
      <option value="">Featured</option>
      <option value="PRICE">Price, low to high</option>
      <option value="PRICE:reverse">Price, high to low</option>
      <option value="TITLE">Alphabetical</option>
      <option value="CREATED:reverse">Newest</option>
    </select>
  </change-sort>

  <!-- Applied-filter chips (first child is the chip template) -->
  <active-filter-list>
    <active-filter-item><show-filter-title></show-filter-title><button remove>×</button></active-filter-item>
  </active-filter-list>
  <clear-filters>Clear all</clear-filters>

  <!-- Price range -->
  <change-price>
    <input min-input placeholder="Min" /> <input max-input placeholder="Max" />
    <button apply>Go</button>
  </change-price>

  <!-- Zero-config checkbox facets for everything Search & Discovery exposes -->
  <filter-list>
    <filter-group>
      <h4><show-filter-label></show-filter-label></h4>
      <filter-value>
        <label><input type="checkbox" /> <show-filter-title></show-filter-title> (<show-filter-count></show-filter-count>)</label>
      </filter-value>
    </filter-group>
  </filter-list>

  <!-- The grid: the first child is the card template, cloned per product -->
  <product-list>
    <storesynk-product class="card">
      <product-link><a><show-title></show-title> <show-price></show-price></a></product-link>
    </storesynk-product>
  </product-list>

  <p>Showing <show-result-count></show-result-count></p>
  <load-more>Load more</load-more>

</storesynk-collection>

Leave handle off to render the whole store — no collection needs to exist for this; the engine lists the full catalog via a wildcard search (note: search only sorts by RELEVANCE/PRICE, so other change-sort keys fall back to the default order there). If you have a curated all-products collection, point all-handle at it to use that instead — real collections support the full sort-key set and the merchant's merchandising.

Which filters appear, and how AND/OR works

The available filters — availability, price, product options, vendor, type, tag, metafields — are whatever the merchant enables in Shopify's Search & Discovery app, not something the component decides. Enable one there and it shows up automatically with live result counts. Within a single filter, values combine with OR by default; product tags and list.* metafields can be switched to AND in Search & Discovery. The component only sends the selected values, so the AND/OR behavior always follows the store's configuration.

Custom filter UX (swatches, single/multi-select)

<filter-list> renders every filter uniformly as checkboxes. To style one filter yourself, render it with <change-filter for="…"> and drop it from the auto list with <filter-list except="color">. It clones your <filter-value> template per value — use any markup you like (swatches, pills, image tiles) — and paints <show-filter-swatch> from the value's swatch color/image when the merchant sets that filter to a swatch (or image) presentation.

<filter-list except="color"><!-- other filters render here --></filter-list>

<change-filter for="color" mode="multi">
  <h4><show-filter-label></show-filter-label></h4>
  <filter-value class="swatch">
    <show-filter-swatch class="swatch__dot"></show-filter-swatch>
    <show-filter-title class="swatch__name"></show-filter-title>
  </filter-value>
</change-filter>

for targets a filter by option name, label or id. mode="multi" (default) toggles values; mode="single" keeps one selected at a time within the group.

Shareable URLs

Filters, sort and pagination are mirrored to the URL as readable params (?color=Blue&price=10-50&sort=PRICE&page=2) so views are shareable, bookmarkable, SEO-friendly and back/forward-restorable. With more than one collection on a page, give each a unique url-key so their params don't collide (url-key="a" → ?a.color=Blue). Add no-url-sync to opt out.

License

MIT