Skip to content

[FEATURE] allow choosing the parent directory when creating a new MFE #283

@gs-layer

Description

@gs-layer

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?

  • @cyberfabric/api
  • @cyberfabric/auth
  • @cyberfabric/cli
  • @cyberfabric/framework
  • @cyberfabric/i18n
  • @cyberfabric/react
  • @cyberfabric/screensets
  • @cyberfabric/state
  • @cyberfabric/studio
  • @cyberfabric/uikit

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

  • Low - Nice to have
  • Medium - Improves workflow
  • High - Blocking or critical for use case

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestfeatureNew featuremfesIssues related to MFEs implementation.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions