Skip to content

Infrastructure: Add a Win32 (Paper) Storybook endpoint #4259

Description

@JasonVMo

Summary

Add a Win32 Paper endpoint to apps/storybook using
@office-iss/react-native-win32 and the prebuilt @office-iss/rex-win32 host.
It must run the same story catalog and portable automation manifest as macOS
and Windows Fabric without changing or destabilizing either existing endpoint.

The current Storybook app declares only macOS and Windows Fabric projects, while
the repository's existing Win32 tester proves the required bundle and host
toolchain already exists.

Goal

Add an @office-iss/react-native-win32 endpoint to the agentic Storybook app,
hosted by the prebuilt @office-iss/rex-win32 ReactTest.exe, running the same
story set as the macOS and Windows Fabric endpoints, without changing or
destabilizing either existing endpoint.

Stage

Stage 2 (beta) for phases 1-2 (endpoint + local automation); Stage 3 (production)
for phase 3 (CI gate and supported-endpoint status).

Observed. apps/storybook today declares exactly two native projects - macos
and windows - through react-native-test-app's configureProjects
(apps/storybook/react-native.config.js),
and app.json lists resources only for macos and windows. There is no win32
bundle target, no win32 launch script, and no win32 entry in the app manifest.

Observed. The repository already runs a Win32 Paper application:
apps/win32 (@fluentui-react-native/tester-win32) depends on
@office-iss/react-native-win32 (resolved 0.81.8) and dev-depends on
@office-iss/rex-win32@0.81.1, bundles with rnx-cli bundle to
dist/index.win32.bundle, and launches with
rex-win32 --bundle index.win32 --component FluentTester --basePath ./dist ....

Inferred. Adding a Win32 Storybook endpoint is primarily a bundling, entry
registration, and host-invocation problem, not a native build problem, because
rex-win32 ships a prebuilt host.

Why it matters

Observed. The agentic components declare @office-iss/react-native-win32 as an
optional peer dependency
(packages/agentic/components/package.json),
and Win32 PR is a first-class CI job for the legacy tester
(.github/workflows/pr.yml). The agentic library
therefore claims Win32 support that no agentic-specific app currently exercises.

Observed. packages/agentic/design contains exactly one win32 platform file,
src/theming/platformUtils.win32.ts,
which supplies a win32-specific isHighContrast implementation. Inferred: any
divergence in win32 theming, high-contrast behavior, or Paper-vs-Fabric layout is
currently unverifiable for the agentic library.

Inferred. Storybook is the demonstration and validation surface for the agentic
components. If Win32 is a supported endpoint for consumers, it needs the same
surface, otherwise "supported" rests on type declarations rather than a running app.

Observed current state

Host and renderer

Observed. @office-iss/rex-win32@0.81.1 publishes a prebuilt host - its files
list includes ReactTest.exe, react-native-win32.dll, react-native-sdk.dll,
DefaultPlugin.dll, PlatformBundlePlugin.dll, foundation.win32.bundle,
msptls.dll, office.odf, and offsym.ttf. Its CLI accepts --plugin,
--bundle, --component, --basePath, --timeout, --useFastRefresh,
--useDirectDebugger, --checkInTest, --crashOnRedBox, --jsEngine,
--windowTitle, --useDevMain, --pluginProps, and --debugBundlePath.

Observed. @office-iss/react-native-win32@0.81.8 declares
"main": "./index.win32.js" and ships metro-react-native-platform.js, whose
reactNativePlatformResolver rewrites react-native and react-native/...
specifiers to the platform implementation package for a given platform. This is the
mechanism by which a win32 Metro build resolves the fork.

Observed. react-native-test-app@5.3.3, as resolved in
apps/storybook/node_modules, contains android, common, example, ios,
macos, visionos, and windows directories, and its bins are init,
init-test-app, configure-test-app, and install-windows-test-app. There is no
win32 host. Inferred: the Win32 endpoint cannot be produced by the same
react-native-test-app mechanism that produces the macOS and Windows Fabric
endpoints; it must follow the apps/win32 rex-win32 pattern instead.

Confirmed / Observed - Paper. The Win32 endpoint is the Paper renderer.
Supporting evidence: apps/storybook/README.md records that for the Windows Fabric
endpoint "the Callout package is autolinked as a Windows Fabric native library; its
Paper implementation remains built into the platform", and
packages/native/Callout/src/CalloutNativeComponent.ts
declares paperComponentName: 'RCTCallout' while
packages/native/Callout/react-native.config.cjs
declares a native dependency project for windows only.

Entry point and story reuse

Observed. apps/storybook/index.js registers
the app with AppRegistry.registerComponent(appName, () => StorybookApp) where
appName comes from app.json (AgenticStorybook). rex-win32 selects the
registered component with --component, so the same registration name is directly
usable.

Observed. Story discovery is platform-neutral: prebuild runs
sb-rn-get-stories --config-path src, which generates the git-ignored
src/storybook.requires.ts from the globs in
apps/storybook/src/main.ts. Nothing in
apps/storybook/src imports a platform fork - grep -rn "react-native-windows|react-native-macos|win32" apps/storybook/src
matches only a comment in the safe-area stub.

Observed. Bundling is already rnx-kit-driven: the app's rnx-kit.bundle
entry targets macos and windows with per-platform bundleOutput paths and a
duplicates-checker plugin that ignores pretty-format and react-is.
apps/win32 uses the same mechanism with targets: ["win32"] and
bundleOutput: dist/index.win32.bundle.

Dependency and version landscape

Observed. apps/storybook/package.json depends on react-native@^0.81.6,
react-native-macos@^0.81.0, react-native-windows@^0.81.0, and
react-native-svg@^15.12.1, with react-native-svg disabled for the windows
platform in react-native.config.js. Adding @office-iss/react-native-win32 makes
four React Native forks resolvable from a single package.

Observed. AGENTS.md states: "Do not import more than
one fork into a single program's type graph (it produces order-dependent type
confusion under the unified build). Keep fork imports in .win32.ts /
.windows.ts / .macos.ts files, or redeclare the needed shapes
platform-neutrally." Inferred: since apps/storybook/src imports no fork today,
adding the win32 fork as a dependency is type-safe only if that property is
preserved.

Observed. @rnx-kit/align-deps already models the fork as a distinct
capability: core-win32 is defined in
scripts/configs/rnx-kit/furn-preset.cts
and used by apps/win32; packages/agentic/design uses core-win32-dev-only.

Automation landscape

Observed. apps/E2E/wdio.conf.win32.js
automates a rex-win32 app today by resolving ReactTest.exe from the
@office-iss/rex-win32 package and passing
appium:appArguments = basePath <dist> plugin defaultplugin bundle index.win32 component FluentTester
with appium:automationName: 'windows' and appium:appWorkingDir set to the
package directory. Win32 PR in pr.yml runs this on windows-latest after
installing WinAppDriver 1.1.

Observed. The desktop driver has no Win32 concept:
DesktopPlatform = 'macos' | 'windows' | 'fake' and
DesktopBackendId = 'mac2' | 'windows' | 'novawindows' | 'fake' on the test-driver
branch. Inferred: because rex-win32 apps are automated through the same Appium
windows driver as Fabric apps, a Win32 target is most likely a new
platform/launch profile over the existing windows backend rather than a new
backend - but that must be verified, not assumed, because the window title, process
name (ReactTest.exe versus ReactApp.exe), and launch arguments all differ.

Scope

Phase 1 - endpoint

  • Decide and document the endpoint's package boundary (see Risks): either a win32
    bundle target added to apps/storybook, or a sibling app package that reuses
    apps/storybook's Storybook config, stories, and entry.
  • Add a win32 rnx-kit bundle target producing dist/index.win32.bundle plus a
    win32 Metro configuration that resolves react-native to
    @office-iss/react-native-win32 for the win32 platform.
  • Add declared scripts mirroring the existing naming conventions:
    bundle:win32 (prebuild + bundle) and win32 (launch through rex-win32 with
    --component AgenticStorybook, --basePath ./dist, --bundle index.win32, and a
    stable --windowTitle).
  • Verify Storybook liteMode renders on Paper, including the existing Metro mocks
    (@storybook/react-native-ui emptied, react-native-safe-area-context stubbed)
    and the persistent theme header.
  • Resolve react-native-svg on win32: Observed: apps/win32 uses
    react-native-svg with react-native-svg-transformer, while apps/storybook
    disables react-native-svg for the Fabric windows platform and uses no svg
    transformer.
  • Verify Callout stories on win32, where the Callout native implementation is built
    into the platform rather than autolinked, or exclude them with a documented
    reason.
  • Verify the win32 theming path, including
    packages/agentic/design/src/theming/platformUtils.win32.ts.

Phase 2 - automation

  • Make the channel server and REST control path work against the win32 app
    (storybook:control list|select|args, storybook:smoke).
  • Extend the desktop driver with a Win32 target: platform/launch profile, window
    discovery for the rex-win32 window, testID mapping verification, and portable
    command-matrix conformance.
  • Prove the same generated story-test manifest digest on Win32 as on Windows Fabric
    and macOS.

Phase 3 - build and CI

  • Add a Win32 Storybook CI job on windows-latest modeled on the existing
    Win32 PR job: install, build, bundle:win32, install WinAppDriver, launch, run
    the desktop suite, upload artifacts.
  • Add the endpoint to the documented supported-endpoint matrix and to the beta and
    production exit criteria of storybook-e2e.md.

Coexistence requirements

  • The macOS and Windows Fabric endpoints must build, launch, and pass their existing
    validation unchanged after the win32 work lands.
  • Generated win32 output stays git-ignored, consistent with the existing
    dist/ and artifacts/ ignore rules.
  • The duplicate-module checker must remain enabled for the win32 bundle, with any
    new ignore entry justified.
  • No fork import may be introduced into shared Storybook source; platform-specific
    code, if any, goes in .win32.ts/.win32.tsx files.

