Consumer Integration Guide
What a team outside the WhiskerPlatform core group does to onboard. Two
paths exist: build a new federation module from scratch, or convert an
existing app into an iframe consumer. Both land in the same runtime and the
same pipeline — and neither ever requires a PR against whisker-host.
One-time setup — install the platform CLI
Section titled “One-time setup — install the platform CLI”# .npmrc routing @nike scope to Artifactory — see whisker-platform/README.mdpnpm install -g @nike/whisker-cliwhich thundercatsthundercats install-skill # once per machine: installs the global @thundercats Cursor skillRun thundercats upgrade when you want a newer global CLI build (then
re-run thundercats install-skill to refresh the global skill too).
thundercats update refreshes a module/service repo’s .cursor/rules/
templates only — the skill itself lives outside any repo.
Path A — federation module (greenfield)
Section titled “Path A — federation module (greenfield)”Day 0 — scaffold
Section titled “Day 0 — scaffold”thundercats create module my-module# back-compat alternatives that hit the same library code:# pnpm create whisker# npx @nike/create-whisker## kind: module; name, description, team, slack channel, manager email# accept default ports or set your own## @nike/create-whisker writes AGENTS.md + .cursor/rules/thundercats-core.mdc# itself as the last scaffold step — .cursor/ is already populated before# you cd in, no separate `thundercats init` call happens under the hood.# `whisker dev` (from @nike/whisker-module-kit) finds whisker-host on your# machine the first time you run it — see Day 1 below — offering to clone# it via SSH next to your module if it can't.End state in the new repo:
my-module/ src/ moduleManifest.ts ← your platform surface components/ ← your code config/whisker.config.json ← orchestration (do not hand-edit) module-federation.config.ts package.json ← whisker-module-kit + WCL pinned Jenkinsfile ← branch-aware, ready .husky/ ← pre-commit + post-commit hooks wired .github/workflows/notify-host.yml .cursor/rules/thundercats-core.mdc ← written by create-whisker itself AGENTS.md ← written by create-whisker itself@thundercats itself doesn’t live in the repo — it’s the global Cursor skill
installed once per machine via thundercats install-skill, and it already
works here the moment the repo exists.
Day 1 — develop
Section titled “Day 1 — develop”pnpm exec whisker doctor # pre-flight checkspnpm exec whisker dev # full stack against the test BFFwhisker dev generates and validates the manifest, locates (or auto-clones)
whisker-host, builds your module with VITE_IS_LOCAL=true, rebuilds the
host’s remote loader, and starts everything with browser-sync proxying
the host with reload on remoteEntry.js changes. You open the browser-sync
URL and see the entire registered platform plus your local module. SIGINT
tears everything down cleanly.
Day 1 — write code
Section titled “Day 1 — write code”import { useAuth, useInEditMode } from 'whisker-host/remoteSafeSelectors';import { DataTable, useModuleAnalytics, nikeTheme } from '@nike/whisker-component-library';import { ThemeProvider } from '@mui/material';import { useParams, Link } from 'react-router-dom';
export default function InventoryPage() { const { accessToken, loggedIn } = useAuth(); const inEditMode = useInEditMode(); const { storeId } = useParams(); const { trackEvent, trackError } = useModuleAnalytics('my-module'); return <ThemeProvider theme={nikeTheme}>{/* your UI */}</ThemeProvider>;}You do not initialize analytics, mount your own router, set up auth, or configure MUI — the host and WCL already did.
Day N — ship
Section titled “Day N — ship”git push # Jenkins CI: generate-manifest → validate-manifest → vite build # → aws s3 sync to whisker-modules-test → upload manifest to whisker-manifest-test# Lambda picks up the manifest, merges, writes to DynamoDB# Module appears in test immediatelyMerging to main follows the same flow against the prod bucket, but the
Lambda preserves any admin-controlled enabled / allowedPersonas values —
your first production publish lands behind an admin “turn it on” decision.
.github/workflows/notify-host.yml fires a repository_dispatch so the
host’s federation config picks up your remoteEntry.js on its next build.
Path B — iframe consumer (existing app)
Section titled “Path B — iframe consumer (existing app)”Day 0 — convert
Section titled “Day 0 — convert”cd existing-appthundercats add iframe-consumer# back-compat: npx @nike/create-whisker add-iframe-consumer# thundercats init runs automatically here tooThis detects your package manager and JS/TS from your lockfile, writes
src/moduleManifest.(ts|js) with iframeIntegration and
config/whisker.config.json (hostPort: 3001), patches
package.json#scripts.dev to shell into whisker dev, and scans for
*_ORIGINS arrays to patch idempotently. Your existing build, CI,
framework, and tests are untouched.
Day 1 — develop
Section titled “Day 1 — develop”pnpm dev # your existing command — now shells into `whisker dev`This regenerates the manifest, starts your child app on its port, and
starts whisker-host on 3001 with VITE_LOCAL_IFRAME_APPS pointing at your
local app. Navigate to your module’s route and whisker-host renders
IframeRenderer with your app inside it.
Day 1 — get an auth token
Section titled “Day 1 — get an auth token”window.parent.postMessage({ name: 'requestAccessToken' }, '*');
window.addEventListener('message', (event) => { if (event.data.name === 'accessToken') { const { token, authType } = event.data; // use it }});The host handles refresh transparently. This is the same protocol rwe-core / T.R.U.E speaks — apps that worked there work here unchanged.
Day 1 — make the embed feel native
Section titled “Day 1 — make the embed feel native”document.body.classList.add('whisker-embedded');body.whisker-embedded { scrollbar-width: none;}body.whisker-embedded::-webkit-scrollbar { display: none;}The host already handles iframe sizing; suppressing internal scrollbars makes the embed look like part of the host.
Day N — ship
Section titled “Day N — ship”Your CI publishes your manifest to S3 the same way federation modules do.
Your app deploys wherever it already deployed — no federation bundle, no
remoteEntry.js, no build-time GitHub Actions handshake needed.
Updating either kind of module
Section titled “Updating either kind of module”| Change | Path |
|---|---|
| Add a navigation item / widget | Edit navigation[] / widgets[] in src/moduleManifest.ts, commit, push. For federation nav, reference pages by pageId (not path). navigation.componentPath is optional and only needed for custom icon components. Husky regenerates + validates. Host picks it up on next page load. |
| Rename a component | Treated as new — the old name is hard-deleted, the new one shows up with the manifest’s declared enabled. |
| Restrict a page to admins | Edit pages[].allowedPersonas, ship — unless an admin previously overrode it via the (planned) config panel, in which case their override wins. |
| Update your team’s Slack channel | Edit notifications.slack.channel — nightly + pipeline alerts route accordingly. |
What you don’t have to do
Section titled “What you don’t have to do”- Open a PR against
whisker-host. Never. For anything. - Coordinate a release with the platform team.
- Wire your own analytics, auth, theming, routing, or store context.
- Maintain a CORS/origin allow-list — the host derives it from the registry.
What you do have to do
Section titled “What you do have to do”- Keep your
src/moduleManifest.tshonest. - Run
whisker doctorif something feels off. - Periodically run
thundercats audit(andupdateif drift is reported) to keep.cursor/in sync; re-runthundercats install-skillafter anythundercats upgradeto keep the global skill current. - Run
pnpm update @nike/whisker-module-kitwhenupdate-checkflags a newer version. - For federation modules: be careful renaming a
componentPath— the manifest reference must match what your module actually exports. - For iframe consumers: maintain whatever build/deploy/test pipeline you already had; the platform only sits on top of it.
Where to ask for help
Section titled “Where to ask for help”thundercats audit— read-only diagnostic of this repo’s.cursor/layout.pnpm exec whisker doctor— first stop for “it won’t run” questions.@thundercatsin your IDE — routes tomodule-author,bff-service-author, ormanifest-validatoras appropriate.notifications.slack.channelin your manifest — used by the nightly runner.- This documentation tree — start at the WhiskerPlatform Architecture diagrams and the contract.
