Description
Add a --dir option to frontx screenset create so the user can place a new microfrontend (MFE) in a directory of their choice instead of the hardcoded src/mfe_packages/. Make MFE-discovery scripts (dev:all, manifest generation, port assignment, type-check) read the union of all configured MFE roots from frontx.config.json so MFEs can coexist across multiple directories within a single project.
Problem Statement
frontx screenset create <name> currently scaffolds every MFE under the hardcoded path src/mfe_packages/<name>-mfe/. The same path is hardcoded inside the MFE-discovery scripts (scripts/dev-all.ts, scripts/generate-mfe-manifests.ts, scripts/run-mfe-type-checks.mjs), so any MFE placed elsewhere by hand is silently ignored: manifest imports break, port assignment double-allocates, and dev:all cannot launch it.
This rigid layout assumes one project = one host application = one shared bag of MFEs. That assumption fails when a monorepo hosts more than one host application, a setup that surfaces several scenarios the current structure cannot express:
- Some MFEs logically belong to a specific host and should live next to it rather than in a single shared bucket.
- Other MFEs are reused across hosts and should live in a neutral shared directory visible to every consumer.
- Each host should be able to build and run only its own subset, while every MFE remains independently runnable and discoverable by the
dev:all of its host.
Without a way to choose the MFE directory, these layouts can only be achieved manually — moving files, fixing relative imports inside generated-mfe-manifests.ts, patching dev:all, reassigning ports.
Proposed Solution
- Add an optional
--dir <relative-parent-dir> flag to frontx screenset create. The MFE folder name is still auto-derived as <kebab-name>-mfe and appended to the chosen parent, so the final path becomes <project-root>/<--dir>/<kebab-name>-mfe/.
- Validate the value of
--dir: it must be relative (no leading / or Windows drive letter), must not contain .. segments, and each segment is restricted to [a-zA-Z0-9_.-].
- Extend
frontx.config.json with two independent fields:
mfeRoots: string[] — registry of every directory ever used to scaffold an MFE in this project. Updated automatically whenever --dir is used with a previously unknown directory. This is the source of truth for multi-root discovery (port assignment, manifest, dev:all, type-check).
mfeRoot: string — user-preferred default for future screenset create calls without --dir. Written only when the user explicitly opts in via the interactive prompt.
- After scaffolding into a non-default directory, prompt the user whether to set the directory as the project default. The answer drives only
mfeRoot; the directory is added to mfeRoots[] unconditionally so discovery does not silently miss it.
- Update the discovery scripts (
dev-all.ts, generate-mfe-manifests.ts, run-mfe-type-checks.mjs) and their template-sources counterparts so they scan the deduplicated union of src/mfe_packages (always), mfeRoot, and every entry in mfeRoots[].
- Compute relative imports inside
src/app/mfe/generated-mfe-manifests.ts from each MFE's actual location, not from a fixed depth.
- Keep shared MFE infrastructure (
mfe_packages/shared/, mfe_packages/vitest.mfe.base.ts) under the legacy src/mfe_packages/ regardless of the chosen directory, for backwards compatibility.
Use Case / Example
- Use case 1 — multi-host monorepo with co-located MFEs. A repository hosts more than one host application. MFEs that conceptually belong to a specific host can be co-located with it instead of piling up under a single shared directory.
- Use case 2 — shared MFEs across hosts. A subset of MFEs is reused by several host applications. They can live in a neutral shared directory at a project-relative path, while host-specific MFEs stay in their host's tree, all discovered uniformly.
- Use case 3 — selective
dev:all per host. Each host's dev:all can launch only the MFEs registered for it through mfeRoots[], while every MFE remains an independently runnable application.
- Use case 4 — gradual migration. Existing projects with MFEs already under
src/mfe_packages/ keep working untouched; new MFEs created with --dir coexist with them and are picked up by every script automatically.
Affected Package(s)
Which FrontX package(s) would this impact?
Repo-level dev scripts (scripts/dev-all.ts, scripts/generate-mfe-manifests.ts, scripts/run-mfe-type-checks.mjs) and their template-sources copies inside @cyberfabric/cli are also touched.
Alternative Solutions
- Manual relocation. Scaffold under the legacy path and move files by hand, rewriting
generated-mfe-manifests.ts, port assignments, and dev:all after each scaffold. High maintenance cost; loses the ability to recreate the layout reproducibly via the CLI.
- Symlinks. Keep MFEs in
src/mfe_packages/ and expose them under another path via symlinks. Fragile across operating systems and CI environments; does not solve the discovery problem because scripts still see only the legacy path.
- Multiple per-host configs. Maintain a parallel manifest for each host that filters the global MFE list. Adds runtime complexity and does not address physical co-location of MFEs with their host.
- Single configurable root (no per-MFE override). Replace the legacy default with a single configurable directory but require all MFEs to live there. Insufficient for monorepos that need both shared and host-specific MFEs simultaneously.
Additional Context
- Backwards compatibility is preserved: with neither
--dir nor mfeRoot set, frontx screenset create behaves exactly as before — MFEs land under src/mfe_packages/<name>-mfe/.
- The
mfeRoots[] registry is updated even when the user declines to make the new directory the default; otherwise multi-root discovery would not find the MFE in subsequent commands and ports would collide.
- The shared infrastructure (
mfe-shared, vitest.mfe.base.ts) deliberately stays under src/mfe_packages/ to avoid breaking existing projects.
Priority
Description
Add a
--diroption tofrontx screenset createso the user can place a new microfrontend (MFE) in a directory of their choice instead of the hardcodedsrc/mfe_packages/. Make MFE-discovery scripts (dev:all, manifest generation, port assignment, type-check) read the union of all configured MFE roots fromfrontx.config.jsonso MFEs can coexist across multiple directories within a single project.Problem Statement
frontx screenset create <name>currently scaffolds every MFE under the hardcoded pathsrc/mfe_packages/<name>-mfe/. The same path is hardcoded inside the MFE-discovery scripts (scripts/dev-all.ts,scripts/generate-mfe-manifests.ts,scripts/run-mfe-type-checks.mjs), so any MFE placed elsewhere by hand is silently ignored: manifest imports break, port assignment double-allocates, anddev:allcannot launch it.This rigid layout assumes one project = one host application = one shared bag of MFEs. That assumption fails when a monorepo hosts more than one host application, a setup that surfaces several scenarios the current structure cannot express:
dev:allof its host.Without a way to choose the MFE directory, these layouts can only be achieved manually — moving files, fixing relative imports inside
generated-mfe-manifests.ts, patchingdev:all, reassigning ports.Proposed Solution
--dir <relative-parent-dir>flag tofrontx screenset create. The MFE folder name is still auto-derived as<kebab-name>-mfeand appended to the chosen parent, so the final path becomes<project-root>/<--dir>/<kebab-name>-mfe/.--dir: it must be relative (no leading/or Windows drive letter), must not contain..segments, and each segment is restricted to[a-zA-Z0-9_.-].frontx.config.jsonwith two independent fields:mfeRoots: string[]— registry of every directory ever used to scaffold an MFE in this project. Updated automatically whenever--diris used with a previously unknown directory. This is the source of truth for multi-root discovery (port assignment, manifest,dev:all, type-check).mfeRoot: string— user-preferred default for futurescreenset createcalls without--dir. Written only when the user explicitly opts in via the interactive prompt.mfeRoot; the directory is added tomfeRoots[]unconditionally so discovery does not silently miss it.dev-all.ts,generate-mfe-manifests.ts,run-mfe-type-checks.mjs) and theirtemplate-sourcescounterparts so they scan the deduplicated union ofsrc/mfe_packages(always),mfeRoot, and every entry inmfeRoots[].src/app/mfe/generated-mfe-manifests.tsfrom each MFE's actual location, not from a fixed depth.mfe_packages/shared/,mfe_packages/vitest.mfe.base.ts) under the legacysrc/mfe_packages/regardless of the chosen directory, for backwards compatibility.Use Case / Example
dev:allper host. Each host'sdev:allcan launch only the MFEs registered for it throughmfeRoots[], while every MFE remains an independently runnable application.src/mfe_packages/keep working untouched; new MFEs created with--dircoexist with them and are picked up by every script automatically.Affected Package(s)
Which FrontX package(s) would this impact?
Repo-level dev scripts (
scripts/dev-all.ts,scripts/generate-mfe-manifests.ts,scripts/run-mfe-type-checks.mjs) and theirtemplate-sourcescopies inside@cyberfabric/cliare also touched.Alternative Solutions
generated-mfe-manifests.ts, port assignments, anddev:allafter each scaffold. High maintenance cost; loses the ability to recreate the layout reproducibly via the CLI.src/mfe_packages/and expose them under another path via symlinks. Fragile across operating systems and CI environments; does not solve the discovery problem because scripts still see only the legacy path.Additional Context
--dirnormfeRootset,frontx screenset createbehaves exactly as before — MFEs land undersrc/mfe_packages/<name>-mfe/.mfeRoots[]registry is updated even when the user declines to make the new directory the default; otherwise multi-root discovery would not find the MFE in subsequent commands and ports would collide.mfe-shared,vitest.mfe.base.ts) deliberately stays undersrc/mfe_packages/to avoid breaking existing projects.Priority