Out of scope

  • React Native Windows Fabric changes of any kind.
  • Migrating apps/win32 (FluentTester) onto Storybook or retiring it.
  • Native code changes in @office-iss/react-native-win32 or rex-win32.
  • Adding win32 implementations to agentic components that lack them; this task
    reports gaps, the Components workstream fixes them.
  • Publishing a win32 Storybook build to any distribution channel.

Deliverables

  1. A documented decision record on the endpoint package boundary.
  2. A win32 bundle target and Metro/platform resolution configuration.
  3. Declared bundle:win32 and win32 scripts with the repository's script naming
    and documentation conventions.
  4. A story-compatibility report: which stories render on Paper, which do not, and
    why.
  5. Win32 automation support in the desktop driver, or a documented decision that
    the win32 endpoint uses the existing windows backend with a distinct launch
    profile.
  6. A Win32 Storybook CI job.
  7. Updates to apps/storybook/README.md and apps/storybook/AGENTS.md covering the
    win32 workflow and its distinction from the Windows Fabric workflow.

Acceptance criteria

  • bundle:win32 produces dist/index.win32.bundle with the duplicate-module
    checker enabled and no new unjustified ignore entries.
  • The win32 app launches through rex-win32 and renders the Storybook UI,
    including the persistent theme header and theme switching.
  • The win32 story index returned by GET /index.json matches the macOS and
    Windows Fabric story indices, or every difference is documented with a reason.
  • storybook:control select <storyId> selects a story on win32 and the app
    emits storyRendered.
  • yarn workspace @fluentui-react-native/agentic-components-storybook macos:build
    (or bundle:macos) and the Windows Fabric windows:ci chain still succeed
    after the change, and yarn windows:test still passes.
  • The root yarn build (tsc -b) succeeds, and no shared Storybook source file
    imports more than one React Native fork.
  • yarn lint-repo, yarn check-publishing, and align-deps checks pass with the
    win32 capability declared explicitly (core-win32).
  • A desktop story-test run against the win32 endpoint reports the same manifest
    digest as the Windows Fabric and macOS runs.
  • A CI job bundles and exercises the win32 endpoint and uploads its artifacts
    with if: always().
  • Documentation states explicitly that win32 is the @office-iss/react-native-win32
    Paper endpoint and is not the React Native Windows Fabric endpoint.

Dependencies and ordering

  • Depends on: test-driver.md for phase 2 automation, and on
    test-driver-release-readiness.md before a
    Win32 gate becomes required. Phase 1 (the endpoint itself) depends on neither and
    can proceed in parallel.
  • Blocks: the Win32 job in phase 3 of storybook-e2e.md.
  • Ordering (Inferred): deliver the endpoint and manual verification first; add
    driver support second; add CI last. Doing driver work before the app exists would
    require designing a Win32 target against no running application.

Risks and open decisions

Item Evidence Decision or risk
Package boundary Observed: apps/storybook already carries react-native, react-native-macos, and react-native-windows; AGENTS.md forbids more than one fork in one type graph. Decide: a fourth fork in the same package with strict source discipline, or a sibling win32 app package that reuses the same src.
No react-native-test-app win32 host Observed: react-native-test-app@5.3.3 has no win32 directory. The win32 endpoint diverges architecturally from the other two; app.json resources and configureProjects do not apply to it.
Storybook on Paper Observed: liteMode already removes reanimated/gesture-handler/bottom-sheet/svg from the Storybook UI chain; Inferred: that makes Paper compatibility plausible. It is not verified. Must be proven by running the app; a failure here changes the whole task shape.
react-native-svg on win32 Observed: apps/win32 depends on react-native-svg plus react-native-svg-transformer; apps/storybook disables svg on Fabric windows and has no svg transformer. Decide whether win32 Storybook needs svg, and whether that forces a transformer into the Storybook Metro config.
Callout stories on win32 Observed: Callout declares a native project for windows only; paperComponentName: 'RCTCallout'; the Storybook README states the Paper implementation is built into the platform. Verify the built-in RCTCallout satisfies the current NativeProps, or exclude Callout stories on win32 with a documented reason.
Fast refresh / Metro dev loop Observed: rex-win32 supports --useFastRefresh and --useDirectDebugger; apps/win32 uses rnx-cli start. Confirm the Storybook withStorybook Metro wrapper and the win32 dev loop interoperate.
Window title and process identity for automation Observed: the Fabric app's automation targets window title Agentic Components Storybook and process ReactApp.exe; rex-win32 runs ReactTest.exe with a --windowTitle argument. Choose a distinct, stable win32 window title so attach-mode discovery cannot select the wrong app when both are running.
Two Windows-family endpoints running together Inferred from the above: both use the Appium windows driver and could both be open on one machine. Automation must disambiguate by explicit window title or PID, never by substring or layout order.
Version alignment Observed: @office-iss/react-native-win32 resolves to 0.81.8; rex-win32 is pinned exactly at 0.81.1. Host and fork versions must stay compatible; pin and document the pair.
Windows path length Observed: the Fabric Release package already hits a Windows deployment path limit for a Storybook asset under the Yarn pnpm linker. The win32 basePath/bundle layout should be checked against the same limit.

Evidence and references

Retrieved 2026-08-20.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions