[{"data":1,"prerenderedAt":1037},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fgetting-started":186},[4],{"title":5,"path":6,"stem":7,"children":8,"page":-1},"Docs","\u002Fdocs","docs",[9,12,16,20,24,28,50,75,120,145],{"title":10,"path":6,"stem":11},"What is Fougere","docs\u002Findex",{"title":13,"path":14,"stem":15},"Getting started","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",{"title":17,"path":18,"stem":19},"An app you already have","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"Bring your schema","\u002Fdocs\u002Fbring-your-schema","docs\u002F03.bring-your-schema",{"title":25,"path":26,"stem":27},"The CLI","\u002Fdocs\u002Fcli","docs\u002F04.cli",{"title":29,"path":30,"stem":31,"children":32,"page":49},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[33,37,41,45],{"title":34,"path":35,"stem":36},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":38,"path":39,"stem":40},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":42,"path":43,"stem":44},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",{"title":46,"path":47,"stem":48},"The base","\u002Fdocs\u002Fconcepts\u002Fthe-base","docs\u002F2.concepts\u002F4.the-base",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[55,59,63,67,71],{"title":56,"path":57,"stem":58},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":60,"path":61,"stem":62},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":64,"path":65,"stem":66},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":68,"path":69,"stem":70},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":72,"path":73,"stem":74},"How a schema moves","\u002Fdocs\u002Fschema\u002Fevolution","docs\u002F3.schema\u002F5.evolution",{"title":76,"path":77,"stem":78,"children":79,"page":49},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[80,84,88,92,96,100,104,108,112,116],{"title":81,"path":82,"stem":83},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":85,"path":86,"stem":87},"Ports","\u002Fdocs\u002Fbusiness\u002Fports","docs\u002F4.business\u002F10.ports",{"title":89,"path":90,"stem":91},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":93,"path":94,"stem":95},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":97,"path":98,"stem":99},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":101,"path":102,"stem":103},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":105,"path":106,"stem":107},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":109,"path":110,"stem":111},"Storage","\u002Fdocs\u002Fbusiness\u002Fstorage","docs\u002F4.business\u002F7.storage",{"title":113,"path":114,"stem":115},"Writes that stand or fall as one","\u002Fdocs\u002Fbusiness\u002Ftogether","docs\u002F4.business\u002F8.together",{"title":117,"path":118,"stem":119},"Repositories","\u002Fdocs\u002Fbusiness\u002Frepositories","docs\u002F4.business\u002F9.repositories",{"title":121,"path":122,"stem":123,"children":124,"page":49},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[125,129,133,137,141],{"title":126,"path":127,"stem":128},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":130,"path":131,"stem":132},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":134,"path":135,"stem":136},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":138,"path":139,"stem":140},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":142,"path":143,"stem":144},"Back-office","\u002Fdocs\u002Fclient\u002Fadmin","docs\u002F5.client\u002F5.admin",{"title":146,"path":147,"stem":148,"children":149,"page":49},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[150,154,158,162,166,170,174,178,182],{"title":151,"path":152,"stem":153},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":155,"path":156,"stem":157},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":159,"path":160,"stem":161},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":163,"path":164,"stem":165},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"title":167,"path":168,"stem":169},"Sources","\u002Fdocs\u002Finfra\u002Fsources","docs\u002F6.infra\u002F5.sources",{"title":171,"path":172,"stem":173},"Lifecycle","\u002Fdocs\u002Finfra\u002Flifecycle","docs\u002F6.infra\u002F6.lifecycle",{"title":175,"path":176,"stem":177},"Identity across Fronds","\u002Fdocs\u002Finfra\u002Fidentity","docs\u002F6.infra\u002F7.identity",{"title":179,"path":180,"stem":181},"Observability","\u002Fdocs\u002Finfra\u002Fobservability","docs\u002F6.infra\u002F8.observability",{"title":183,"path":184,"stem":185},"Testing","\u002Fdocs\u002Finfra\u002Ftesting","docs\u002F6.infra\u002F9.testing",{"id":187,"title":13,"body":188,"description":1032,"extension":1033,"meta":1034,"navigation":569,"path":14,"seo":1035,"stem":15,"__hash__":1036},"docs_en\u002Fdocs\u002F01.getting-started.md",{"type":189,"value":190,"toc":1024},"minimark",[191,195,263,295,300,307,315,347,353,386,419,437,445,451,457,476,489,493,962,965,978,982,1005,1008,1014,1020],[192,193,13],"h1",{"id":194},"getting-started",[196,197,202],"pre",{"className":198,"code":199,"language":200,"meta":201,"style":201},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","npm create fougere shop --frond blog --app nuxt\ncd shop && pnpm install && pnpm dev\n","bash","",[203,204,205,237],"code",{"__ignoreMap":201},[206,207,210,214,218,221,224,228,231,234],"span",{"class":208,"line":209},"line",1,[206,211,213],{"class":212},"sbgvK","npm",[206,215,217],{"class":216},"s_sjI"," create",[206,219,220],{"class":216}," fougere",[206,222,223],{"class":216}," shop",[206,225,227],{"class":226},"stzsN"," --frond",[206,229,230],{"class":216}," blog",[206,232,233],{"class":226}," --app",[206,235,236],{"class":216}," nuxt\n",[206,238,240,244,246,250,253,256,258,260],{"class":208,"line":239},2,[206,241,243],{"class":242},"sptTA","cd",[206,245,223],{"class":216},[206,247,249],{"class":248},"sP7_E"," &&",[206,251,252],{"class":212}," pnpm",[206,254,255],{"class":216}," install",[206,257,249],{"class":248},[206,259,252],{"class":212},[206,261,262],{"class":216}," dev\n",[264,265,266],"blockquote",{},[267,268,269,273,274,277,278,281,282,285,286,289,290,294],"p",{},[270,271,272],"strong",{},"Alpha."," The ",[203,275,276],{},"@fougere\u002F*"," packages are on npm under the ",[203,279,280],{},"alpha"," tag — the version\nis the whole promise, the surface can still move. This site (",[203,283,284],{},"site\u002F",") and\n",[203,287,288],{},"demos\u002Fnuxt-blog"," are complete references. The structure below matches the current\nimplementation. Already have a Nuxt app? ",[291,292,293],"a",{"href":18},"Add Fougere to it",".",[296,297,299],"h2",{"id":298},"application-structure","Application structure",[267,301,302,303,306],{},"A Fougere app is a Nuxt app plus a ",[203,304,305],{},"fronds\u002F"," directory and one config file:",[196,308,313],{"className":309,"code":311,"language":312},[310],"language-text","my-app\u002F\n  fougere.config.ts       ← persistence, auth, topology\n  nuxt.config.ts          ← modules: ['@fougere\u002Fnuxt']\n  fronds\u002F\n    blog\u002F\n      entities\u002FPost.ts\n      handlers\u002FPostHandler.ts\n      collectors\u002FCurrentUserCollector.ts\n      seeds\u002FPost.seed.ts\n    user\u002F                 ← a second domain\n      entities\u002FUser.ts\n  app\u002F\n    pages\u002F                ← ordinary Nuxt pages, talking through the primitives\n","text",[203,314,311],{"__ignoreMap":201},[267,316,317,318,320,321,324,325,328,329,328,332,328,335,338,339,342,343,346],{},"The scanner reads seven convention directories under ",[203,319,305],{}," — ",[203,322,323],{},"entities\u002F",",\n",[203,326,327],{},"handlers\u002F",", ",[203,330,331],{},"presenters\u002F",[203,333,334],{},"collectors\u002F",[203,336,337],{},"seeds\u002F",", and ",[203,340,341],{},"services\u002F"," + ",[203,344,345],{},"repositories\u002F",",\nwhich are two spellings of one provider list. File location and class name are used for\nregistration; no additional wiring file is needed.",[267,348,349,350,352],{},"Each directory directly under ",[203,351,305],{}," defines a Frond. A page imports an entity using\nthat directory name:",[196,354,358],{"className":355,"code":356,"language":357,"meta":201,"style":201},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import Post from '@fronds\u002Fblog\u002Fentities\u002FPost';\n","ts",[203,359,360],{"__ignoreMap":201},[206,361,362,366,370,373,377,380,383],{"class":208,"line":209},[206,363,365],{"class":364},"sVHd0","import",[206,367,369],{"class":368},"su5hD"," Post ",[206,371,372],{"class":364},"from",[206,374,376],{"class":375},"sjJ54"," '",[206,378,379],{"class":216},"@fronds\u002Fblog\u002Fentities\u002FPost",[206,381,382],{"class":375},"'",[206,384,385],{"class":248},";\n",[267,387,388,391,392,395,396,399,400,403,404,407,408,411,412,414,415,294],{},[203,389,390],{},"@fougere\u002Fnuxt"," reads the scan and registers a ",[203,393,394],{},"@fronds\u002F\u003Cname>"," alias per Frond, so that\nimport works for ",[203,397,398],{},"blog"," and ",[203,401,402],{},"user"," alike — nothing to add, no ",[203,405,406],{},"package.json",", no\n",[203,409,410],{},"pnpm-workspace.yaml"," entry. Renaming a Frond, or importing one from outside a Nuxt app,\nis where a Frond's ",[203,413,406],{}," earns its keep: see\n",[291,416,418],{"href":417},"\u002Fdocs\u002Fconcepts\u002Ffrond#naming-and-importing-a-frond","Frond — naming and importing",[267,420,421,424,425,428,429,432,433,436],{},[203,422,423],{},"fougere new"," writes the same directories one level out — the app under ",[203,426,427],{},"apps\u002F\u003Cname>\u002F",", the\nFronds shared at the workspace root, ",[203,430,431],{},"fougere: { root: '..\u002F..' }"," in ",[203,434,435],{},"nuxt.config.ts"," — so\nthat several apps consume the same domains. One app, one directory: the shape above.",[438,439,441,442,444],"h3",{"id":440},"one-domain-no-fronds-at-all","One domain, no ",[203,443,305],{}," at all",[267,446,447,448,450],{},"The project root can use the same convention as a directory under ",[203,449,305],{},". A\nsingle-domain app can therefore place its entities and handlers directly at the root:",[196,452,455],{"className":453,"code":454,"language":312},[310],"my-shop\u002F\n  fougere.config.ts\n  nuxt.config.ts\n  entities\u002FProduct.ts       ← the root IS the Frond, named after the directory\n  handlers\u002FProductHandler.ts\n  app\u002Fpages\u002F\n",[203,456,454],{"__ignoreMap":201},[267,458,459,462,463,466,467,469,470,472,473,475],{},[203,460,461],{},"fougere new my-shop --flat --frond blog"," writes exactly that. ",[203,464,465],{},"import Product from '@fronds\u002Fmy-shop\u002Fentities\u002FProduct'"," — same alias rule, no ",[203,468,305],{}," segment, and the word\nnever comes up until there are two domains to tell apart. The root needs at least an\n",[203,471,323],{}," to count; a lone ",[203,474,341],{}," is an ordinary directory name.",[267,477,478,479,399,482,485,486,488],{},"When the second domain arrives it goes to ",[203,480,481],{},"fronds\u002Fbilling\u002F",[270,483,484],{},"the root Frond stays\nwhere it is"," — nothing moves, no import is rewritten. ",[203,487,305],{}," is not what defines a\nFrond, it is where the others live.",[296,490,492],{"id":491},"fougereconfigts-reference","fougere.config.ts — reference",[196,494,496],{"className":355,"code":495,"language":357,"meta":201,"style":201},"import { defineFougere } from '@fougere\u002Fcore';\nimport { betterAuth } from '@fougere\u002Fauth-better';\nimport User from '.\u002Ffronds\u002Fuser\u002Fentities\u002FUser';\n\nexport default defineFougere({\n  \u002F\u002F Persistence. Three forms:\n  \u002F\u002F   'sqlite'                          → in-memory on the Nuxt side (reseeded each reload)\n  \u002F\u002F   { dialect: 'sqlite', path: '…' }  → file-backed (survives reloads and deploys)\n  \u002F\u002F   false                             → no db\n  db: { dialect: 'sqlite', path: '.data\u002Fapp.db' },\n\n  \u002F\u002F Where rows live, when they do not all live in `db`. An entity this does not\n  \u002F\u002F name stays in the default source, so one database declares nothing at all.\n  \u002F\u002F sources: { archive: { path: '\u002Fmnt\u002Flegacy\u002Fcatalog.db', entities: ['Book'] } },\n\n  \u002F\u002F Topology. A Frond listed here is STILL scanned (its entities keep feeding\n  \u002F\u002F metadata to forms and validation) but is not hosted locally: calls travel\n  \u002F\u002F as JSON-RPC to the process that hosts it. Comment the line → in-process.\n  \u002F\u002F remotes: { blog: 'http:\u002F\u002F127.0.0.1:4100' },\n\n  \u002F\u002F Auth (optional) — better-auth behind a thin translation layer.\n  auth: betterAuth({\n    user: User,                             \u002F\u002F your entity extending AuthUser\n    secret: process.env.AUTH_SECRET!,       \u002F\u002F 32+ chars\n    baseUrl: process.env.SITE_URL ?? 'http:\u002F\u002Flocalhost:3000',\n    basePath: '\u002Fauth',                      \u002F\u002F mounts \u002Fauth\u002F** (sign-in, sign-up, sign-out…)\n    trustedOrigins: ['http:\u002F\u002Flocalhost:3000'],\n    sessionTtl: 30 * 24 * 60 * 60 * 1000,\n    providers: {\n      credential: { minPasswordLength: 8, autoSignIn: true },\n      \u002F\u002F google: { clientId: …, clientSecret: … },\n    },\n  }),\n});\n",[203,497,498,523,545,564,571,589,596,602,608,614,656,661,667,673,679,684,690,696,702,708,713,719,733,749,780,811,831,853,887,898,929,935,941,952],{"__ignoreMap":201},[206,499,500,502,505,508,511,514,516,519,521],{"class":208,"line":209},[206,501,365],{"class":364},[206,503,504],{"class":248}," {",[206,506,507],{"class":368}," defineFougere",[206,509,510],{"class":248}," }",[206,512,513],{"class":364}," from",[206,515,376],{"class":375},[206,517,518],{"class":216},"@fougere\u002Fcore",[206,520,382],{"class":375},[206,522,385],{"class":248},[206,524,525,527,529,532,534,536,538,541,543],{"class":208,"line":239},[206,526,365],{"class":364},[206,528,504],{"class":248},[206,530,531],{"class":368}," betterAuth",[206,533,510],{"class":248},[206,535,513],{"class":364},[206,537,376],{"class":375},[206,539,540],{"class":216},"@fougere\u002Fauth-better",[206,542,382],{"class":375},[206,544,385],{"class":248},[206,546,548,550,553,555,557,560,562],{"class":208,"line":547},3,[206,549,365],{"class":364},[206,551,552],{"class":368}," User ",[206,554,372],{"class":364},[206,556,376],{"class":375},[206,558,559],{"class":216},".\u002Ffronds\u002Fuser\u002Fentities\u002FUser",[206,561,382],{"class":375},[206,563,385],{"class":248},[206,565,567],{"class":208,"line":566},4,[206,568,570],{"emptyLinePlaceholder":569},true,"\n",[206,572,574,577,580,583,586],{"class":208,"line":573},5,[206,575,576],{"class":364},"export",[206,578,579],{"class":364}," default",[206,581,507],{"class":582},"sGLFI",[206,584,585],{"class":368},"(",[206,587,588],{"class":248},"{\n",[206,590,592],{"class":208,"line":591},6,[206,593,595],{"class":594},"sutJx","  \u002F\u002F Persistence. Three forms:\n",[206,597,599],{"class":208,"line":598},7,[206,600,601],{"class":594},"  \u002F\u002F   'sqlite'                          → in-memory on the Nuxt side (reseeded each reload)\n",[206,603,605],{"class":208,"line":604},8,[206,606,607],{"class":594},"  \u002F\u002F   { dialect: 'sqlite', path: '…' }  → file-backed (survives reloads and deploys)\n",[206,609,611],{"class":208,"line":610},9,[206,612,613],{"class":594},"  \u002F\u002F   false                             → no db\n",[206,615,617,621,624,626,629,631,633,636,638,641,644,646,648,651,653],{"class":208,"line":616},10,[206,618,620],{"class":619},"skxfh","  db",[206,622,623],{"class":248},":",[206,625,504],{"class":248},[206,627,628],{"class":619}," dialect",[206,630,623],{"class":248},[206,632,376],{"class":375},[206,634,635],{"class":216},"sqlite",[206,637,382],{"class":375},[206,639,640],{"class":248},",",[206,642,643],{"class":619}," path",[206,645,623],{"class":248},[206,647,376],{"class":375},[206,649,650],{"class":216},".data\u002Fapp.db",[206,652,382],{"class":375},[206,654,655],{"class":248}," },\n",[206,657,659],{"class":208,"line":658},11,[206,660,570],{"emptyLinePlaceholder":569},[206,662,664],{"class":208,"line":663},12,[206,665,666],{"class":594},"  \u002F\u002F Where rows live, when they do not all live in `db`. An entity this does not\n",[206,668,670],{"class":208,"line":669},13,[206,671,672],{"class":594},"  \u002F\u002F name stays in the default source, so one database declares nothing at all.\n",[206,674,676],{"class":208,"line":675},14,[206,677,678],{"class":594},"  \u002F\u002F sources: { archive: { path: '\u002Fmnt\u002Flegacy\u002Fcatalog.db', entities: ['Book'] } },\n",[206,680,682],{"class":208,"line":681},15,[206,683,570],{"emptyLinePlaceholder":569},[206,685,687],{"class":208,"line":686},16,[206,688,689],{"class":594},"  \u002F\u002F Topology. A Frond listed here is STILL scanned (its entities keep feeding\n",[206,691,693],{"class":208,"line":692},17,[206,694,695],{"class":594},"  \u002F\u002F metadata to forms and validation) but is not hosted locally: calls travel\n",[206,697,699],{"class":208,"line":698},18,[206,700,701],{"class":594},"  \u002F\u002F as JSON-RPC to the process that hosts it. Comment the line → in-process.\n",[206,703,705],{"class":208,"line":704},19,[206,706,707],{"class":594},"  \u002F\u002F remotes: { blog: 'http:\u002F\u002F127.0.0.1:4100' },\n",[206,709,711],{"class":208,"line":710},20,[206,712,570],{"emptyLinePlaceholder":569},[206,714,716],{"class":208,"line":715},21,[206,717,718],{"class":594},"  \u002F\u002F Auth (optional) — better-auth behind a thin translation layer.\n",[206,720,722,725,727,729,731],{"class":208,"line":721},22,[206,723,724],{"class":619},"  auth",[206,726,623],{"class":248},[206,728,531],{"class":582},[206,730,585],{"class":368},[206,732,588],{"class":248},[206,734,736,739,741,744,746],{"class":208,"line":735},23,[206,737,738],{"class":619},"    user",[206,740,623],{"class":248},[206,742,743],{"class":368}," User",[206,745,640],{"class":248},[206,747,748],{"class":594},"                             \u002F\u002F your entity extending AuthUser\n",[206,750,752,755,757,760,762,765,767,771,775,777],{"class":208,"line":751},24,[206,753,754],{"class":619},"    secret",[206,756,623],{"class":248},[206,758,759],{"class":368}," process",[206,761,294],{"class":248},[206,763,764],{"class":368},"env",[206,766,294],{"class":248},[206,768,770],{"class":769},"s_hVV","AUTH_SECRET",[206,772,774],{"class":773},"smGrS","!",[206,776,640],{"class":248},[206,778,779],{"class":594},"       \u002F\u002F 32+ chars\n",[206,781,783,786,788,790,792,794,796,799,802,804,807,809],{"class":208,"line":782},25,[206,784,785],{"class":619},"    baseUrl",[206,787,623],{"class":248},[206,789,759],{"class":368},[206,791,294],{"class":248},[206,793,764],{"class":368},[206,795,294],{"class":248},[206,797,798],{"class":769},"SITE_URL",[206,800,801],{"class":773}," ??",[206,803,376],{"class":375},[206,805,806],{"class":216},"http:\u002F\u002Flocalhost:3000",[206,808,382],{"class":375},[206,810,324],{"class":248},[206,812,814,817,819,821,824,826,828],{"class":208,"line":813},26,[206,815,816],{"class":619},"    basePath",[206,818,623],{"class":248},[206,820,376],{"class":375},[206,822,823],{"class":216},"\u002Fauth",[206,825,382],{"class":375},[206,827,640],{"class":248},[206,829,830],{"class":594},"                      \u002F\u002F mounts \u002Fauth\u002F** (sign-in, sign-up, sign-out…)\n",[206,832,834,837,839,842,844,846,848,851],{"class":208,"line":833},27,[206,835,836],{"class":619},"    trustedOrigins",[206,838,623],{"class":248},[206,840,841],{"class":368}," [",[206,843,382],{"class":375},[206,845,806],{"class":216},[206,847,382],{"class":375},[206,849,850],{"class":368},"]",[206,852,324],{"class":248},[206,854,856,859,861,865,868,871,873,876,878,880,882,885],{"class":208,"line":855},28,[206,857,858],{"class":619},"    sessionTtl",[206,860,623],{"class":248},[206,862,864],{"class":863},"srdBf"," 30",[206,866,867],{"class":773}," *",[206,869,870],{"class":863}," 24",[206,872,867],{"class":773},[206,874,875],{"class":863}," 60",[206,877,867],{"class":773},[206,879,875],{"class":863},[206,881,867],{"class":773},[206,883,884],{"class":863}," 1000",[206,886,324],{"class":248},[206,888,890,893,895],{"class":208,"line":889},29,[206,891,892],{"class":619},"    providers",[206,894,623],{"class":248},[206,896,897],{"class":248}," {\n",[206,899,901,904,906,908,911,913,916,918,921,923,927],{"class":208,"line":900},30,[206,902,903],{"class":619},"      credential",[206,905,623],{"class":248},[206,907,504],{"class":248},[206,909,910],{"class":619}," minPasswordLength",[206,912,623],{"class":248},[206,914,915],{"class":863}," 8",[206,917,640],{"class":248},[206,919,920],{"class":619}," autoSignIn",[206,922,623],{"class":248},[206,924,926],{"class":925},"syTEX"," true",[206,928,655],{"class":248},[206,930,932],{"class":208,"line":931},31,[206,933,934],{"class":594},"      \u002F\u002F google: { clientId: …, clientSecret: … },\n",[206,936,938],{"class":208,"line":937},32,[206,939,940],{"class":248},"    },\n",[206,942,944,947,950],{"class":208,"line":943},33,[206,945,946],{"class":248},"  }",[206,948,949],{"class":368},")",[206,951,324],{"class":248},[206,953,955,958,960],{"class":208,"line":954},34,[206,956,957],{"class":248},"}",[206,959,949],{"class":368},[206,961,385],{"class":248},[267,963,964],{},"Tables are derived from your entities. At boot, SQLite auto-DDL creates missing tables and\nadds missing columns. Renames, removals and type changes require an explicit migration.\nSeeds run after that schema sync and call operations with their usual validation.",[267,966,967,968,971,972,975,976,294],{},"An app with several databases declares them under ",[203,969,970],{},"sources:",", and a Frond that must query\nacross them declares ",[203,973,974],{},"reads:"," — see ",[291,977,167],{"href":168},[296,979,981],{"id":980},"run","Run",[196,983,985],{"className":198,"code":984,"language":200,"meta":201,"style":201},"pnpm install\npnpm dev          # scan → sync additive schema → seed → serve on :3000\n",[203,986,987,995],{"__ignoreMap":201},[206,988,989,992],{"class":208,"line":209},[206,990,991],{"class":212},"pnpm",[206,993,994],{"class":216}," install\n",[206,996,997,999,1002],{"class":208,"line":239},[206,998,991],{"class":212},[206,1000,1001],{"class":216}," dev",[206,1003,1004],{"class":594},"          # scan → sync additive schema → seed → serve on :3000\n",[267,1006,1007],{},"Check the boot log for the number of discovered Fronds:",[196,1009,1012],{"className":1010,"code":1011,"language":312},[310],"INF [boot:app] scanned 2 frond(s) in 467ms\nINF [boot] ready in 483ms — 2 frond(s) + auth (\u002Fauth)\n",[203,1013,1011],{"__ignoreMap":201},[267,1015,1016,1017,1019],{},"Next: ",[291,1018,56],{"href":57}," — the field vocabulary and the four axes.",[1021,1022,1023],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":201,"searchDepth":239,"depth":239,"links":1025},[1026,1030,1031],{"id":298,"depth":239,"text":299,"children":1027},[1028],{"id":440,"depth":547,"text":1029},"One domain, no fronds\u002F at all",{"id":491,"depth":239,"text":492},{"id":980,"depth":239,"text":981},"The structure of a Fougere app and the fougere.config.ts reference.","md",{},{"title":13,"description":1032},"iT8s5TKb9DXlvUwNo3U-pZm7n_TeTgTQ0GrS6pYeq00",1788560229821]