One repo per team
This tutorial creates a polyrepo: a platform repo, a shell repo and one repo for each remote. You run the shell next to a remote from another repo, then add a team repo. At the end you know the steps that only you can do: GitHub and a package registry.
mfeflow writes the repos on your machine. It never calls GitHub. For why you might want this layout, read the FAQ.
Before you start
You need Node.js 22.12 or newer, pnpm 12.16.1, git and mfeflow 0.6.0 or newer. The first install needs the network.
Check your versions:
You should see something like this:
1. Create the repos
Run the creator with the topology and the remotes:
It writes four folders, runs git init in each and installs each one. The last lines are:
This is what each folder holds:
Every folder is its own git repo with its own mfeflow.json. Go into the org folder:
2. Build the platform packages
The platform repo publishes two packages: @acme/contracts and @acme/tokens. The shell and the remotes read them through link: paths, so build them first:
You should see both packages build:
Check that the output exists:
You should see the compiled files:
The shell's package.json points at them with link:../../../platform/packages/contracts. These two packages need no registry, which is why it is the default. Publish the packages replaces it later.
3. Run the shell and the remotes
Start a remote in its own terminal. This one is the catalog:
Start the cart the same way in a third terminal. Then start the shell in the first terminal:
You should see the shell start:
Open http://localhost:4300. You should see a header with home, catalog and cart. The home page shows both remotes.
The shell does not read a registry folder in dev. It reads devRemotes in shell/apps/shell/public/config/runtime-config.dev.json:
Each remote repo serves on the port in that file. To use a remote you run somewhere else, add --remote to the command:
The first line says which remote is yours:
See Develop locally for the other flags.
4. Add a team repo
A new team gets a new repo. Run this in the shell repo:
It creates ../checkout as a git repo and registers the remote in the shell. The last lines are:
The shell got a route, staging and prod registry entries and a dev server entry on port 4313. If mfeflow dev is still running, the shell lists the new remote without a restart.
Preview the change first with --dry-run. Nothing is written in either repo:
You should see Dry run: nothing was written.
Check the shell repo:
You should see no errors:
5. Put the repos on GitHub
This step is yours. For each folder, create an empty repo with the same name in your GitHub organization. Then push from that folder:
You should see a line like this from git:
Repeat for shell, catalog, cart and checkout. The CI and Renovate files point at <owner>/platform. The owner defaults to the scope without the @, here acme. If your GitHub owner is different, create the repos with --org <github-owner>, and init prints which owner the CI calls. add team-repo reuses the same owner.
Each team repo calls the reusable workflow in platform/.github/workflows/reusable-ci.yml. If the platform repo is private, allow the others to use it under Settings, Actions, General, Access.
6. Publish the platform packages
Until the packages are on a registry, only machines that have the folders side by side can install the other repos. CI cannot, because ../platform is not there. Pick one registry:
Whichever you choose, the release flow in the platform repo is the same. Describe a change with a changeset:
Commit the changeset and merge your pull request. Set the repository variable RELEASE_ENABLED to true. The release workflow then opens a "chore: version packages" pull request, and merging it publishes.
After the first publish, replace the links in each repo. This example is for the shell:
You should see both packages move from link: to a version in package.json. Do the same in each remote.
What you built
- A platform repo that publishes
@acme/contractsand@acme/tokenswith Changesets. - A reusable CI workflow and a Renovate preset that every repo uses.
- A shell repo that finds its remotes through a dev config, and a registry for staging and prod.
- A repo for each remote, and a command to add one more.
Every mfeflow.json has topology set to polyrepo and a repo of platform, shell or remote. See mfeflow.json.
Troubleshoot
add team-repo works in the shell repo of a polyrepo (E107). You ran the command in another repo, or in a monorepo. Go to the shell folder and run it again.
/path/to/acme/checkout already has notes.txt (E108). The folder next to the shell is not empty. Pick another name or move the folder.
--features ci-github: not in a polyrepo yet, every repo already calls the reusable workflow in the platform repo (E107). Leave the feature out. env-t3 is refused too, because it writes the runtime config files that hold the dev config.
upgrade does not work in the repos of a polyrepo yet (E107). Update the mfeflow packages in each repo by hand for now.
pnpm install fails in a team repo on CI. The link: paths need platform next to the repo. Publish the packages and replace the links.
Next
- Follow the same steps with real output in the polyrepo-teams example.
- Deploy and roll back a remote from its own repo.
- CLI reference for every flag of
initandadd.