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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@syntrologie/runtime-sdk

v0.2.1

Published

Syntrologie Runtime SDK for web experimentation and analytics

Downloads

315

Readme

Syntrologie Smart Canvas SDK

Smart Canvas SDK (React + Shadow DOM)

The SDK now ships a framework-agnostic <smart-canvas> custom element with an open shadow root. We still render everything with React, but the canvas is encapsulated so host Tailwind configs, resets, or stacking contexts can’t break the UI.

What’s Included

  • SmartCanvasElement – the custom element that owns the shadow DOM, overlay root, and controller.
  • SmartCanvasApp – the React tree (overlay, rectangles, toggle) you portal into the shadow.
  • SmartCanvasPortal – helper for React hosts to portal their tree (and context) into the element mount.
  • createSmartCanvas – imperative API (window.SmartCanvas.create) for non-React hosts.
  • GrowthBook/PostHog wrappers, hooks, rectangle components, and wheel remain available.

Installation

NPM/Yarn

npm install @syntrologie/smart-canvas-sdk
# or
yarn add @syntrologie/smart-canvas-sdk

CDN

For quick setup without a build process:

<!-- Minified production build -->
<script src="https://unpkg.com/@syntrologie/smart-canvas-sdk@latest/dist/smart-canvas.min.js"></script>

<!-- Non-minified development build -->
<script src="https://unpkg.com/@syntrologie/smart-canvas-sdk@latest/dist/smart-canvas.js"></script>

<!-- ES Modules -->
<script type="module">
  import { createSmartCanvas } from 'https://unpkg.com/@syntrologie/smart-canvas-sdk@latest/dist/smart-canvas.esm.js';
</script>

Local Development

cd tech-core/sdks/shadow-canvas
npm run build
cd ../../tax_landing_page
npm install @syntrologie/smart-canvas-sdk@file:../tech-core/sdks/shadow-canvas

Rebuild and reinstall whenever the SDK changes.

Using the Custom Element (React Host)

import {
  createSyntroExperiment,
  createSyntroTelemetry,
  SmartCanvasApp,
  SmartCanvasPortal,
  registerSmartCanvasElement,
  type SmartCanvasElement,
} from "@syntrologie/smart-canvas-sdk";

const canvasFetcher = async () => {/* return ShadowCanvasConfigResponse */};

function SmartCanvasBridge() {
  const [element, setElement] = useState<SmartCanvasElement | null>(null);

  useEffect(() => {
    registerSmartCanvasElement();
  }, []);

  const controller = element?.getController();

  return (
    <>
      <smart-canvas ref={setElement as any} />
      {element && controller ? (
        <SmartCanvasPortal element={element}>
          <SmartCanvasApp
            controller={controller}
            fetcher={canvasFetcher}
            overlayConfigUri={import.meta.env.VITE_SHADOW_CANVAS_OVERLAY_URI}
          />
        </SmartCanvasPortal>
      ) : null}
    </>
  );
}

Using the Imperative API (Plain JS Host)

When using via CDN, the SDK is available as window.SyntrologieSDK:

// Via npm/ES modules
await window.SmartCanvas?.create({
  defaultOpen: true,
  tokens: {
    "--sc-surface": "#050814",
    "--sc-fg": "#f8fafc",
  },
  integrations: {
    posthog,       // existing PostHog client
    growthbook,    // existing GrowthBook client
  },
});

Styling & Overlays

  • Fonts, colors, and CSS variables (--sc-surface, --sc-fg, etc.) are inherited from the host. Tokens can be overridden via setTokens or standard CSS:
    • --syntro-tooltip-bg, --syntro-tooltip-fg, --syntro-tooltip-radius, --syntro-tooltip-shadow
    • --syntro-ring, --syntro-spotlight-backdrop for highlights
  • A scoped reset is injected via adoptedStyleSheets (fallbacks to <style>).
  • Tooltips/popovers should use the Popover API or Floating UI with the exposed overlay root (element.getOverlayRoot()).

Analytics Events

The createSyntroTelemetry client emits:

| Event | Description | | --- | --- | | shadow_canvas_opened / shadow_canvas_closed | Toggle button interactions. | | shadow_canvas_rectangle_viewed | A rectangle becomes visible (overlay grid & wheel). | | shadow_canvas_action | CTA click, chatbot send, overlay events (tooltips, dismiss, anchor missing). |

Rectangle Config (unchanged)

The experimentation service still returns the same payload (rectangles, style, content, optional experiment metadata). Top-level fields now include optional canvasTitle so host teams can rename the overlay without code changes. See src/types.ts for the exact contract.

Schema & Validation Tool

  • JSON schema lives at schema/canvas-config.schema.json (published with the package).
  • Validate a config file locally:
cd tech-core/sdks/shadow-canvas
npm run validate-config -- ../../tax_landing_page/public/smart-canvas-demo.json

The script evaluates structure/required fields without third-party dependencies so CI and content authors can catch issues early.

Overlays (Tooltips & Highlights)

  • Recipes use the schema in src/overlays/schema.ts (roughly { id, version, steps[] }).
  • Provide a recipe URI via overlayConfigUri or let GrowthBook supply smart-canvas-overlay-uri.
  • Overlays render in #syntro-overlays (fixed, pointer-events: none) and use Floating UI for tethering.
  • The Canvas runtime dynamically imports the overlay chunk only when a recipe resolves.
  • Exposed helpers:
    • createOverlayRecipeFetcher, resolveConfigUri
    • runOverlays, showTooltip, showHighlight
    • createAnchorResolver (works for main DOM + shadow DOM)

Telemetry for overlays uses telemetry.trackAction("syntro_overlay_*", stepId, "overlay").

Testing

  • Shadow root is open, so Playwright/Cypress can traverse via .shadow().
  • Data hooks: [data-shadow-canvas-id="overlay-launcher"], [data-shadow-canvas-id="rectangle-${id}"], etc.
  • SmartCanvasController exposes open/close for deterministic tests.

Directory Overview

tech-core/sdks/shadow-canvas
├─ src
│  ├─ SmartCanvasElement.tsx   // custom element + controller glue
│  ├─ SmartCanvasApp.tsx       // React UI
│  ├─ SmartCanvasPortal.tsx    // portal helper
│  ├─ api.tsx                  // window.SmartCanvas + imperative API
│  ├─ analytics/, experiments/, hooks/, components/
│  └─ controller.ts
└─ README.md

Quick Checklist

  1. Call registerSmartCanvasElement() once per app.
  2. Render <smart-canvas> (custom element).
  3. Portal your React tree into the element’s shadow via SmartCanvasPortal.
  4. Configure the SDK with your API credentials.
  5. For non-React pages, call window.SmartCanvas.create() with configuration.