Curated catalogue of framework-agnostic interactive widgets for the
CBEY Drupal site. Each widget is a sealed shadow-DOM unit. Cadence is
roughly one new widget every 3–4 weeks; first widget is the
grid-tech-market-map scatter chart.
js_widget paragraph
and supply a JSON config blob.dist/manifest.json that
Drupal reads via composer require square360/cbey-js-widgets.The full architectural picture lives in
cbey-d8/docs/2026-05-12-js-widget-paragraph-plan.md. The
non-negotiables for widget authors live in
docs/isolation-contract.md.
cbey-js-widgets/
├── package.json # npm scripts: dev / build / build:runtime / test
├── composer.json # type:drupal-library — dist/ is what cbey-d8 installs
├── vite.config.ts # multi-entry build; React externalised
├── tailwind.config.ts # prefix: 'cbey-' ; tokens map to :host CSS vars
├── tsconfig.json
├── postcss.config.js
├── docs/
│ ├── intake-recipe-react.md # canonical recipe for new React widgets
│ └── isolation-contract.md # the sealed-unit contract (plain language)
├── scripts/
│ ├── emit-manifest.mjs # post-build: writes dist/manifest.json
│ └── build-runtime.mjs # builds the shared React 18 runtime
├── src/
│ ├── manifest.ts # typed source of truth for the manifest
│ ├── runtimes/
│ │ ├── tailwind-base.css # :host-scoped reset + tokens shared by all widgets
│ │ └── react18/
│ │ ├── build-runtime.ts # source for window.CbeyReact bundle
│ │ └── README.md
│ ├── schemas/
│ │ └── grid-tech-market-map.json
│ └── widgets/
│ └── grid-tech-market-map/
│ ├── index.tsx
│ ├── MarketMap.tsx
│ ├── data/gridTechData.ts
│ ├── styles.css
│ └── README.md # accessibility brief (Aria reviews)
└── tests/ # vitest; loader contract + widget smoke tests
npm install
npm run typecheck # tsc --noEmit
npm run lint
npm run dev # vite dev server; rough preview
npm run build # vite build → dist/, then emit-manifest.mjs
npm run build:runtime react18 # build the shared React 18 bundle
npm test # vitest run
After npm run build:
dist/{widget-id}/, content-hashed.dist/manifest.json carries the published manifest Drupal reads.dist/runtimes/react18.bundle.js is the shared React 18 runtime
(produced separately via build:runtime).Follow docs/intake-recipe-react.md.
Short version:
docs/isolation-contract.md.src/widgets/{widget-id}/.src/manifest.ts.src/schemas/{widget-id}.json.src/widgets/{widget-id}/README.md.npm run build, verify, open a PR.When the first Vue / Svelte / Lit widget arrives:
src/runtimes/{runtime}/build-runtime.ts mirroring the React 18
bridge.scripts/build-runtime.mjs's allow-list.cbey_js_widgets.libraries.yml and a corresponding mapping in
JsWidgetMount::RUNTIME_LIBRARIES.supportedRuntimes in src/manifest.ts.docs/intake-recipe-{runtime}.md.Existing widgets are untouched.
v0.1.0).composer update square360/cbey-js-widgets.vendor/square360/cbey-js-widgets/dist/runtimes/react18.bundle.js
to web/modules/custom/cbey_js_widgets/js/runtimes/react18.bundle.js,
or wire a Composer post-update hook.lando drush cr to invalidate the manifest cache tag.Atlas owns the deploy path; the steps above are the contract from this repo's side, not the Drupal side.