[{"data":1,"prerenderedAt":1344},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fcli":134},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,24,42,63,92,113],{"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},"Existing Nuxt app","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"The CLI","\u002Fdocs\u002Fcli","docs\u002F03.cli",{"title":25,"path":26,"stem":27,"children":28,"page":41},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[29,33,37],{"title":30,"path":31,"stem":32},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":34,"path":35,"stem":36},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":38,"path":39,"stem":40},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",false,{"title":43,"path":44,"stem":45,"children":46,"page":41},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[47,51,55,59],{"title":48,"path":49,"stem":50},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":52,"path":53,"stem":54},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":56,"path":57,"stem":58},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":60,"path":61,"stem":62},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":64,"path":65,"stem":66,"children":67,"page":41},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[68,72,76,80,84,88],{"title":69,"path":70,"stem":71},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":73,"path":74,"stem":75},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":77,"path":78,"stem":79},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":81,"path":82,"stem":83},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":85,"path":86,"stem":87},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":89,"path":90,"stem":91},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":93,"path":94,"stem":95,"children":96,"page":41},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[97,101,105,109],{"title":98,"path":99,"stem":100},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":102,"path":103,"stem":104},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":106,"path":107,"stem":108},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":110,"path":111,"stem":112},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":114,"path":115,"stem":116,"children":117,"page":41},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[118,122,126,130],{"title":119,"path":120,"stem":121},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":123,"path":124,"stem":125},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":127,"path":128,"stem":129},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":131,"path":132,"stem":133},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"id":135,"title":21,"body":136,"description":1339,"extension":1340,"meta":1341,"navigation":471,"path":22,"seo":1342,"stem":23,"__hash__":1343},"docs_en\u002Fdocs\u002F03.cli.md",{"type":137,"value":138,"toc":1323},"minimark",[139,143,151,177,185,223,226,234,326,340,391,402,600,603,610,631,645,658,674,681,728,735,742,762,773,882,892,903,1012,1023,1042,1049,1056,1115,1126,1157,1162,1212,1226,1238,1245,1257,1260,1266,1273,1280,1295,1314,1319],[140,141,21],"h1",{"id":142},"the-cli",[144,145,146,150],"p",{},[147,148,149],"code",{},"@fougere\u002Fcli"," creates a workspace, hosts a Frond in a separate process, and invokes an\noperation from a shell. The CLI itself uses entities and handlers, so its options are\nvalidated from their schemas.",[152,153,154],"blockquote",{},[144,155,156,160,161,164,165,168,169,172,173,176],{},[157,158,159],"strong",{},"Alpha."," On npm under the ",[147,162,163],{},"alpha"," tag — ",[147,166,167],{},"npx fougere@alpha"," runs it without\ninstalling, ",[147,170,171],{},"npm create fougere"," enters it at ",[147,174,175],{},"new",". The commands and flags below are\nwhat ships.",[178,179,181,184],"h2",{"id":180},"fougere-new-compose-a-workspace",[147,182,183],{},"fougere new"," — compose a workspace",[186,187,192],"pre",{"className":188,"code":189,"language":190,"meta":191,"style":191},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","fougere new shop --frond blog --app nuxt\n","bash","",[147,193,194],{"__ignoreMap":191},[195,196,199,203,207,210,214,217,220],"span",{"class":197,"line":198},"line",1,[195,200,202],{"class":201},"sbgvK","fougere",[195,204,206],{"class":205},"s_sjI"," new",[195,208,209],{"class":205}," shop",[195,211,213],{"class":212},"stzsN"," --frond",[195,215,216],{"class":205}," blog",[195,218,219],{"class":212}," --app",[195,221,222],{"class":205}," nuxt\n",[144,224,225],{},"The command creates Fronds first, followed by the apps that consume them. It produces a\npnpm workspace:",[186,227,232],{"className":228,"code":230,"language":231},[229],"language-text","shop\u002F\n  fougere.config.ts          ← db, auth, topology\n  pnpm-workspace.yaml        ← packages: [fronds\u002F*, apps\u002F*]\n  fronds\u002Fblog\u002F               ← the domain\n    entities\u002FPost.ts\n    handlers\u002FPostHandler.ts\n  apps\u002Fnuxt\u002F                 ← the consumer\n    nuxt.config.ts\n    app\u002Fpages\u002Findex.vue\n","text",[147,233,230],{"__ignoreMap":191},[235,236,237,250],"table",{},[238,239,240],"thead",{},[241,242,243,247],"tr",{},[244,245,246],"th",{},"Flag",[244,248,249],{},"What it does",[251,252,253,268,278,288,302,316],"tbody",{},[241,254,255,261],{},[256,257,258],"td",{},[147,259,260],{},"--frond blog,api:catalog",[256,262,263,264,267],{},"Fronds to add — ",[147,265,266],{},"template:name"," renames; the template name is the default name",[241,269,270,275],{},[256,271,272],{},[147,273,274],{},"--app nuxt:web",[256,276,277],{},"same, for apps",[241,279,280,285],{},[256,281,282],{},[147,283,284],{},"--bare",[256,286,287],{},"the empty shell, nothing composed",[241,289,290,295],{},[256,291,292],{},[147,293,294],{},"--flat",[256,296,297,298,301],{},"one domain: no ",[147,299,300],{},"fronds\u002F",", no workspace — the app root is the Frond",[241,303,304,309],{},[256,305,306],{},[147,307,308],{},"--local",[256,310,311,312,315],{},"link ",[147,313,314],{},"@fougere\u002F*"," to a local Fougere checkout (development)",[241,317,318,323],{},[256,319,320],{},[147,321,322],{},"--force",[256,324,325],{},"overwrite an existing directory",[144,327,328,331,332,335,336,339],{},[157,329,330],{},"Arguments or interactive mode."," With ",[147,333,334],{},"--frond"," and ",[147,337,338],{},"--app",", the command asks no\nquestions and can run in a script or CI job. Without these options, it prompts for\ntemplates in a TTY. Interactive mode is not available without a TTY.",[144,341,342,345,346,349,350,352,353,356,357,360,361,366,367,369,370,374,375,378,379,382,383,386,387,390],{},[157,343,344],{},"Flat structure."," ",[147,347,348],{},"fougere new shop --flat --frond blog","\nwrites one Nuxt app whose root carries the domain — no ",[147,351,300],{}," segment, no\n",[147,354,355],{},"pnpm-workspace.yaml",", one ",[147,358,359],{},"pnpm install"," (",[362,363,365],"a",{"href":364},"\u002Fdocs\u002Fgetting-started#one-domain-no-fronds-at-all","the flat\nshape","). ",[147,368,338],{}," is refused with it:\nthe app ",[371,372,373],"em",{},"is"," the root. A second domain later goes to ",[147,376,377],{},"fronds\u002Fbilling\u002F"," and the root Frond\nstays where it is. The generated project also carries a ",[147,380,381],{},"tsconfig.frond.json"," whose\n",[147,384,385],{},"include"," names the convention directories. ",[147,388,389],{},"pnpm typecheck"," can therefore check the\ndomain without loading Nuxt.",[144,392,393,394,397,398,401],{},"The generated Frond contains an entity, two derived views (",[147,395,396],{},"NewPost"," for input and\n",[147,399,400],{},"PostCard"," for list output), and a business operation in addition to CRUD:",[186,403,407],{"className":404,"code":405,"language":406,"meta":191,"style":191},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","export class NewPost extends Post.pick('title', 'body') {}\n\nexport default class PostHandler extends Crud(Post) {\n  async create(input: NewPost): Promise\u003CPost> { … }\n\n  \u002F** The draft→published transition — an operation, not a field write. *\u002F\n  async publish(id: string): Promise\u003CPost> { … }\n}\n","ts",[147,408,409,466,473,497,546,551,558,595],{"__ignoreMap":191},[195,410,411,415,419,422,425,429,433,437,440,444,447,449,452,455,458,460,463],{"class":197,"line":198},[195,412,414],{"class":413},"sVHd0","export",[195,416,418],{"class":417},"sbsja"," class",[195,420,421],{"class":201}," NewPost",[195,423,424],{"class":417}," extends",[195,426,428],{"class":427},"su5hD"," Post",[195,430,432],{"class":431},"sP7_E",".",[195,434,436],{"class":435},"sGLFI","pick",[195,438,439],{"class":427},"(",[195,441,443],{"class":442},"sjJ54","'",[195,445,446],{"class":205},"title",[195,448,443],{"class":442},[195,450,451],{"class":431},",",[195,453,454],{"class":442}," '",[195,456,457],{"class":205},"body",[195,459,443],{"class":442},[195,461,462],{"class":427},") ",[195,464,465],{"class":431},"{}\n",[195,467,469],{"class":197,"line":468},2,[195,470,472],{"emptyLinePlaceholder":471},true,"\n",[195,474,476,478,481,483,486,488,491,494],{"class":197,"line":475},3,[195,477,414],{"class":413},[195,479,480],{"class":413}," default",[195,482,418],{"class":417},[195,484,485],{"class":201}," PostHandler",[195,487,424],{"class":417},[195,489,490],{"class":435}," Crud",[195,492,493],{"class":427},"(Post) ",[195,495,496],{"class":431},"{\n",[195,498,500,503,507,509,513,517,519,522,524,527,530,533,536,539,543],{"class":197,"line":499},4,[195,501,502],{"class":417},"  async",[195,504,506],{"class":505},"sVXei"," create",[195,508,439],{"class":431},[195,510,512],{"class":511},"s99_P","input",[195,514,516],{"class":515},"smGrS",":",[195,518,421],{"class":201},[195,520,521],{"class":431},")",[195,523,516],{"class":515},[195,525,526],{"class":201}," Promise",[195,528,529],{"class":431},"\u003C",[195,531,532],{"class":201},"Post",[195,534,535],{"class":431},">",[195,537,538],{"class":431}," {",[195,540,542],{"class":541},"skxfh"," … ",[195,544,545],{"class":431},"}\n",[195,547,549],{"class":197,"line":548},5,[195,550,472],{"emptyLinePlaceholder":471},[195,552,554],{"class":197,"line":553},6,[195,555,557],{"class":556},"sutJx","  \u002F** The draft→published transition — an operation, not a field write. *\u002F\n",[195,559,561,563,566,568,571,573,577,579,581,583,585,587,589,591,593],{"class":197,"line":560},7,[195,562,502],{"class":417},[195,564,565],{"class":505}," publish",[195,567,439],{"class":431},[195,569,570],{"class":511},"id",[195,572,516],{"class":515},[195,574,576],{"class":575},"sZMiF"," string",[195,578,521],{"class":431},[195,580,516],{"class":515},[195,582,526],{"class":201},[195,584,529],{"class":431},[195,586,532],{"class":201},[195,588,535],{"class":431},[195,590,538],{"class":431},[195,592,542],{"class":541},[195,594,545],{"class":431},[195,596,598],{"class":197,"line":597},8,[195,599,545],{"class":431},[144,601,602],{},"The views define the input and output contracts for these operations.",[178,604,606,609],{"id":605},"fougere-serve-one-frond-its-own-process",[147,607,608],{},"fougere serve"," — one Frond, its own process",[186,611,613],{"className":188,"code":612,"language":190,"meta":191,"style":191},"fougere serve blog --port 4100\n",[147,614,615],{"__ignoreMap":191},[195,616,617,619,622,624,627],{"class":197,"line":198},[195,618,202],{"class":201},[195,620,621],{"class":205}," serve",[195,623,216],{"class":205},[195,625,626],{"class":212}," --port",[195,628,630],{"class":629},"srdBf"," 4100\n",[144,632,633,634,637,638,641,642,432],{},"Starts that Frond alone and exposes it over JSON-RPC on ",[147,635,636],{},"POST \u002F_fougere\u002Fcall",". The\nconsuming app sets its address in ",[147,639,640],{},"remotes:"," to route calls to that host. See\n",[362,643,644],{"href":120},"the gradient",[144,646,647,648,651,652,654,655,657],{},"It does ",[157,649,650],{},"not"," follow ",[147,653,640],{}," itself: a host ",[371,656,373],{}," the Frond, it does not route back\nout.",[152,659,660],{},[144,661,662,665,666,669,670,673],{},[147,663,664],{},"serve()"," binds ",[147,667,668],{},"127.0.0.1"," unless ",[147,671,672],{},"hosts"," says otherwise: a receiver reads identity\noff the wire, so the default keeps it on the machine and widening it is a decision\nwritten down.",[178,675,677,680],{"id":676},"fougere-call-invoke-an-operation",[147,678,679],{},"fougere call"," — invoke an operation",[186,682,684],{"className":188,"code":683,"language":190,"meta":191,"style":191},"fougere call post.list\nfougere call post.create --title \"Hello\" --body \"…\"\n",[147,685,686,696],{"__ignoreMap":191},[195,687,688,690,693],{"class":197,"line":198},[195,689,202],{"class":201},[195,691,692],{"class":205}," call",[195,694,695],{"class":205}," post.list\n",[195,697,698,700,702,705,708,711,714,717,720,722,725],{"class":197,"line":468},[195,699,202],{"class":201},[195,701,692],{"class":205},[195,703,704],{"class":205}," post.create",[195,706,707],{"class":212}," --title",[195,709,710],{"class":442}," \"",[195,712,713],{"class":205},"Hello",[195,715,716],{"class":442},"\"",[195,718,719],{"class":212}," --body",[195,721,710],{"class":442},[195,723,724],{"class":205},"…",[195,726,727],{"class":442},"\"\n",[144,729,730,731,734],{},"The command uses the same envelope, validation, and typed errors as other clients. A\n",[147,732,733],{},"VALIDATION_FAILED"," error therefore keeps the format received by a page.",[178,736,738,741],{"id":737},"fougere-sync-consume-a-remote-frond",[147,739,740],{},"fougere sync"," — consume a remote Frond",[186,743,745],{"className":188,"code":744,"language":190,"meta":191,"style":191},"fougere sync blog --from http:\u002F\u002Fblog-service:4100\n",[147,746,747],{"__ignoreMap":191},[195,748,749,751,754,756,759],{"class":197,"line":198},[195,750,202],{"class":201},[195,752,753],{"class":205}," sync",[195,755,216],{"class":205},[195,757,758],{"class":212}," --from",[195,760,761],{"class":205}," http:\u002F\u002Fblog-service:4100\n",[144,763,764,765,768,769,772],{},"Asks the host ",[147,766,767],{},"rpc.discover",", and writes local entity files rebuilt from the\n",[362,770,771],{"href":57},"cards"," it answers with:",[186,774,776],{"className":404,"code":775,"language":406,"meta":191,"style":191},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPost.ts — generated\nimport { reconstruct } from '@fougere\u002Fschema';\n\nexport class Post extends reconstruct\u003C{\n  id: string;\n  title: string;\n  createdAt: Date;\n}>({ \u002F* the card, verbatim *\u002F }) {}\n",[147,777,778,783,809,813,828,840,851,863],{"__ignoreMap":191},[195,779,780],{"class":197,"line":198},[195,781,782],{"class":556},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPost.ts — generated\n",[195,784,785,788,790,793,796,799,801,804,806],{"class":197,"line":468},[195,786,787],{"class":413},"import",[195,789,538],{"class":431},[195,791,792],{"class":427}," reconstruct",[195,794,795],{"class":431}," }",[195,797,798],{"class":413}," from",[195,800,454],{"class":442},[195,802,803],{"class":205},"@fougere\u002Fschema",[195,805,443],{"class":442},[195,807,808],{"class":431},";\n",[195,810,811],{"class":197,"line":475},[195,812,472],{"emptyLinePlaceholder":471},[195,814,815,817,819,821,823,825],{"class":197,"line":499},[195,816,414],{"class":413},[195,818,418],{"class":417},[195,820,428],{"class":201},[195,822,424],{"class":417},[195,824,792],{"class":435},[195,826,827],{"class":431},"\u003C{\n",[195,829,830,834,836,838],{"class":197,"line":548},[195,831,833],{"class":832},"sucvu","  id",[195,835,516],{"class":515},[195,837,576],{"class":575},[195,839,808],{"class":431},[195,841,842,845,847,849],{"class":197,"line":553},[195,843,844],{"class":832},"  title",[195,846,516],{"class":515},[195,848,576],{"class":575},[195,850,808],{"class":431},[195,852,853,856,858,861],{"class":197,"line":560},[195,854,855],{"class":832},"  createdAt",[195,857,516],{"class":515},[195,859,860],{"class":201}," Date",[195,862,808],{"class":431},[195,864,865,868,870,873,876,878,880],{"class":197,"line":597},[195,866,867],{"class":431},"}>",[195,869,439],{"class":427},[195,871,872],{"class":431},"{",[195,874,875],{"class":556}," \u002F* the card, verbatim *\u002F",[195,877,795],{"class":431},[195,879,462],{"class":427},[195,881,465],{"class":431},[144,883,884,885,887,888,891],{},"One class, like the one you would have written by hand: ",[147,886,532],{}," is the value — a judge\nthat validates locally, without an additional request to the host — and the type of a row\nit hands back, so ",[147,889,890],{},"post.titel"," does not compile. Both are read off the same card.",[144,893,894,895,898,899,902],{},"Next to it, ",[147,896,897],{},"handlers\u002FPostHandler.ts"," states what the frond serves, so a consumer can\nwrite ",[147,900,901],{},"Facade\u003CPostHandler>"," without holding the handler's code:",[186,904,906],{"className":404,"code":905,"language":406,"meta":191,"style":191},"export interface PostHandler {\n  list(invocation?: Invocation): Promise\u003CPost[] & { total?: number; hasMore?: boolean }>;\n  findById(invocation?: Invocation): Promise\u003CPost | undefined>;\n}\n",[147,907,908,920,976,1008],{"__ignoreMap":191},[195,909,910,912,915,917],{"class":197,"line":198},[195,911,414],{"class":413},[195,913,914],{"class":417}," interface",[195,916,485],{"class":201},[195,918,919],{"class":431}," {\n",[195,921,922,925,927,930,933,936,938,940,942,944,946,949,952,954,957,959,962,965,968,970,973],{"class":197,"line":468},[195,923,924],{"class":505},"  list",[195,926,439],{"class":431},[195,928,929],{"class":511},"invocation",[195,931,932],{"class":515},"?:",[195,934,935],{"class":201}," Invocation",[195,937,521],{"class":431},[195,939,516],{"class":515},[195,941,526],{"class":201},[195,943,529],{"class":431},[195,945,532],{"class":201},[195,947,948],{"class":427},"[] ",[195,950,951],{"class":515},"&",[195,953,538],{"class":431},[195,955,956],{"class":832}," total",[195,958,932],{"class":515},[195,960,961],{"class":575}," number",[195,963,964],{"class":431},";",[195,966,967],{"class":832}," hasMore",[195,969,932],{"class":515},[195,971,972],{"class":575}," boolean",[195,974,975],{"class":431}," }>;\n",[195,977,978,981,983,985,987,989,991,993,995,997,999,1002,1005],{"class":197,"line":475},[195,979,980],{"class":505},"  findById",[195,982,439],{"class":431},[195,984,929],{"class":511},[195,986,932],{"class":515},[195,988,935],{"class":201},[195,990,521],{"class":431},[195,992,516],{"class":515},[195,994,526],{"class":201},[195,996,529],{"class":431},[195,998,532],{"class":201},[195,1000,1001],{"class":515}," |",[195,1003,1004],{"class":575}," undefined",[195,1006,1007],{"class":431},">;\n",[195,1009,1010],{"class":197,"line":499},[195,1011,545],{"class":431},[144,1013,1014,1015,1018,1019,1022],{},"The command also writes ",[147,1016,1017],{},".fougere\u002Fremotes.json",", which the Nuxt module reads to alias\n",[147,1020,1021],{},"@frond\u002Fblog",". Pages therefore use the same import path for a local or remote entity.",[144,1024,1025,1026,1029,1030,1033,1034,1037,1038,1041],{},"Re-running it ",[157,1027,1028],{},"removes what the host no longer serves",". The barrel loses the export by\nitself, but the file used to stay — and ",[147,1031,1032],{},"exports"," lists ",[147,1035,1036],{},"'.\u002Fentities\u002F*'"," as a wildcard, so\n",[147,1039,1040],{},"@frond\u002Fblog\u002Fentities\u002FTicket.js"," kept resolving to a class that validates perfectly and\nthat nothing behind it answers for. Only files carrying the generated header are removed;\nanything you put in that folder yourself is left alone.",[144,1043,1044,1045,1048],{},"The host returns entities associated with a façade, and ",[157,1046,1047],{},"the facts its fronds announce",".\nAn entity that is neither is not in the discovery result — a shape nobody exposed and\nnobody declared to leave stays home.",[144,1050,1051,1052,1055],{},"A fact has no operation, so it gets a class and no ",[147,1053,1054],{},"Handler"," interface beside it:",[186,1057,1059],{"className":404,"code":1058,"language":406,"meta":191,"style":191},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.ts — generated\nexport class PostPublished extends reconstruct\u003C{ id: string; title: string; at: Date }>(…) {}\n",[147,1060,1061,1066],{"__ignoreMap":191},[195,1062,1063],{"class":197,"line":198},[195,1064,1065],{"class":556},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.ts — generated\n",[195,1067,1068,1070,1072,1075,1077,1079,1082,1085,1087,1089,1091,1094,1096,1098,1100,1103,1105,1107,1110,1113],{"class":197,"line":468},[195,1069,414],{"class":413},[195,1071,418],{"class":417},[195,1073,1074],{"class":201}," PostPublished",[195,1076,424],{"class":417},[195,1078,792],{"class":435},[195,1080,1081],{"class":431},"\u003C{",[195,1083,1084],{"class":832}," id",[195,1086,516],{"class":515},[195,1088,576],{"class":575},[195,1090,964],{"class":431},[195,1092,1093],{"class":832}," title",[195,1095,516],{"class":515},[195,1097,576],{"class":575},[195,1099,964],{"class":431},[195,1101,1102],{"class":832}," at",[195,1104,516],{"class":515},[195,1106,860],{"class":201},[195,1108,1109],{"class":431}," }>",[195,1111,1112],{"class":427},"(…) ",[195,1114,465],{"class":431},[144,1116,1117,1118,1121,1122,1125],{},"To have an arriving fact judged, re-export that class into one of your own fronds — the\nboot validates against an entity of a ",[157,1119,1120],{},"scanned"," frond, and ",[147,1123,1124],{},".fougere\u002Fremotes\u002F"," is a\npackage, not a frond:",[186,1127,1129],{"className":404,"code":1128,"language":406,"meta":191,"style":191},"\u002F\u002F fronds\u002Fsearch\u002Fentities\u002FPostPublished.ts\nexport { default } from '..\u002F..\u002F..\u002F.fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.js';\n",[147,1130,1131,1136],{"__ignoreMap":191},[195,1132,1133],{"class":197,"line":198},[195,1134,1135],{"class":556},"\u002F\u002F fronds\u002Fsearch\u002Fentities\u002FPostPublished.ts\n",[195,1137,1138,1140,1142,1144,1146,1148,1150,1153,1155],{"class":197,"line":468},[195,1139,414],{"class":413},[195,1141,538],{"class":431},[195,1143,480],{"class":413},[195,1145,795],{"class":431},[195,1147,798],{"class":413},[195,1149,454],{"class":442},[195,1151,1152],{"class":205},"..\u002F..\u002F..\u002F.fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.js",[195,1154,443],{"class":442},[195,1156,808],{"class":431},[1158,1159,1161],"h3",{"id":1160},"the-rules","The rules",[235,1163,1164,1173],{},[238,1165,1166],{},[241,1167,1168,1170],{},[244,1169,147],{},[244,1171,1172],{},"what it means",[251,1174,1175,1192,1202],{},[241,1176,1177,1189],{},[256,1178,1179,1182,1183,1182,1186],{},[147,1180,1181],{},"directory-unreadable",", ",[147,1184,1185],{},"handler-parse-failed",[147,1187,1188],{},"heritage-unresolved",[256,1190,1191],{},"what the scan could not do — a rule about an absence is only sound if the analysis attests it looked",[241,1193,1194,1199],{},[256,1195,1196],{},[147,1197,1198],{},"operation-unbound",[256,1200,1201],{},"an operation declares parameters and has no binding plan: it is served, and it receives none of them",[241,1203,1204,1209],{},[256,1205,1206],{},[147,1207,1208],{},"cross-frond-import",[256,1210,1211],{},"a relative import that resolves into another frond",[144,1213,1214,1215,1218,1219,1222,1223,1225],{},"The last one is a warning, not a refusal — it resolves today and the app runs. What it\nstates is that a ",[157,1216,1217],{},"colocation constraint is holding the app together and nothing declares\nit",": ",[147,1220,1221],{},"'..\u002F..\u002Fuser\u002Fentities\u002FUser.js'"," says these two folders are neighbours, in a string\nthe scan, the identity card and ",[147,1224,640],{}," all ignore. It keeps working right up to the day\nthat folder is not there, and then it fails as a file path rather than as a model.",[144,1227,1228,1231,1232,1237],{},[147,1229,1230],{},"'@frond\u002Fuser\u002Fentities\u002FUser.js'"," says the same dependency in terms the model reads, and it\nis the form ",[362,1233,1235],{"href":1234},"#fougere-sync-consume-a-remote-frond",[147,1236,740],{}," writes — so it survives\nthe frond moving out. The name resolves the same way whether the frond is local or synced.",[178,1239,1241,1244],{"id":1240},"fougere-graph-read-the-model",[147,1242,1243],{},"fougere graph"," — read the model",[186,1246,1248],{"className":188,"code":1247,"language":190,"meta":191,"style":191},"fougere graph\n",[147,1249,1250],{"__ignoreMap":191},[195,1251,1252,1254],{"class":197,"line":198},[195,1253,202],{"class":201},[195,1255,1256],{"class":205}," graph\n",[144,1258,1259],{},"Prints entities, their references, and the number of incoming references. Beyond six\nentities, the command also suggests clusters calculated from that graph:",[186,1261,1264],{"className":1262,"code":1263,"language":231},[229],"  Post → Author, Category (2 incoming)\n  Author\n",[147,1265,1263],{"__ignoreMap":191},[144,1267,1268,1269,1272],{},"The ",[362,1270,1271],{"href":39},"shortest path"," page covers current and possible future\nuses of this graph.",[178,1274,1276,1279],{"id":1275},"fougere-build-frond-publish-a-fronds-entities",[147,1277,1278],{},"fougere build-frond"," — publish a Frond's entities",[186,1281,1283],{"className":188,"code":1282,"language":190,"meta":191,"style":191},"fougere build-frond blog\n",[147,1284,1285],{"__ignoreMap":191},[195,1286,1287,1289,1292],{"class":197,"line":198},[195,1288,202],{"class":201},[195,1290,1291],{"class":205}," build-frond",[195,1293,1294],{"class":205}," blog\n",[144,1296,1297,1298,1301,1302,1305,1306,1309,1310,432],{},"Compiles ",[147,1299,1300],{},"fronds\u002Fblog\u002Fentities\u002F**"," to ",[147,1303,1304],{},"dist\u002F"," with type declarations and configures the\nFrond's ",[147,1307,1308],{},"package.json",". A consumer in another repository can then install that package.\nSee ",[362,1311,1313],{"href":1312},"\u002Fdocs\u002Finfra\u002Fgradient#where-the-code-lives","where the code lives",[144,1315,1316,1317,432],{},"Next: ",[362,1318,30],{"href":31},[1320,1321,1322],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--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 .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 .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":191,"searchDepth":468,"depth":468,"links":1324},[1325,1327,1329,1331,1335,1337],{"id":180,"depth":468,"text":1326},"fougere new — compose a workspace",{"id":605,"depth":468,"text":1328},"fougere serve — one Frond, its own process",{"id":676,"depth":468,"text":1330},"fougere call — invoke an operation",{"id":737,"depth":468,"text":1332,"children":1333},"fougere sync — consume a remote Frond",[1334],{"id":1160,"depth":475,"text":1161},{"id":1240,"depth":468,"text":1336},"fougere graph — read the model",{"id":1275,"depth":468,"text":1338},"fougere build-frond — publish a Frond's entities","fougere new, serve, call, sync, graph — composing a workspace, hosting one Frond, invoking an operation from a shell.","md",{},{"title":21,"description":1339},"FbhLudrh1B4C_Hfxk3REiaET6EhZbztDptsiBNnLpUQ",1786637819120]