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

@strata-ds/web

v1.0.1

Published

Strata Design System Web Components

Downloads

275

Readme

@strata-ds/web


🌐 Framework-agnostic web components for Strata — connect any frontend to your design system with zero lock-in.

@strata-ds/web is a Stencil-powered component library that delivers Strata design tokens and components to vanilla JS, React, Vue, Angular, Svelte, and any framework that supports web standards. It ensures design-to-code fidelity across your entire frontend ecosystem.

Design once in Strata. Ship everywhere.


Specs

Durable, versioned contracts for agent-driven rendering and related runtime interfaces live in docs/specs/.

AI coding agents must read AGENTS.md before contributing.


Table of Contents


Why @strata-ds/web?

The Problem

Modern teams use multiple frameworks (React for marketing site, Vue for admin panel, vanilla JS for docs). Without a framework-agnostic design system, you face:

  • Duplicate style implementations across frameworks
  • Inconsistent brand experience (React button ≠ Vue button)
  • Manual token updates in 5+ repositories
  • Designer → developer handoff breaks down per framework

Key Pain Points:

  • ⚠️ Stale Tokens: Design tokens become outdated across multiple codebases.
  • ❌ No Source of Truth: No single source of truth for component styling.
  • 🔄 Manual Sync: Manual synchronization between design and code is slow and error-prone.
  • 📉 Platform Divergence: Platform-specific implementations diverge over time.

The Solution

@strata-ds/web uses Web Components (browser-native, framework-agnostic) to deliver:

  • One source of truth — Tokens and components sync from Strata
  • Works everywhere — Vanilla JS, React, Vue, Angular, Svelte, etc.
  • Real-time updates — Design changes propagate without redeploying
  • Zero lock-in — Web standards, not proprietary APIs
  • CSS variable injection for global styling
  • Dynamic component rendering based on API-defined structure

Who Is This For?

| Persona | Value | |---------|-------| | Design System Teams | Single source of truth for variables and components | | Solopreneurs | "I'm using vanilla JS — I don't need React bloat. I just want brand-consistent components." | | Frontend Engineers | "I maintain 3 apps in different frameworks. One design system = one source of truth." | | Multi-Framework Teams | Consistent UI across React, Vue, Angular, and static sites | | Product Teams | Real-time style updates without redeployment | | Entrepreneurs | "My team ships faster because components stay in sync across React, Vue, and marketing pages." | | Designers | "What I create in Strata works everywhere — no framework-specific tweaks." |


Core Features

  • 🌐 Framework-agnostic — Works in vanilla JS, React, Vue, Angular, Svelte
  • 🔁 Live sync with Strata backend
  • 🧠 Token-driven styling — Design tokens as CSS custom properties
  • 🧩 Dynamic component loading — Fetch components from Strata on-demand
  • 🛠 Framework wrappers — First-class React and Vue support
  • 📴 Offline-first fallback — Cached data when network fails
  • 🧪 Debug tools<strata-debug> component for inspection

Before you start:

  • [ ] Created a project at strata.charisol.io
  • [ ] Imported your design tokens (Style Dictionary JSON or Figma)
  • [ ] Published your project (dashboard shows "✅ Published")

Integration:

  • [ ] Installed @strata-ds/web via npm/yarn
  • [ ] Copied projectId from dashboard URL or project settings
  • [ ] Copied projectToken from Publish & Sync tab (starts with pt_live_)
  • [ ] Added <strata-provider> wrapper
  • [ ] Loaded the Stencil script in your HTML/framework entry point
  • [ ] Rendered your first component with <strata-dynamic>

Verification:

  • [ ] Opened DevTools → Console and saw Connected to design system
  • [ ] Console shows Design system synced: { components: {...}, variables: {...} }
  • [ ] Component renders on screen with correct styles
  • [ ] Added <strata-debug></strata-debug> and verified connection status

Stuck? → Jump to Debugging & Troubleshooting.


Quick Start (< 5 Minutes)

🚀 New to Strata? Get your first component rendering in 3 steps.

Step 1: Install

npm install @strata-ds/web
# or
yarn add @strata-ds/web

Step 2: Get Your Credentials

Go to strata.charisol.io → Your Project → Publish & Sync tab:

  • Copy your Project ID (e.g., abc123def456)

  • Copy your Project Token (starts with pt_live_)


Step 3: Load the Components

Vanilla JS / HTML

<!DOCTYPE html>
<html>
  <head>
    <script type="module" src="https://cdn.jsdelivr.net/npm/@strata-ds/web/dist/strata-web/strata-web.esm.js"></script>
  </head>
  <body>
    <strata-provider
      url="http://localhost:4000"
      enable-realtime="true"
      poll-interval="6000"
      project-id="YOUR_PROJECT_ID"
      project-token="pt_live_your_token_here"
      sync-enabled="true"
    >
      <!-- Dynamic component -->
      <strata-dynamic
        component="button"
        props='{"children": "Click me!", "variant": "primary"}'
      ></strata-dynamic>
    </strata-provider>
  </body>
