Démarrer
npm create fougere shop --frond blog --app nuxt
cd shop && pnpm install && pnpm dev
Alpha. Les paquets
@fougere/*sont sur npm sous le tagalpha— le numéro de version est toute la promesse, la surface peut encore bouger. Ce site (site/) etdemos/nuxt-blogservent de références complètes. La structure ci-dessous correspond à l'état actuel. Vous avez déjà une app Nuxt ? Ajoutez-y Fougere.
Structure d'une app
Une app Fougere est une app Nuxt plus un répertoire fronds/ et un fichier de config :
mon-app/
fougere.config.ts ← persistance, auth, topologie
nuxt.config.ts ← modules: ['@fougere/nuxt']
fronds/
blog/
entities/Post.ts
handlers/PostHandler.ts
collectors/CurrentUserCollector.ts
seeds/Post.seed.ts
user/ ← un second domaine
entities/User.ts
app/
pages/ ← des pages Nuxt ordinaires, qui parlent via les primitives
Le scanner découvre les entités, handlers, collectors et seeds placés sous fronds/.
L'emplacement du fichier et le nom de la classe servent à leur enregistrement ; aucun
fichier de câblage supplémentaire n'est nécessaire.
Chaque dossier placé directement sous fronds/ définit une Frond. Une page importe une
entité avec le nom de ce dossier :
import Post from '@frond/blog/entities/Post';
@fougere/nuxt lit le scan et enregistre un alias @frond/<nom> par Frond, donc cet
import marche pour blog comme pour user — rien à ajouter, ni package.json, ni entrée
dans pnpm-workspace.yaml. Renommer une Frond, ou en importer une depuis autre chose
qu'une app Nuxt, est là où le package.json d'une Frond sert : voir
Frond — nommer et importer.
fougere new écrit les mêmes dossiers un cran plus haut — l'app sous apps/<nom>/, les
Fronds partagées à la racine du workspace, fougere: { root: '../..' } dans
nuxt.config.ts — pour que plusieurs apps consomment les mêmes domaines. Une app, un
dossier : la forme ci-dessus.
Un seul domaine, pas de fronds/ du tout
La racine du projet peut utiliser la même convention qu'un dossier sous fronds/. Une app
avec un seul domaine peut donc placer directement ses entités et handlers à la racine :
mon-shop/
fougere.config.ts
nuxt.config.ts
entities/Product.ts ← la racine EST la Frond, nommée d'après le dossier
handlers/ProductHandler.ts
app/pages/
fougere new mon-shop --flat --frond blog écrit exactement ça. import Product from '@frond/mon-shop/entities/Product' — même règle d'alias, pas de segment fronds/, et le
mot n'arrive que le jour où il y a deux domaines à distinguer. La racine doit au moins
porter un entities/ pour compter ; un services/ seul est un nom de dossier ordinaire.
Quand le deuxième domaine arrive, il va dans fronds/billing/ et la Frond racine reste
où elle est — rien ne bouge, aucun import n'est réécrit. fronds/ ne définit pas une
Frond, c'est là où vivent les autres.
fougere.config.ts — référence
import { defineFougere } from '@fougere/core';
import { betterAuth } from '@fougere/auth-better';
import User from './fronds/user/entities/User';
export default defineFougere({
// Persistance. Trois formes :
// 'sqlite' → mémoire côté Nuxt (resemée à chaque reload)
// { dialect: 'sqlite', path: '…' } → fichier (survit aux reloads et aux deploys)
// false → pas de db
db: { dialect: 'sqlite', path: '.data/app.db' },
// Topologie. Une Frond listée ici reste SCANNÉE (ses entités continuent de
// nourrir formulaires et validation en metadata) mais n'est pas hébergée
// localement : les appels voyagent en JSON-RPC vers le process qui l'héberge.
// Commenter la ligne → in-process.
// remotes: { blog: 'http://127.0.0.1:4100' },
// Auth (optionnel) — better-auth derrière une fine couche de traduction.
auth: betterAuth({
user: User, // votre entité qui étend AuthUser
secret: process.env.AUTH_SECRET!, // 32+ caractères
baseUrl: process.env.SITE_URL ?? 'http://localhost:3000',
basePath: '/auth', // monte /auth/** (sign-in, sign-up, sign-out…)
trustedOrigins: ['http://localhost:3000'],
sessionTtl: 30 * 24 * 60 * 60 * 1000,
providers: {
credential: { minPasswordLength: 8, autoSignIn: true },
// google: { clientId: …, clientSecret: … },
},
}),
});
Les tables dérivent de vos entités. Au boot, l'auto-DDL SQLite crée les tables manquantes et ajoute les colonnes absentes. Renommages, suppressions et changements de type demandent une migration explicite. Les seeds tournent après cette synchronisation et appellent les opérations avec leur validation habituelle.
Lancer
pnpm install
pnpm dev # scan → synchronise le schéma additif → seed → sert sur :3000
Vérifiez dans le log de boot le nombre de Fronds détectées :
INF [boot:app] scanned 2 frond(s) in 467ms
INF [boot] ready in 483ms — 2 frond(s) + auth (/auth)
Suite : Entités — le vocabulaire des champs et les quatre axes.