A frond from another repository
A frond can live in another repository, with its own team and release cycle. Your app still calls it. What has to reach your repository is its contract — its entities and operations — never its code.
Get the contract
Two commands, depending on how the other team shares it:
| What it does | When | |
|---|---|---|
fougere sync | asks the running frond for its card (rpc.discover) and writes its entities and facade into remotes/ | the frond is running — also the only way to use a frond written in another language |
fougere build-frond | compiles its entities/ into a package you install | the other team publishes its contract as a dependency |
Either way @fronds/<name> resolves, so your pages and handlers import the frond the same way as
one of your own.
Call it
Give it its address, as for any frond in another process:
// fougere.config.ts
fronds: { billing: { remote: 'https://billing.internal' } },
The two processes must be able to reach each other, and the receiver must know who calls it: Deploy a split and Secure calls between processes.
Facts across repositories
Finding the listeners. When the other frond has an address in your fronds:, its card says which
facts it accepts, and an announcement reaches it as a call — nothing more to write. A call keeps
nothing, though: a listener that is down misses the fact. When that matters, or when the other side
has no address you can call, put a carrier under the announcement — a queue or a broker of your
own. Both sides meet on the fact's name, read off their own code:
const app = await createApp({
root: import.meta.dirname,
createContainer,
onEmit: (fact, payload) => publishToYourBroker(fact, payload), // out
});
// in — the same local dispatch, validation and links included
await app.deliver(fact, payload);
// what to subscribe to, read off your own signatures
app.listensTo(); // ['postPublished']
Knowing the shape. A frond's card lists every fact its handlers announce, so fougere sync writes
the fact's class rather than you copying its fields. Re-export it into one of your fronds, and an
arriving fact is checked against the announcer's own declaration. When the shape changes, readers
deploy before the sender: see Changing a fact.
A carrier has no address. An announcement and a listener name nobody, so a carrier can take a fact
across. A Pipe<T> is called and answers, so it needs an address —
it crosses processes, never a carrier. Emit<T, A> draws the same line: it needs answers back.
emit-multirepo runs two projects and one fact, and loses the first publication on purpose to show what a carrier buys.