</html>

💡 Replace YOUR_PROJECT_ID and pt_live_your_token_here with values from Step 2.


React (Next.js / Create React App)

Step 1: Create a Provider Component

👉 app/providers/StrataProvider.tsx

<<<<<<< HEAD
// app/layout.tsx (Next.js App Router)
"use client";
import { StrataProvider } from "@strata-ds/web/react";
=======
'use client';

import { useEffect, useRef } from 'react';
import { defineCustomElements } from '@strata-ds/web/loader';

export default function StrataProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const providerRef = useRef<any>(null);

  useEffect(() => {
    const load = async () => {
      try {
        await defineCustomElements();
        console.log('✅ Strata web components registered');
      } catch (err) {
        console.error('❌ Failed to register Strata:', err);
      }
    };

    load();
  }, []);

  return (
    <strata-provider
      ref={providerRef}
      url="http://localhost:4000"
      enable-realtime={true}
      poll-interval={6000}
      project-id="YOUR_PROJECT_ID"
      project-token="pt_live_your_token_here"
      sync-enabled={true}
    >
      {children}
    </strata-provider>
  );
}

Step 2: Update the Layout (app/layout.tsx)

import './globals.css';
import { StrataProvider } from './providers/StrataProvider';
import Script from 'next/script'; // Import the Script component
>>>>>>> 020a780f53ce5f1c32b9cbf0c05e4f98f836a432

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        {/* Use the Script component for the CDN */}
        <Script 
          src="https://cdn.tailwindcss.com" 
          strategy="beforeInteractive" 
        />
      </head>
      <body>
        <StrataProvider>
          {children}
        </StrataProvider>
      </body>
    </html>
  );
}

Step 3: Usage in Pages (app/page.tsx)

👉 app/page.tsx

// app/page.tsx
<<<<<<< HEAD
"use client";
import { StrataDynamic } from "@strata-ds/web/react";
=======
'use client';
>>>>>>> 020a780f53ce5f1c32b9cbf0c05e4f98f836a432

export default function Page() {
  return (
    <main>
      <h1>Strata Design System Test</h1>

      <h2>Card Component</h2>
      <strata-dynamic component="card" sync-enabled={true} />

      <h2>Button Component</h2>
      <strata-dynamic component="button" />
    </main>
  );
}

⚠️ 4. Add TypeScript support for custom elements (recommended)

TypeScript: If TypeScript complains about the custom tags, ensure you have a custom-elements.d.ts file in your project:

declare module 'react' {
  namespace JSX {
    interface IntrinsicElements {
      'strata-provider': DetailedHTMLProps<HTMLAttributes<HTMLElement> & {
        url?: string;
        'enable-realtime'?: boolean;
        'poll-interval'?: number;
        'project-id'?: string;
        'sync-enabled'?: boolean;
        'syncToken'?: string;
        'projectToken'?: string;
      }, HTMLElement>;
      'strata-dynamic': DetailedHTMLProps<HTMLAttributes<HTMLElement> & {
        component?: string;
        props?: string;
        'sync-enabled'?: boolean;
      }, HTMLElement>;
      'strata-debug': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
    }
  }
}

export { };

Alternative simpler declaration:

declare module 'react' {
  namespace JSX {
    interface IntrinsicElements {
      'strata-provider': any;
      'strata-dynamic': any;
      'strata-debug': any;
    }
  }
}

export { };

Vue 3

<template>
  <div>
    <strata-provider 
      url="http://localhost:4000"
      enable-realtime="true"
      poll-interval="6000"
      project-id="YOUR_PROJECT_ID"
      project-token="pt_live_your_token_here"
      sync-enabled="true"
      @connected="onConnected"
      @error="onError"
    >
      <div>
        <h2>Card Component</h2>
        <strata-dynamic component="card" />
        
        <h2>Button Component</h2>
        <strata-dynamic component="button" 
         :props="JSON.stringify({ children: 'Click me!', variant: 'primary' })"
        />
      </div>
    </strata-provider>
  </div>
</template>

<script setup>
<<<<<<< HEAD
import { defineCustomElements } from '@strata-ds/web/loader';
=======
const onConnected = () => {
  console.log('Connected to Strata')
}
>>>>>>> 020a780f53ce5f1c32b9cbf0c05e4f98f836a432

const onError = (error) => {
  console.error('Strata error:', error)
}
</script>

<style>
body {
  font-family: Arial, sans-serif;
  padding: 20px;
}
</style>

