Scaffold a RegistrationFlowSkill orchestrator using the Stepper system
57
72%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Use this skill when the task is to build a registration flow orchestrator — a Smart component that:
PartySearch, PartyRegistration, and DocumentPicture.onResultData when the entire chain succeeds.Do not use this skill to modify the Stepper core files, the MFE remote components, or any shared service layer. This skill only concerns the orchestrator component itself.
The Stepper core is already available at skillsTESSL/stepper/. The orchestrator must import from it — never copy or duplicate its internals.
| Placeholder | Usage |
|---|---|
COMPONENT_NAME | PascalCase name for the orchestrator folder and files (e.g. RegistrationFlowSkill). |
CATEGORY_NAME | Subfolder under src/components for this domain (e.g. flows, registration). |
BASE_PATH | Router base path used by the Stepper for URL segments (e.g. /registration). |
MODULE_TITLE | Static text shown in the Header (e.g. Partners - Individual). |
SESSION_EMAIL | Mocked session email shown in the Header (e.g. osmorato@cconer.com). |
SESSION_ROLE | Mocked session role shown in the Header (e.g. Operational Control). |
This skill follows the same Component Folder Pattern defined in the react-component skill. Flat .tsx files are strictly forbidden.
The orchestrator must be generated inside its own PascalCase subfolder containing exactly:
COMPONENT_NAME.tsx — the orchestrator implementation.COMPONENT_NAME.types.ts — props, result, and accumulated payload interfaces.COMPONENT_NAME.steps.tsx — the step definitions builder (returns the StepConfig[] array).COMPONENT_NAME.service.ts — the backend orchestration chain (no React imports allowed here).index.ts — barrel export.SDD_COMPONENT_NAME.md — Software Design Document.Create the types file first. It must declare three interfaces:
Props interface — the public API of the orchestrator. It receives two props:
initSettings: an object containing partyId (integer), orderId (integer), and configId (string or integer). These values are passed down to each MFE step as initialization context.onResultData: a callback that the orchestrator calls once — and only once — after the full backend orchestration chain completes successfully. It emits a result object that includes at minimum partyId, orderId, a status field set to 'completed', and a completedAt ISO timestamp.Accumulated payload interface — an internal shape that holds the data collected from each step as the user progresses. It has one optional key per step (partySearch, partyRegistration, documentPicture), each typed as a generic data record.
Result interface — the shape emitted via onResultData. It must include partyId, orderId, status: 'completed', and completedAt.
Create the steps file. Its only export is a builder function that receives initSettings and an onStepResult callback, and returns the StepConfig[] array consumed by the Stepper.
Each of the three steps must:
key in kebab-case — this becomes the URL segment in the Stepper router.label.module-federation skill for the correct consumption pattern.initSettings down to the MFE child as its initialization context.onResultData callback to call onStepResult(stepKey, data) so the orchestrator can accumulate the payload.loading fallback and an error fallback.The three steps in order are:
| Step index | Key | Label | MFE form |
|---|---|---|---|
| 0 | party-search | Party Search | PartySearch |
| 1 | party-registration | Party Registration | PartyRegistration |
| 2 | document-picture | Document Picture | DocumentPicture |
The MFE remote URLs, mfe names, and component expose keys must be resolved at implementation time from the project's module-federation.config.ts files. Do not hardcode placeholder strings — look them up before generating the file.
Create the service file. It must contain a single exported async function that receives initSettings and the accumulated payload, and executes the following four operations in strict sequential order:
orderId and the payload from the last step.partyId and orderId plus the accumulated payload.partyId and the relevant payload slice.partyId and orderId.Each operation must be its own private async function inside the service file so it can be replaced with a real API call independently. Until real endpoints exist, each function logs its arguments via console.info and resolves successfully.
Hard rules for the service file:
await in order, never Promise.all or Promise.allSettled.Create the main component file. It is a Smart component that owns the orchestration state and delegates all UI rendering to the Stepper and all form logic to the MFE children.
The component renders a full-page flex column with three regions:
MODULE_TITLE on the left and SESSION_EMAIL / SESSION_ROLE stacked on the right. Tailwind className only, no inline styles.Stepper component with the steps array and the navigation control object. If a submission error occurred, an error banner is shown above the Stepper.Processing…) during that time.| State | Hook | Rationale |
|---|---|---|
| Accumulated step payloads | useRef | Mutations must not trigger re-renders |
| Submission in-progress flag | useState | Drives button disabled state and loading label |
| Submission error message | useState | Drives error banner visibility |
| Active step index | Internal to Stepper | The orchestrator must not duplicate this state |
The orchestrator builds a StepperNavigationControl object and passes it to the Stepper via the navigation prop. This object has three members:
canAdvance — returns true for all steps. Step-level validation is owned by each MFE child, not by the orchestrator.onNext — for non-last steps, returns true to let the Stepper advance. For the last step, calls handleFinish and returns false to prevent the Stepper from advancing past the final step.onFinish — calls handleFinish directly.handleFinish is an async function that:
isSubmitting to true and clears any previous error.initSettings and the current payloadRef.current.onResultData with the result object and sets isSubmitting to false.submitError with the error message, sets isSubmitting to false, and does not call onResultData.The Stepper's internal StepNavigation already renders a Continue/Finish button via StepperNavigationBridge. The Footer button is the visual shell affordance. At implementation time, decide whether to use the Stepper's built-in navigation or the Footer button — both must never coexist as two independent triggers for the same action.
The index.ts file must re-export the component by its PascalCase name and all public types from the types file. Consumers must always import from this barrel — never from internal files.
The orchestrator imports from the Stepper directory already present at skillsTESSL/stepper/. Resolve the relative path from the component file's location to that directory before generating any import statement.
| What to import | Source file inside stepper/ |
|---|---|
Stepper component | components/Stepper.tsx |
StepperNavigationControl type | hooks/useStepper.ts |
StepConfig type | hooks/useStepper.ts |
Do not import useStepper, useFlowSteps, or any internal Stepper hook directly in the orchestrator. Navigation is controlled exclusively through the StepperNavigationControl object passed as the navigation prop.
For the MFE service layer, follow the import rules defined in the module-federation skill.
Host
└─ <COMPONENT_NAME initSettings onResultData />
│
├─ buildSteps() → StepConfig[]
│ └─ each step: MFE child → onResultData → onStepResult(key, data) → payloadRef
│
├─ <Stepper steps navigation />
│ └─ StepperNavigationBridge → navigation.onNext(index, isLastStep)
│
└─ Last step → handleFinish()
│
├─ 1. registerOrder()
├─ 2. associateOrderAndUpdateParty()
├─ 3. updateContactsAndAddresses()
├─ 4. startBackendProcessFlow()
│
└─ ✅ All succeed → onResultData({ status: 'completed', ... })
❌ Any fails → submitError shown, onResultData NOT calledonResultData before the full orchestration chain resolves. Partial success is not success.await in order — never Promise.all or Promise.allSettled.canAdvance.style={{ }} — Tailwind className with CSS custom properties (var(--color-*)) only.any. All callbacks and data shapes must have explicit TypeScript interfaces.payloadRef is the single source of truth for accumulated step data. Do not duplicate it in useState.../-based path from the component file's location before generating any import statement. Never hardcode absolute paths..tsx files are forbidden. See the react-component skill for the full specification.mfe field in LoadComponent must match exactly the name field in the remote's module-federation.config.ts. Look it up before generating the step definitions.SDD_COMPONENT_NAME.md)The Software Design Document must include at minimum:
initSettings fields and onResultData signature.onResultData.A fully wired, type-safe registration flow orchestrator: a Smart container that drives three MFE forms through the Stepper system, accumulates their payloads, executes a sequential backend chain on completion, and emits a single onResultData event only on full success — ready for composition in any host application.