Shape your topology

So far the shop is one frond. This guide splits it in three — the catalog, the prices, the cart — has them call each other, then runs the catalog in its own process without changing their code.

Fronds

A frond is a directory under fronds/. It holds its own entities, handlers, services and repositories:

fronds/
  catalog/     Product, ProductHandler
  pricing/     PriceHandler
  cart/        CartHandler

A frond does not import another's files. It asks for another frond's facade, by type:

// fronds/pricing/handlers/PriceHandler.ts
import type { Facade } from '@fougere/core';
import type ProductHandler from '@fronds/catalog/handlers/ProductHandler.js';

export default class PriceHandler {
  constructor(private catalog: Facade<ProductHandler>) {}

  async getTotal(): Promise<number> {
    const products = await this.catalog.list();

    return products.items.reduce((sum, product) => sum + product.cents, 0);
  }
}
// fronds/cart/handlers/CartHandler.ts
import type { Facade } from '@fougere/core';
import type PriceHandler from '@fronds/pricing/handlers/PriceHandler.js';

export default class CartHandler {
  constructor(private pricing: Facade<PriceHandler>) {}

  async getSummary(): Promise<{ cents: number }> {
    return { cents: await this.pricing.getTotal() };
  }
}

fougere graph prints the three fronds and which one calls which.

→ Frond

Moving a frond

To run the catalog in its own process, start it alone:

fougere dev catalog --port 4620       # in production: fougere build, then fougere serve

and give it that address in fougere.config.ts:

export default defineFougere({
  fronds: { catalog: 'http://127.0.0.1:4620' },
});

PriceHandler keeps calling this.catalog.list() the same way; the call now crosses the network. Remove the line and the catalog runs in the app's process again.

→ The gradient · CLI

Built with Fougere and Nuxt, hosted on GitHub Pages.