[{"data":1,"prerenderedAt":687},["ShallowReactive",2],{"docs:\u002Fdocs":3,"docs-nav:en":601},{"id":4,"title":5,"body":6,"description":594,"extension":595,"meta":596,"navigation":121,"path":597,"seo":598,"stem":599,"__hash__":600},"docs_en\u002Fdocs\u002Findex.md","What is Fougere",{"type":7,"value":8,"toc":591},"minimark",[9,13,17,34,336,339,342,398,412,447,454,457,462,478,532,553,570,587],[10,11,5],"h1",{"id":12},"what-is-fougere",[14,15,16],"p",{},"Fougere is a TypeScript framework built around two ideas.",[14,18,19,23,24,28,29,33],{},[20,21,22],"strong",{},"Single-schema."," One entity class declares your data once — and judges its own input:\nthe same ",[25,26,27],"code",{},"validate()"," runs in the browser and at the façade. That judge is itself a\nprojection, derived from the shape axis, but a normative one shipped with the class:\nevery other projection must agree with it, and it cannot drift on its own. SQLite tables,\nGraphQL types, form contracts and API surfaces are ",[30,31,32],"em",{},"projections"," of that declaration —\nnothing is written twice.",[35,36,41],"pre",{"className":37,"code":38,"language":39,"meta":40,"style":40},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { entity, primary, text, created, oneOf, date, readOnly, optional } from '@fougere\u002Fschema';\n\nexport default class Post extends entity({\n  id: primary(),\n  title: text({ min: 1, max: 160 }),\n  body: optional(text()),\n  createdAt: created(),\n  status: readOnly(oneOf('draft', 'published', { default: 'draft' })),\n  publishedAt: readOnly(optional(date())),\n}) {}\n","ts","",[25,42,43,116,123,152,170,211,231,245,299,324],{"__ignoreMap":40},[44,45,48,52,56,60,63,66,68,71,73,76,78,81,83,86,88,91,93,96,99,102,106,110,113],"span",{"class":46,"line":47},"line",1,[44,49,51],{"class":50},"sVHd0","import",[44,53,55],{"class":54},"sP7_E"," {",[44,57,59],{"class":58},"su5hD"," entity",[44,61,62],{"class":54},",",[44,64,65],{"class":58}," primary",[44,67,62],{"class":54},[44,69,70],{"class":58}," text",[44,72,62],{"class":54},[44,74,75],{"class":58}," created",[44,77,62],{"class":54},[44,79,80],{"class":58}," oneOf",[44,82,62],{"class":54},[44,84,85],{"class":58}," date",[44,87,62],{"class":54},[44,89,90],{"class":58}," readOnly",[44,92,62],{"class":54},[44,94,95],{"class":58}," optional",[44,97,98],{"class":54}," }",[44,100,101],{"class":50}," from",[44,103,105],{"class":104},"sjJ54"," '",[44,107,109],{"class":108},"s_sjI","@fougere\u002Fschema",[44,111,112],{"class":104},"'",[44,114,115],{"class":54},";\n",[44,117,119],{"class":46,"line":118},2,[44,120,122],{"emptyLinePlaceholder":121},true,"\n",[44,124,126,129,132,136,140,143,146,149],{"class":46,"line":125},3,[44,127,128],{"class":50},"export",[44,130,131],{"class":50}," default",[44,133,135],{"class":134},"sbsja"," class",[44,137,139],{"class":138},"sbgvK"," Post",[44,141,142],{"class":134}," extends",[44,144,59],{"class":145},"sGLFI",[44,147,148],{"class":58},"(",[44,150,151],{"class":54},"{\n",[44,153,155,159,162,164,167],{"class":46,"line":154},4,[44,156,158],{"class":157},"skxfh","  id",[44,160,161],{"class":54},":",[44,163,65],{"class":145},[44,165,166],{"class":58},"()",[44,168,169],{"class":54},",\n",[44,171,173,176,178,180,182,185,188,190,194,196,199,201,204,206,209],{"class":46,"line":172},5,[44,174,175],{"class":157},"  title",[44,177,161],{"class":54},[44,179,70],{"class":145},[44,181,148],{"class":58},[44,183,184],{"class":54},"{",[44,186,187],{"class":157}," min",[44,189,161],{"class":54},[44,191,193],{"class":192},"srdBf"," 1",[44,195,62],{"class":54},[44,197,198],{"class":157}," max",[44,200,161],{"class":54},[44,202,203],{"class":192}," 160",[44,205,98],{"class":54},[44,207,208],{"class":58},")",[44,210,169],{"class":54},[44,212,214,217,219,221,223,226,229],{"class":46,"line":213},6,[44,215,216],{"class":157},"  body",[44,218,161],{"class":54},[44,220,95],{"class":145},[44,222,148],{"class":58},[44,224,225],{"class":145},"text",[44,227,228],{"class":58},"())",[44,230,169],{"class":54},[44,232,234,237,239,241,243],{"class":46,"line":233},7,[44,235,236],{"class":157},"  createdAt",[44,238,161],{"class":54},[44,240,75],{"class":145},[44,242,166],{"class":58},[44,244,169],{"class":54},[44,246,248,251,253,255,257,260,262,264,267,269,271,273,276,278,280,282,284,286,288,290,292,294,297],{"class":46,"line":247},8,[44,249,250],{"class":157},"  status",[44,252,161],{"class":54},[44,254,90],{"class":145},[44,256,148],{"class":58},[44,258,259],{"class":145},"oneOf",[44,261,148],{"class":58},[44,263,112],{"class":104},[44,265,266],{"class":108},"draft",[44,268,112],{"class":104},[44,270,62],{"class":54},[44,272,105],{"class":104},[44,274,275],{"class":108},"published",[44,277,112],{"class":104},[44,279,62],{"class":54},[44,281,55],{"class":54},[44,283,131],{"class":157},[44,285,161],{"class":54},[44,287,105],{"class":104},[44,289,266],{"class":108},[44,291,112],{"class":104},[44,293,98],{"class":54},[44,295,296],{"class":58},"))",[44,298,169],{"class":54},[44,300,302,305,307,309,311,314,316,319,322],{"class":46,"line":301},9,[44,303,304],{"class":157},"  publishedAt",[44,306,161],{"class":54},[44,308,90],{"class":145},[44,310,148],{"class":58},[44,312,313],{"class":145},"optional",[44,315,148],{"class":58},[44,317,318],{"class":145},"date",[44,320,321],{"class":58},"()))",[44,323,169],{"class":54},[44,325,327,330,333],{"class":46,"line":326},10,[44,328,329],{"class":54},"}",[44,331,332],{"class":58},") ",[44,334,335],{"class":54},"{}\n",[337,338],"derivation-diagram",{},[14,340,341],{},"That single class is simultaneously:",[343,344,345,361,370,379,388],"ul",{},[346,347,348,349,352,353,356,357,360],"li",{},"the ",[20,350,351],{},"TypeScript type"," of a row (",[25,354,355],{},"function render(p: Post)"," — no ",[25,358,359],{},"Infer\u003Ctypeof …>","),",[346,362,348,363,366,367,360],{},[20,364,365],{},"validator"," of client input (",[25,368,369],{},"Post.validate(input)",[346,371,348,372,375,376,360],{},[20,373,374],{},"metadata"," every adapter reads (",[25,377,378],{},"Post.getFields()",[346,380,348,381,384,385,360],{},[20,382,383],{},"designation"," pages use to call operations (",[25,386,387],{},"useQuery(Post, 'list')",[346,389,348,390,393,394,397],{},[20,391,392],{},"nominal name"," dependency injection matches in handler signatures (",[25,395,396],{},"user: User | null",").",[14,399,400,403,404,407,408,411],{},[20,401,402],{},"The gradient."," Business logic lives in ",[30,405,406],{},"Fronds"," — self-contained modules of entities,\nhandlers, collectors and seeds. A Frond runs in-process today and in its own process\ntomorrow, behind JSON-RPC 2.0, with ",[20,409,410],{},"identical user code",". The entire topology statement\nis one line of config:",[35,413,415],{"className":37,"code":414,"language":39,"meta":40,"style":40},"\u002F\u002F fougere.config.ts\nremotes: { blog: 'http:\u002F\u002F127.0.0.1:4100' }\n",[25,416,417,423],{"__ignoreMap":40},[44,418,419],{"class":46,"line":47},[44,420,422],{"class":421},"sutJx","\u002F\u002F fougere.config.ts\n",[44,424,425,428,430,432,435,437,439,442,444],{"class":46,"line":118},[44,426,427],{"class":138},"remotes",[44,429,161],{"class":54},[44,431,55],{"class":54},[44,433,434],{"class":138}," blog",[44,436,161],{"class":54},[44,438,105],{"class":104},[44,440,441],{"class":108},"http:\u002F\u002F127.0.0.1:4100",[44,443,112],{"class":104},[44,445,446],{"class":54}," }\n",[14,448,449,450,453],{},"There is no RPC without travel: a call is a value ",[25,451,452],{},"(entity, operation, invocation)","; the\nrunner executes it directly in memory when the Frond is local and frames it onto the wire\nwhen it is remote. Transports move the value — they never reshape it.",[14,455,456],{},"So the split costs the hop and the JSON that rides it, and nothing else: no serialization\nthe local path avoids, no framework tax layered on top of the network.",[458,459,461],"h2",{"id":460},"reading-order","Reading order",[14,463,464,467,468,473,474],{},[20,465,466],{},"Concepts"," — ",[469,470,472],"a",{"href":471},"\u002Fdocs\u002Fconcepts\u002Fphilosophy","Philosophy"," · ",[469,475,477],{"href":476},"\u002Fdocs\u002Fconcepts\u002Ffrond","The Frond",[14,479,480,467,483,473,487,491,492,491,496,473,500,491,504,473,508,491,512,473,516,473,520,473,524,491,528],{},[20,481,482],{},"Server side",[469,484,486],{"href":485},"\u002Fdocs\u002Fgetting-started","Getting started",[469,488,490],{"href":489},"\u002Fdocs\u002Fexisting-app","Existing Nuxt app"," ·\n",[469,493,495],{"href":494},"\u002Fdocs\u002Fcli","The CLI",[469,497,499],{"href":498},"\u002Fdocs\u002Fschema\u002Fentities","Entities",[469,501,503],{"href":502},"\u002Fdocs\u002Fschema\u002Fviews","Views",[469,505,507],{"href":506},"\u002Fdocs\u002Fschema\u002Fstandard-schema","Standard Schema",[469,509,511],{"href":510},"\u002Fdocs\u002Fbusiness\u002Fhandlers","Handlers",[469,513,515],{"href":514},"\u002Fdocs\u002Fbusiness\u002Fpresenters","Presenters",[469,517,519],{"href":518},"\u002Fdocs\u002Fbusiness\u002Fcollectors","Collectors",[469,521,523],{"href":522},"\u002Fdocs\u002Fbusiness\u002Ferrors","Errors",[469,525,527],{"href":526},"\u002Fdocs\u002Fbusiness\u002Fseeds","Seeds",[469,529,531],{"href":530},"\u002Fdocs\u002Fbusiness\u002Ffacts","Facts",[14,533,534,467,537,491,541,473,545,473,549],{},[20,535,536],{},"Client side",[469,538,540],{"href":539},"\u002Fdocs\u002Fclient\u002Fqueries-commands","Queries & commands",[469,542,544],{"href":543},"\u002Fdocs\u002Fclient\u002Fforms","Forms",[469,546,548],{"href":547},"\u002Fdocs\u002Fclient\u002Fsession","Session",[469,550,552],{"href":551},"\u002Fdocs\u002Fclient\u002Finvoke","invoke",[14,554,555,467,558,473,562,491,566],{},[20,556,557],{},"Topology",[469,559,561],{"href":560},"\u002Fdocs\u002Finfra\u002Fgradient","The gradient",[469,563,565],{"href":564},"\u002Fdocs\u002Finfra\u002Fsurfaces","Surfaces",[469,567,569],{"href":568},"\u002Fdocs\u002Finfra\u002Fdeployment","Deployment",[571,572,573],"blockquote",{},[14,574,575,578,579,582,583,586],{},[20,576,577],{},"Status."," Fougere is in alpha: the ",[25,580,581],{},"@fougere\u002F*"," packages are on npm under the ",[25,584,585],{},"alpha","\ntag, and this documentation describes the API as it exists in the repository today.\nThis site runs on it.",[588,589,590],"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 .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .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}",{"title":40,"searchDepth":118,"depth":118,"links":592},[593],{"id":460,"depth":118,"text":461},"A TypeScript framework built around two ideas — single-schema and the gradient.","md",{},"\u002Fdocs",{"title":5,"description":594},"docs\u002Findex","Vxz9ZNVtfO48bqD6A4oozPJEzFeBuhObHyIX7849zRw",[602],{"title":603,"path":597,"stem":604,"children":605,"page":-1},"Docs","docs",[606,607,609,611,613,626,641,658,671],{"title":5,"path":597,"stem":599},{"title":486,"path":485,"stem":608},"docs\u002F01.getting-started",{"title":490,"path":489,"stem":610},"docs\u002F02.existing-app",{"title":495,"path":494,"stem":612},"docs\u002F03.cli",{"title":466,"path":614,"stem":615,"children":616,"page":625},"\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[617,619,621],{"title":472,"path":471,"stem":618},"docs\u002F2.concepts\u002F1.philosophy",{"title":477,"path":476,"stem":620},"docs\u002F2.concepts\u002F2.frond",{"title":622,"path":623,"stem":624},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",false,{"title":627,"path":628,"stem":629,"children":630,"page":625},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[631,633,635,639],{"title":499,"path":498,"stem":632},"docs\u002F3.schema\u002F1.entities",{"title":503,"path":502,"stem":634},"docs\u002F3.schema\u002F2.views",{"title":636,"path":637,"stem":638},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":507,"path":506,"stem":640},"docs\u002F3.schema\u002F4.standard-schema",{"title":642,"path":643,"stem":644,"children":645,"page":625},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[646,648,650,652,654,656],{"title":511,"path":510,"stem":647},"docs\u002F4.business\u002F1.handlers",{"title":515,"path":514,"stem":649},"docs\u002F4.business\u002F2.presenters",{"title":519,"path":518,"stem":651},"docs\u002F4.business\u002F3.collectors",{"title":523,"path":522,"stem":653},"docs\u002F4.business\u002F4.errors",{"title":527,"path":526,"stem":655},"docs\u002F4.business\u002F5.seeds",{"title":531,"path":530,"stem":657},"docs\u002F4.business\u002F6.facts",{"title":659,"path":660,"stem":661,"children":662,"page":625},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[663,665,667,669],{"title":540,"path":539,"stem":664},"docs\u002F5.client\u002F1.queries-commands",{"title":544,"path":543,"stem":666},"docs\u002F5.client\u002F2.forms",{"title":548,"path":547,"stem":668},"docs\u002F5.client\u002F3.session",{"title":552,"path":551,"stem":670},"docs\u002F5.client\u002F4.invoke",{"title":672,"path":673,"stem":674,"children":675,"page":625},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[676,678,681,683],{"title":561,"path":560,"stem":677},"docs\u002F6.infra\u002F1.gradient",{"title":679,"path":564,"stem":680},"Surfaces — REST & GraphQL","docs\u002F6.infra\u002F2.surfaces",{"title":569,"path":568,"stem":682},"docs\u002F6.infra\u002F3.deployment",{"title":684,"path":685,"stem":686},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",1786637818908]