Step 2 Update vite.config.ts of Vue:

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue({
    template: {
      compilerOptions: {
        // Treat all tags with 'strata-' prefix as custom elements
        isCustomElement: (tag) => tag.startsWith('strata-')
      }
    }
  }),
    vueDevTools(),
  ],
  optimizeDeps: {
    include: ['@strata-ds/web', '@strata-ds/web/loader'],
    exclude: []
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    },
  },
})

⚠️ Add TypeScript support for custom elements (recommended)

In your Vue app create a file src/strata-web.d.ts inside it add;

declare module '@strata-ds/web/vue' {
  import { Plugin, Component } from 'vue'

  export const StrataProvider: Component
  export const StrataDynamic: Component
  
  const StrataVuePlugin: Plugin
  export default StrataVuePlugin
}

Create a new file src/shims-vue.d.ts inside it add;

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

Inside the index.html of the Vue project add Tailwind CSS CDN

       <!-- Add Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>

Angular

// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { defineCustomElements } from '@strata-ds/web/loader';

defineCustomElements();

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}

HTML

<!-- app.component.html -->
<strata-provider
  url="http://localhost:4000"
  enable-realtime="true"
  poll-interval="6000"
  project-id="YOUR_PROJECT_ID"
  project-token="pt_live_your_token_here"
  sync-enabled="true"
>
  <strata-dynamic
    component="Button"
    props='{"children": "Click me!", "variant": "primary"}'
  ></strata-dynamic>
</strata-provider>

Svelte

<!-- App.svelte -->
<script>
  import { onMount } from 'svelte';
  import { defineCustomElements } from '@strata-ds/web/loader';

  onMount(() => {
    defineCustomElements();
  });
</script>

<strata-provider
  url="http://localhost:4000"
  enable-realtime="true"
  poll-interval="6000"
  project-id="YOUR_PROJECT_ID"
  project-token="pt_live_your_token_here"
  sync-enabled="true"
>
  <strata-dynamic
    component="Button"
    props={JSON.stringify({ children: 'Click me!', variant: 'primary' })}
  ></strata-dynamic>
</strata-provider>

API Reference

<strata-provider>

Wraps your app and manages the connection to Strata.

| Attribute | Type | Default | Description | |-----------|------|---------|-------------| | url | string | 'http://localhost:4000' | Base URL for the Strata backend. Use http://localhost:4000 for local development; set to your deployed Strata backend URL (use https:// in production to protect tokens) | | enable-realtime | boolean | true | Enable WebSocket + polling for real-time updates | | poll-interval | number | 6000 | Polling interval in milliseconds | | project-id | string | undefined | Your Strata project ID (from dashboard) | | project-token | string | undefined | Sync token (starts with pt_live_) — required if project is private | | sync-enabled | boolean | true | Enable/disable syncing |

Events:

  • synced — Fires when design system data syncs successfully
  • error — Fires when sync fails (check event.detail.error)
  • connected — Fires when WebSocket connects
  • disconnected - Fired when connection is lost

<strata-dynamic>

Renders a component fetched from Strata.

| Attribute | Type | Default | Description | |-----------|------|---------|-------------| | component | string | required | Name of the component (e.g., "Button", "Navbar") | | props | string (JSON) | '{}' | Props to pass to the component (JSON string) | | sync-enabled | boolean | true | Enable/disable syncing for this component |

Events:

  • load — Fires when the component loads successfully
  • error — Fires when the component fails to load

Example:

<strata-dynamic
  component="Card"
  props='{"title": "Welcome", "variant": "elevated"}'
></strata-dynamic>

<strata-debug>

Renders a debug panel showing connection status and loaded components.

<strata-debug></strata-debug>

Displays:

  • ✅ Connection status (Connected / Disconnected / Error)
  • ✅ Loaded components
  • ✅ Loaded variables
  • ✅ Sync mode (WebSocket + Polling)
  • ✅ Last sync time
  • ✅ Any errors

Debugging & Troubleshooting

Quick Debug Panel

Add <strata-debug></strata-debug> anywhere inside <strata-provider> to inspect:

  • ✅ Connection status
  • ✅ Loaded components
  • ✅ Loaded design tokens
  • ✅ Sync configuration
<strata-provider url="http://localhost:4000" project-id="abc123">
  <strata-debug></strata-debug>
  <!-- Your app content -->
</strata-provider>

Console Log Reference

When debugging, look for these messages in DevTools Console:

  • Strata Web Components loaded — Script initialized successfully
  • Connected to design system — Provider mounted and connected
  • Design system synced: { components: {...}, variables: {...} } — Data loaded
  • 401 / 403 — Token or CORS issue (see table above)
  • Component "X" doesn't exist — Component name doesn't match your Strata project

Common Issues

| 🚨 Problem | ✅ Solution | |-----------|-----------| | 401 Unauthorized | Your project-token is invalid or expired. Go to Publish & Sync tab in your Strata project and copy a fresh token. | | 403 Forbidden | Your project has CORS restrictions. Add your domain to allowedOrigins in your Strata project settings. | | Component not rendering | 1. Check project-id matches your dashboard URL2. Verify the component exists in your Strata project3. Open DevTools Console and look for errors | | Styles broken / unstyled | Design tokens are applied as CSS custom properties on :root. Check DevTools → Elements → Styles for --color-*, --font-*, etc. | | TypeScript errors (React) | Install type definitions: npm install --save-dev @types/react | | Vue warning: unknown element | Call defineCustomElements() from @strata-ds/web/loader in your app entry file (see Vue example above) |


Network Tab Debugging

Open DevTools → Network tab and filter by:

  • Polling requests — Look for requests to your url (e.g., http://localhost:4000/sync); status should be 200 OK with JSON responses
  • WebSocket connection — Look for 101 Switching Protocols

🏗 Architecture Overview

Your App
  └── <strata-provider>        ← Manages connection & token sync
        ├── <strata-dynamic>   ← Fetches & renders individual components
        └── <strata-debug>     ← (Optional) Debug panel

@strata-ds/web Core

The following diagram illustrates how @strata-ds/web acts as the bridge between the Design System API and the consumer frameworks.

graph TD
    subgraph API ["Design System API"]
        A["Variables"]
        B["Components"]
        C["Real-time WebSocket"]
    end

    API --> Core

    subgraph Core ["@strata-ds/web Core"]
        direction TB
        subgraph Sync ["StrataSystemSyncService - Singleton"]
            S1["- Fetches variables & components from API"]
            S2["- Manages polling/WebSocket connections"]
            S3["- Injects CSS variables into :root"]
            S4["- Event emission for state changes"]
        end

        subgraph Factory ["Component Factory & Style Manager"]
            F1["- Renders components from API definitions"]
            F2["- Processes Tailwind classes and CSS variables"]
            F3["- Generates inline styles from properties"]
        end
    end

    Core --> WC["Web Component Direct Usage"]
    Core --> RW["React Wrapper"]
    Core --> VW["Vue Wrapper"]

    %% Styling
    style API fill:#f9f9f9,stroke:#333,stroke-width:2px
    style Core fill:#282829,stroke:#01579b,stroke-width:2px
    style Sync fill:#333,stroke:#01579b
    style Factory fill:#333,stroke:#01579b

Authentication

If your project is private, pass a project-token:

<strata-provider
  project-id="YOUR_PROJECT_ID"
  project-token="pt_live_your_token_here"
>

Every sync request will include Authorization: Bearer pt_live_... and X-Project-Token headers.

  1. REST API (Initial Sync)

For standard HTTP requests (fetching variables and component definitions), credentials are sent via Headers:

| Header | Value | | :--- | :--- | | Authorization | Bearer pt_live_xxxxxxxxxxxx | | X-Project-Token | your-project-id |

  1. WebSocket (Real-time Updates)

For live synchronization, credentials must be passed as Query Parameters to ensure compatibility across all browser environments:

wss://api.strata.run/sync?token=pt_live_xxx&projectId=your-project-id

💡 Why the distinction?

  • Headers are used for API calls to follow REST best practices and keep tokens out of server access logs.

  • Query Parameters are used for WebSockets because the initial browser handshake for WSS does not always support custom headers reliably across all platforms (Web, Flutter, etc.).

See how the StrataSystemSyncService handles this internally:

// Internal Auth Logic
const headers = {
  'Authorization': `Bearer ${token}`,
  'X-Project-Token': projectId
};

const wsUrl = `${BASE_WS_URL}?token=${token}&projectId=${projectId}`;

Advanced Usage

Listening to Events (Vanilla JS)

const provider = document.querySelector('strata-provider');

provider.addEventListener('synced', (event) => {
  console.log('Design system loaded:', event.detail);
});

provider.addEventListener('error', (event) => {
  console.error('Sync failed:', event.detail.error);
});

⚛️ React Usage

import { StrataProvider } from '@strata-ds/web/react';

<StrataProvider
  projectId="YOUR_PROJECT_ID"
  projectToken="pt_live_your_token_here"
  onSync={(data) => console.log('Synced:', data)}
  onError={(error) => console.error('Error:', error)}
>
  {children}
</StrataProvider>

Dynamic Props

Update props dynamically:

const dynamic = document.querySelector('strata-dynamic');
dynamic.setAttribute('props', JSON.stringify({ variant: 'secondary', children: 'Updated!' }));

⚠️ Note: props must be a JSON string when using the web component directly. For React, use the strata-dynamic wrapper which accepts objects directly.


License

MIT © Charisol


Resources