[{"data":1,"prerenderedAt":1643},["ShallowReactive",2],{"fougere:post.list:{}":3,"docs:\u002Fdocs\u002Fconcepts\u002Fconfiguration":6,"docs-uses":1345,"docs-nav":1505},{"items":4,"hasMore":5},[],false,{"id":7,"title":8,"body":9,"description":1336,"extension":1337,"forms":1338,"kind":1339,"meta":1340,"navigation":116,"path":1341,"seo":1342,"stem":1343,"step":120,"uses":1338,"__hash__":1344},"docs\u002Fdocs\u002F1.concepts\u002F8.configuration.md","Configuration",{"type":10,"value":11,"toc":1324},"minimark",[12,30,276,284,289,295,324,327,362,370,374,385,484,494,498,508,618,656,660,666,725,732,739,753,801,812,816,822,942,966,992,996,999,1134,1138,1236,1251,1255,1265,1268,1314,1320],[13,14,15,16,20,21,24,25,29],"p",{},"Your code says what a thing is: its data, what it does. It names no process, no provider, no\ndatabase and no protocol. Those choices live in one file at the root of the project,\n",[17,18,19],"code",{},"fougere.config.ts",", and changing them changes no line under ",[17,22,23],{},"fronds\u002F",". That separation is\n",[26,27,28],"strong",{},"the gradient",": since nothing in a frond says where it runs, moving it is a line of config.",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-ts shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u002F\u002F fougere.config.ts\nimport '@fougere\u002Fadapter-sql';\nimport '@fougere\u002Fadapter-rest';\nimport { defineFougere } from '@fougere\u002Fcore';\n\nexport default defineFougere({\n  fronds: { catalog: { remote: 'http:\u002F\u002F127.0.0.1:4620' } },\n  ports: { Payment: 'StripePayment' },\n  sources: { main: { type: 'sqlite', path: '.data\u002Fshop.db' } },\n  protocols: { rest: {} },\n});\n","ts","",[17,38,39,48,70,84,111,118,137,173,197,245,265],{"__ignoreMap":36},[40,41,44],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"skXKP","\u002F\u002F fougere.config.ts\n",[40,49,51,55,59,63,66],{"class":42,"line":50},2,[40,52,54],{"class":53},"sK6XW","import",[40,56,58],{"class":57},"sDDC1"," '",[40,60,62],{"class":61},"sN-8n","@fougere\u002Fadapter-sql",[40,64,65],{"class":57},"'",[40,67,69],{"class":68},"s15xx",";\n",[40,71,73,75,77,80,82],{"class":42,"line":72},3,[40,74,54],{"class":53},[40,76,58],{"class":57},[40,78,79],{"class":61},"@fougere\u002Fadapter-rest",[40,81,65],{"class":57},[40,83,69],{"class":68},[40,85,87,89,92,96,99,102,104,107,109],{"class":42,"line":86},4,[40,88,54],{"class":53},[40,90,91],{"class":68}," {",[40,93,95],{"class":94},"sPEhv"," defineFougere",[40,97,98],{"class":68}," }",[40,100,101],{"class":53}," from",[40,103,58],{"class":57},[40,105,106],{"class":61},"@fougere\u002Fcore",[40,108,65],{"class":57},[40,110,69],{"class":68},[40,112,114],{"class":42,"line":113},5,[40,115,117],{"emptyLinePlaceholder":116},true,"\n",[40,119,121,124,127,130,134],{"class":42,"line":120},6,[40,122,123],{"class":53},"export",[40,125,126],{"class":53}," default",[40,128,95],{"class":129},"s4mR9",[40,131,133],{"class":132},"srlTG","(",[40,135,136],{"class":68},"{\n",[40,138,140,144,147,149,152,154,156,159,161,163,166,168,170],{"class":42,"line":139},7,[40,141,143],{"class":142},"sHtqg","  fronds",[40,145,146],{"class":68},":",[40,148,91],{"class":68},[40,150,151],{"class":142}," catalog",[40,153,146],{"class":68},[40,155,91],{"class":68},[40,157,158],{"class":142}," remote",[40,160,146],{"class":68},[40,162,58],{"class":57},[40,164,165],{"class":61},"http:\u002F\u002F127.0.0.1:4620",[40,167,65],{"class":57},[40,169,98],{"class":68},[40,171,172],{"class":68}," },\n",[40,174,176,179,181,183,186,188,190,193,195],{"class":42,"line":175},8,[40,177,178],{"class":142},"  ports",[40,180,146],{"class":68},[40,182,91],{"class":68},[40,184,185],{"class":142}," Payment",[40,187,146],{"class":68},[40,189,58],{"class":57},[40,191,192],{"class":61},"StripePayment",[40,194,65],{"class":57},[40,196,172],{"class":68},[40,198,200,203,205,207,210,212,214,217,219,221,224,226,229,232,234,236,239,241,243],{"class":42,"line":199},9,[40,201,202],{"class":142},"  sources",[40,204,146],{"class":68},[40,206,91],{"class":68},[40,208,209],{"class":142}," main",[40,211,146],{"class":68},[40,213,91],{"class":68},[40,215,216],{"class":142}," type",[40,218,146],{"class":68},[40,220,58],{"class":57},[40,222,223],{"class":61},"sqlite",[40,225,65],{"class":57},[40,227,228],{"class":68},",",[40,230,231],{"class":142}," path",[40,233,146],{"class":68},[40,235,58],{"class":57},[40,237,238],{"class":61},".data\u002Fshop.db",[40,240,65],{"class":57},[40,242,98],{"class":68},[40,244,172],{"class":68},[40,246,248,251,253,255,258,260,263],{"class":42,"line":247},10,[40,249,250],{"class":142},"  protocols",[40,252,146],{"class":68},[40,254,91],{"class":68},[40,256,257],{"class":142}," rest",[40,259,146],{"class":68},[40,261,262],{"class":68}," {}",[40,264,172],{"class":68},[40,266,268,271,274],{"class":42,"line":267},11,[40,269,270],{"class":68},"}",[40,272,273],{"class":132},")",[40,275,69],{"class":68},[13,277,278,279,283],{},"Leave a key out and you get the default: every frond in the app's process, the only realization of\neach port, rows in memory (the boot warns), no REST and no GraphQL. The imports at the top make a\nsource type or a protocol exist; naming one that is not imported refuses the boot, naming the import.\nEvery key, and the package that answers it: ",[280,281,19],"a",{"href":282},"\u002Freference\u002Fconfig",".",[285,286,288],"h2",{"id":287},"where-each-frond-runs","Where each frond runs",[13,290,291,294],{},[17,292,293],{},"fronds:"," gives a frond an address. Start the catalog alone:",[31,296,300],{"className":297,"code":298,"language":299,"meta":36,"style":36},"language-bash shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","fougere dev catalog --port 4620       # in production: fougere build, then fougere serve\n","bash",[17,301,302],{"__ignoreMap":36},[40,303,304,308,311,313,317,321],{"class":42,"line":43},[40,305,307],{"class":306},"sV8pK","fougere",[40,309,310],{"class":61}," dev",[40,312,151],{"class":61},[40,314,316],{"class":315},"svHQO"," --port",[40,318,320],{"class":319},"s3dPA"," 4620",[40,322,323],{"class":46},"       # in production: fougere build, then fougere serve\n",[13,325,326],{},"and name that address:",[31,328,330],{"className":33,"code":329,"language":35,"meta":36,"style":36},"fronds: { catalog: { remote: 'http:\u002F\u002F127.0.0.1:4620' } },\n",[17,331,332],{"__ignoreMap":36},[40,333,334,338,340,342,344,346,348,350,352,354,356,358,360],{"class":42,"line":43},[40,335,337],{"class":336},"sWI7z","fronds",[40,339,146],{"class":68},[40,341,91],{"class":68},[40,343,151],{"class":336},[40,345,146],{"class":68},[40,347,91],{"class":68},[40,349,158],{"class":336},[40,351,146],{"class":68},[40,353,58],{"class":57},[40,355,165],{"class":61},[40,357,65],{"class":57},[40,359,98],{"class":68},[40,361,172],{"class":68},[13,363,364,365,369],{},"The code that calls the catalog does not change; the call now crosses the network. Remove the line\nand the catalog runs in the app's process again. The ",[280,366,368],{"href":367},"\u002Ftutorial\u002F8-split","tutorial"," does it step by step.",[285,371,373],{"id":372},"what-answers-a-port","What answers a port",[13,375,376,377,380,381,384],{},"When two classes extend ",[17,378,379],{},"Payment",", the boot stops until ",[17,382,383],{},"ports:"," says which one answers. The same\nkey orders the links that stand in front of it, outside in:",[31,386,388],{"className":33,"code":387,"language":35,"meta":36,"style":36},"ports: { Payment: process.env.NODE_ENV === 'production' ? 'StripePayment' : 'FakePayment' },\nports: { Payment: ['AuditPayment', 'StripePayment'] },\n",[17,389,390,448],{"__ignoreMap":36},[40,391,392,395,397,399,401,403,406,408,412,414,417,420,422,425,427,430,432,434,436,439,441,444,446],{"class":42,"line":43},[40,393,394],{"class":336},"ports",[40,396,146],{"class":68},[40,398,91],{"class":68},[40,400,185],{"class":336},[40,402,146],{"class":68},[40,404,405],{"class":94}," process",[40,407,283],{"class":68},[40,409,411],{"class":410},"sy9f4","env",[40,413,283],{"class":68},[40,415,416],{"class":410},"NODE_ENV",[40,418,419],{"class":68}," ===",[40,421,58],{"class":57},[40,423,424],{"class":61},"production",[40,426,65],{"class":57},[40,428,429],{"class":68}," ?",[40,431,58],{"class":57},[40,433,192],{"class":61},[40,435,65],{"class":57},[40,437,438],{"class":68}," :",[40,440,58],{"class":57},[40,442,443],{"class":61},"FakePayment",[40,445,65],{"class":57},[40,447,172],{"class":68},[40,449,450,452,454,456,458,460,464,466,469,471,473,475,477,479,482],{"class":42,"line":50},[40,451,394],{"class":336},[40,453,146],{"class":68},[40,455,91],{"class":68},[40,457,185],{"class":336},[40,459,146],{"class":68},[40,461,463],{"class":462},"spAFX"," [",[40,465,65],{"class":57},[40,467,468],{"class":61},"AuditPayment",[40,470,65],{"class":57},[40,472,228],{"class":68},[40,474,58],{"class":57},[40,476,192],{"class":61},[40,478,65],{"class":57},[40,480,481],{"class":462},"]",[40,483,172],{"class":68},[13,485,486,487,489,490,283],{},"The handler asks for ",[17,488,379],{}," and never learns which one it got. See ",[280,491,493],{"href":492},"\u002Fdocs\u002Fconcepts\u002Fport","Port",[285,495,497],{"id":496},"where-rows-live","Where rows live",[13,499,500,503,504,507],{},[17,501,502],{},"sources:"," names each place rows live. The entry with no ",[17,505,506],{},"rows:"," holds every entity the others do\nnot list:",[31,509,511],{"className":33,"code":510,"language":35,"meta":36,"style":36},"sources: {\n  main: { type: 'sqlite', path: '.data\u002Fshop.db' },\n  archive: { type: 'file', path: '.\u002Farchive', rows: ['Order'] },   \u002F\u002F import '@fougere\u002Fadapter-file'\n},\n",[17,512,513,523,556,613],{"__ignoreMap":36},[40,514,515,518,520],{"class":42,"line":43},[40,516,517],{"class":336},"sources",[40,519,146],{"class":68},[40,521,522],{"class":68}," {\n",[40,524,525,528,530,532,534,536,538,540,542,544,546,548,550,552,554],{"class":42,"line":50},[40,526,527],{"class":336},"  main",[40,529,146],{"class":68},[40,531,91],{"class":68},[40,533,216],{"class":336},[40,535,146],{"class":68},[40,537,58],{"class":57},[40,539,223],{"class":61},[40,541,65],{"class":57},[40,543,228],{"class":68},[40,545,231],{"class":336},[40,547,146],{"class":68},[40,549,58],{"class":57},[40,551,238],{"class":61},[40,553,65],{"class":57},[40,555,172],{"class":68},[40,557,558,561,563,565,567,569,571,574,576,578,580,582,584,587,589,591,594,596,598,600,603,605,607,610],{"class":42,"line":72},[40,559,560],{"class":336},"  archive",[40,562,146],{"class":68},[40,564,91],{"class":68},[40,566,216],{"class":336},[40,568,146],{"class":68},[40,570,58],{"class":57},[40,572,573],{"class":61},"file",[40,575,65],{"class":57},[40,577,228],{"class":68},[40,579,231],{"class":336},[40,581,146],{"class":68},[40,583,58],{"class":57},[40,585,586],{"class":61},".\u002Farchive",[40,588,65],{"class":57},[40,590,228],{"class":68},[40,592,593],{"class":336}," rows",[40,595,146],{"class":68},[40,597,463],{"class":462},[40,599,65],{"class":57},[40,601,602],{"class":61},"Order",[40,604,65],{"class":57},[40,606,481],{"class":462},[40,608,609],{"class":68}," },",[40,611,612],{"class":46},"   \u002F\u002F import '@fougere\u002Fadapter-file'\n",[40,614,615],{"class":42,"line":86},[40,616,617],{"class":68},"},\n",[13,619,620,622,623,626,627,630,631,634,635,638,639,642,643,646,647,651,652,283],{},[17,621,602],{}," is now kept as files under ",[17,624,625],{},"archive\u002F","; everything else stays in ",[17,628,629],{},"main",". The repository a\nhandler asks for is the same either way. An entity with one instance — a search engine's address,\nsome settings — is listed in ",[17,632,633],{},"values:"," and injected as that value: ",[17,636,637],{},"env: { type: 'env', values: ['Meili'] }"," reads ",[17,640,641],{},"MEILI_URL"," into the ",[17,644,645],{},"Meili"," a constructor asks for. See\n",[280,648,650],{"href":649},"\u002Fdocs\u002Fdata\u002Fsql","SQLite or Postgres"," and ",[280,653,655],{"href":654},"\u002Fdocs\u002Fdata\u002Fvalues","Values",[285,657,659],{"id":658},"what-the-app-serves","What the app serves",[13,661,662,665],{},[17,663,664],{},"protocols:"," says which APIs the app answers on, beside the calls its own pages make:",[31,667,669],{"className":33,"code":668,"language":35,"meta":36,"style":36},"import '@fougere\u002Fadapter-rest';\nimport '@fougere\u002Fadapter-graphql';\n\nprotocols: { rest: {}, graphql: {} },\n",[17,670,671,683,696,700],{"__ignoreMap":36},[40,672,673,675,677,679,681],{"class":42,"line":43},[40,674,54],{"class":53},[40,676,58],{"class":57},[40,678,79],{"class":61},[40,680,65],{"class":57},[40,682,69],{"class":68},[40,684,685,687,689,692,694],{"class":42,"line":50},[40,686,54],{"class":53},[40,688,58],{"class":57},[40,690,691],{"class":61},"@fougere\u002Fadapter-graphql",[40,693,65],{"class":57},[40,695,69],{"class":68},[40,697,698],{"class":42,"line":72},[40,699,117],{"emptyLinePlaceholder":116},[40,701,702,705,707,709,711,713,716,719,721,723],{"class":42,"line":86},[40,703,704],{"class":336},"protocols",[40,706,146],{"class":68},[40,708,91],{"class":68},[40,710,257],{"class":336},[40,712,146],{"class":68},[40,714,715],{"class":68}," {},",[40,717,718],{"class":336}," graphql",[40,720,146],{"class":68},[40,722,262],{"class":68},[40,724,172],{"class":68},[13,726,727,728,283],{},"Importing an adapter makes a protocol available; naming it here is what serves it. See\n",[280,729,731],{"href":730},"\u002Fdocs\u002Fserve\u002Frest-graphql","REST, OpenAPI, GraphQL",[285,733,735,736],{"id":734},"what-stands-around-fougere-serve","What stands around ",[17,737,738],{},"fougere serve",[13,740,741,743,744,748,749,752],{},[17,742,738],{}," is the one host where Fougere ",[745,746,747],"em",{},"is"," the server, so what you would put around a server\nof your own goes in ",[17,750,751],{},"server:"," — srvx middlewares, outside in:",[31,754,756],{"className":33,"code":755,"language":35,"meta":36,"style":36},"server: { use: [cors({ origin: 'https:\u002F\u002Fapp.example.com' })] },\n",[17,757,758],{"__ignoreMap":36},[40,759,760,763,765,767,770,772,774,777,779,782,785,787,789,792,794,796,799],{"class":42,"line":43},[40,761,762],{"class":336},"server",[40,764,146],{"class":68},[40,766,91],{"class":68},[40,768,769],{"class":336}," use",[40,771,146],{"class":68},[40,773,463],{"class":462},[40,775,776],{"class":129},"cors",[40,778,133],{"class":462},[40,780,781],{"class":68},"{",[40,783,784],{"class":142}," origin",[40,786,146],{"class":68},[40,788,58],{"class":57},[40,790,791],{"class":61},"https:\u002F\u002Fapp.example.com",[40,793,65],{"class":57},[40,795,98],{"class":68},[40,797,798],{"class":462},")]",[40,800,172],{"class":68},[13,802,803,804,807,808,283],{},"They stand around what the process answers browsers — REST, GraphQL, and any request none of them\nclaims, such as a ",[17,805,806],{},"\u002Fhealthz",". Under Nuxt, Next, Express or Hono the key is not read: the server and\nits middlewares are yours. See ",[280,809,811],{"href":810},"\u002Fdocs\u002Fadopt\u002Fhosts#any-engine","Pick a host",[285,813,815],{"id":814},"what-the-app-is-made-of","What the app is made of",[13,817,818,819,821],{},"Besides an address, an entry of ",[17,820,293],{}," can say two more things — which frond inherits from which,\nand which package brings a frond of its own:",[31,823,825],{"className":33,"code":824,"language":35,"meta":36,"style":36},"fronds: {\n  shop: {},\n  cart:    { extends: 'shop' },                  \u002F\u002F cart and pricing inherit shop's code\n  pricing: { extends: 'shop' },\n  blog:    { remote: 'http:\u002F\u002F127.0.0.1:4100' },  \u002F\u002F answers elsewhere\n  '@fougere\u002Flog': {},                            \u002F\u002F a package: every process logs its calls\n},\n",[17,826,827,835,845,872,893,918,938],{"__ignoreMap":36},[40,828,829,831,833],{"class":42,"line":43},[40,830,337],{"class":336},[40,832,146],{"class":68},[40,834,522],{"class":68},[40,836,837,840,842],{"class":42,"line":50},[40,838,839],{"class":336},"  shop",[40,841,146],{"class":68},[40,843,844],{"class":68}," {},\n",[40,846,847,850,852,855,858,860,862,865,867,869],{"class":42,"line":72},[40,848,849],{"class":336},"  cart",[40,851,146],{"class":68},[40,853,854],{"class":68},"    {",[40,856,857],{"class":336}," extends",[40,859,146],{"class":68},[40,861,58],{"class":57},[40,863,864],{"class":61},"shop",[40,866,65],{"class":57},[40,868,609],{"class":68},[40,870,871],{"class":46},"                  \u002F\u002F cart and pricing inherit shop's code\n",[40,873,874,877,879,881,883,885,887,889,891],{"class":42,"line":86},[40,875,876],{"class":336},"  pricing",[40,878,146],{"class":68},[40,880,91],{"class":68},[40,882,857],{"class":336},[40,884,146],{"class":68},[40,886,58],{"class":57},[40,888,864],{"class":61},[40,890,65],{"class":57},[40,892,172],{"class":68},[40,894,895,898,900,902,904,906,908,911,913,915],{"class":42,"line":113},[40,896,897],{"class":336},"  blog",[40,899,146],{"class":68},[40,901,854],{"class":68},[40,903,158],{"class":336},[40,905,146],{"class":68},[40,907,58],{"class":57},[40,909,910],{"class":61},"http:\u002F\u002F127.0.0.1:4100",[40,912,65],{"class":57},[40,914,609],{"class":68},[40,916,917],{"class":46},"  \u002F\u002F answers elsewhere\n",[40,919,920,923,926,928,932,935],{"class":42,"line":120},[40,921,922],{"class":57},"  '",[40,924,925],{"class":61},"@fougere\u002Flog",[40,927,65],{"class":57},[40,929,931],{"class":930},"ssXpW",": ",[40,933,934],{"class":68},"{},",[40,936,937],{"class":46},"                            \u002F\u002F a package: every process logs its calls\n",[40,939,940],{"class":42,"line":139},[40,941,617],{"class":68},[13,943,944,945,947,948,951,952,955,956,958,959,961,962,965],{},"Fronds under ",[17,946,23],{}," need no entry; the scan finds them. ",[17,949,950],{},"extends"," says one thing: ",[17,953,954],{},"cart"," resolves\nthe services, repositories and ports ",[17,957,864],{}," declared. It grants no right to call — ",[17,960,954],{}," still\nreaches ",[17,963,964],{},"pricing"," through a facade or a fact, like any neighbour. A frond others inherit from serves\nnothing (the boot refuses it otherwise), so nothing can call it or move it, and it stands in every\nprocess that holds one of its children.",[13,967,968,969,972,973,651,976,979,980,983,984,987,988,283],{},"The scheme of ",[17,970,971],{},"remote:"," names what carries the call: ",[17,974,975],{},"http:\u002F\u002F",[17,977,978],{},"https:\u002F\u002F",", or ",[17,981,982],{},"binding:\u002F\u002FCATALOG","\nfor a Cloudflare service binding, all three registered by ",[17,985,986],{},"@fougere\u002Ftransport-http",". Another scheme is\na package's to register — see ",[280,989,991],{"href":990},"\u002Fdocs\u002Fextending\u002Fextension-points#a-transport-and-http","extension points",[285,993,995],{"id":994},"five-rungs-and-what-each-costs","Five rungs, and what each costs",[13,997,998],{},"Going up a rung never rewrites what you wrote. What each one costs:",[1000,1001,1002,1020],"table",{},[1003,1004,1005],"thead",{},[1006,1007,1008,1011,1014,1017],"tr",{},[1009,1010],"th",{},[1009,1012,1013],{},"The step",[1009,1015,1016],{},"What it buys",[1009,1018,1019],{},"What it costs",[1021,1022,1023,1038,1068,1089,1115],"tbody",{},[1006,1024,1025,1029,1032,1035],{},[1026,1027,1028],"td",{},"0",[1026,1030,1031],{},"one frond, one process",[1026,1033,1034],{},"a running app — no network, no HTTP",[1026,1036,1037],{},"nothing",[1006,1039,1040,1043,1049,1052],{},[1026,1041,1042],{},"1",[1026,1044,1045,1046],{},"a second frond, in ",[17,1047,1048],{},"fronds\u002Fbilling\u002F",[1026,1050,1051],{},"a boundary of ownership, before any network",[1026,1053,1054,1055,1058,1059,1062,1063,1067],{},"no reaching into another frond's files (",[17,1056,1057],{},"fougere check"," reports ",[17,1060,1061],{},"cross-frond-import","); a ",[280,1064,1066],{"href":1065},"\u002Fdocs\u002Faccess\u002Fauthentication#know-who-calls","collector"," lives in the frond that uses it",[1006,1069,1070,1073,1078,1081],{},[1026,1071,1072],{},"2",[1026,1074,1075],{},[17,1076,1077],{},"fronds: { blog: { remote: '…' } }",[1026,1079,1080],{},"the frond runs elsewhere, same code",[1026,1082,1083,1084,1088],{},"the hop and its JSON; beyond one machine the receiver must ",[280,1085,1087],{"href":1086},"\u002Fdocs\u002Frun\u002Fsecure","know who calls","; a named surface answers nothing for a remote frond; one address per frond, so a frond cannot be deployed twice",[1006,1090,1091,1094,1097,1100],{},[1026,1092,1093],{},"3",[1026,1095,1096],{},"the frond moves to its own repository",[1026,1098,1099],{},"its own team, release cycle and deployment",[1026,1101,1102,1103,1106,1107,1110,1111],{},"its ",[26,1104,1105],{},"contract"," is copied (",[17,1108,1109],{},"fougere sync","), the carrier under facts is yours, and readers of a fact deploy before its sender — see ",[280,1112,1114],{"href":1113},"\u002Fdocs\u002Fadopt\u002Fanother-repository","A frond from another repository",[1006,1116,1117,1120,1123,1126],{},[1026,1118,1119],{},"4",[1026,1121,1122],{},"the frond is not TypeScript",[1026,1124,1125],{},"a Rust or Python process answering the same calls",[1026,1127,1128,1129,1133],{},"you honour ",[280,1130,1132],{"href":1131},"\u002Fdocs\u002Fextending\u002Fcard-and-wire","the card and the wire"," yourself",[285,1135,1137],{"id":1136},"after-a-split","After a split",[1000,1139,1140,1148],{},[1003,1141,1142],{},[1006,1143,1144,1146],{},[1009,1145],{},[1009,1147],{},[1021,1149,1150,1158,1180,1198,1206,1217,1228],{},[1006,1151,1152,1155],{},[1026,1153,1154],{},"results",[1026,1156,1157],{},"the same shapes on both sides, lists included",[1006,1159,1160,1163],{},[1026,1161,1162],{},"errors",[1026,1164,1165,1166,1169,1170,1172,1173,1172,1176,1179],{},"the same ",[17,1167,1168],{},"FougereError"," — ",[17,1171,17],{},", ",[17,1174,1175],{},"message",[17,1177,1178],{},"details"," — rebuilt on arrival",[1006,1181,1182,1185],{},[1026,1183,1184],{},"an optional input",[1026,1186,1187,1188,1191,1192,1195,1196],{},"absent is ",[17,1189,1190],{},"undefined","; JSON omits the key; an explicit ",[17,1193,1194],{},"null"," stays ",[17,1197,1194],{},[1006,1199,1200,1203],{},[1026,1201,1202],{},"state",[1026,1204,1205],{},"the calling app's session reaches the other process, in the signed envelope",[1006,1207,1208,1211],{},[1026,1209,1210],{},"caller",[1026,1212,1213,1216],{},[17,1214,1215],{},"invocation.caller"," names the frond that signed — absent when nothing was established",[1006,1218,1219,1222],{},[1026,1220,1221],{},"an unreachable process",[1026,1223,1224,1227],{},[17,1225,1226],{},"SERVICE_UNAVAILABLE"," — 503 on REST — and calls resume once it is back",[1006,1229,1230,1233],{},[1026,1231,1232],{},"the transport",[1026,1234,1235],{},"a timeout and retries on the envelope, never an automatic retry of a command",[13,1237,1238,1239,1245,1246,1250],{},"The split adds a hop: one HTTP request and its JSON, framed and unframed by the transport, after\nwhich the receiving side runs the same checks as a local call. What that costs depends on your\nnetwork and payloads; ",[280,1240,1244],{"href":1241,"rel":1242},"https:\u002F\u002Fgithub.com\u002Fchok\u002Ffougere\u002Ftree\u002Fmain\u002Fdemos\u002Fcrossing-cost",[1243],"nofollow","crossing-cost","\nmeasures it on a chain of three fronds, and ",[280,1247,1249],{"href":1248},"\u002Fdocs\u002Frun\u002Fobserve","Observe"," shows it per call.",[285,1252,1254],{"id":1253},"one-recipient-per-call","One recipient per call",[13,1256,1257,1258,1260,1261,1264],{},"Every call has one recipient: ",[17,1259,293],{}," gives each frond one address, and ",[17,1262,1263],{},"Facade\u003CT>"," resolves to one\nfacade. A device behind a firewall still names one gateway; that it opens the connection itself is a\nproperty of the deployment, not another kind of call.",[13,1266,1267],{},"A send with several recipients comes in two kinds, and only one is here:",[1000,1269,1270,1281],{},[1003,1271,1272],{},[1006,1273,1274,1276,1279],{},[1009,1275],{},[1009,1277,1278],{},"Who decides the recipients",[1009,1280],{},[1021,1282,1283,1297],{},[1006,1284,1285,1288,1291],{},[1026,1286,1287],{},"a fact — a post was published",[1026,1289,1290],{},"nobody: whoever accepts it",[1026,1292,1293],{},[280,1294,1296],{"href":1295},"\u002Fdocs\u002Fconcepts\u002Ffact","Fact",[1006,1298,1299,1302,1305],{},[1026,1300,1301],{},"a fleet",[1026,1303,1304],{},"the sender, naming the set",[1026,1306,1307,1308,1313],{},"not here — address it in the data, as ",[280,1309,1312],{"href":1310,"rel":1311},"https:\u002F\u002Fgithub.com\u002Fchok\u002Ffougere\u002Ftree\u002Fmain\u002Fdemos\u002Femit-fleet",[1243],"emit-fleet"," does",[13,1315,1316,1317,1319],{},"A remote frond adds latency and failure modes; Fougere reports them as typed errors and hides\nneither. One process stays the reference; ",[17,1318,293],{}," moves a frond when the need is real.",[1321,1322,1323],"style",{},"html pre.shiki code .skXKP, html code.shiki .skXKP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#7D8C80;--shiki-default-font-style:inherit;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sK6XW, html code.shiki .sK6XW{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#8FCF86;--shiki-default-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sDDC1, html code.shiki .sDDC1{--shiki-light:#39ADB5;--shiki-default:#EE9F6B;--shiki-dark:#89DDFF}html pre.shiki code .sN-8n, html code.shiki .sN-8n{--shiki-light:#91B859;--shiki-default:#EE9F6B;--shiki-dark:#C3E88D}html pre.shiki code .s15xx, html code.shiki .s15xx{--shiki-light:#39ADB5;--shiki-default:#A3B0A5;--shiki-dark:#89DDFF}html pre.shiki code .sPEhv, html code.shiki .sPEhv{--shiki-light:#90A4AE;--shiki-default:#DDE5DA;--shiki-dark:#BABED8}html pre.shiki code .s4mR9, html code.shiki .s4mR9{--shiki-light:#6182B8;--shiki-default:#C9B6EA;--shiki-dark:#82AAFF}html pre.shiki code .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--shiki-dark:#BABED8}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}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 .sWI7z, html code.shiki .sWI7z{--shiki-light:#E2931D;--shiki-default:#93CFC0;--shiki-dark:#FFCB6B}html pre.shiki code .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}html pre.shiki code .spAFX, html code.shiki .spAFX{--shiki-light:#E53935;--shiki-default:#A3B0A5;--shiki-dark:#F07178}html pre.shiki code .ssXpW, html code.shiki .ssXpW{--shiki-light:#E53935;--shiki-default:#DDE5DA;--shiki-dark:#F07178}html pre.shiki code .sV8pK, html code.shiki .sV8pK{--shiki-light:#E2931D;--shiki-default:#C9B6EA;--shiki-dark:#FFCB6B}html pre.shiki code .svHQO, html code.shiki .svHQO{--shiki-light:#91B859;--shiki-default:#8FCF86;--shiki-dark:#C3E88D}html pre.shiki code .s3dPA, html code.shiki .s3dPA{--shiki-light:#F76D47;--shiki-default:#EE9F6B;--shiki-dark:#F78C6C}",{"title":36,"searchDepth":50,"depth":50,"links":1325},[1326,1327,1328,1329,1330,1332,1333,1334,1335],{"id":287,"depth":50,"text":288},{"id":372,"depth":50,"text":373},{"id":496,"depth":50,"text":497},{"id":658,"depth":50,"text":659},{"id":734,"depth":50,"text":1331},"What stands around fougere serve",{"id":814,"depth":50,"text":815},{"id":994,"depth":50,"text":995},{"id":1136,"depth":50,"text":1137},{"id":1253,"depth":50,"text":1254},"Your code says what a thing is; fougere.config.ts says how it runs.","md",null,"concept",{},"\u002Fdocs\u002Fconcepts\u002Fconfiguration",{"title":8,"description":1336},"docs\u002F1.concepts\u002F8.configuration","L2Va_UbXvI-CkxE5v1d85cWdCSKI9BK8bOPt39UKsJI",[1346,1349,1352,1355,1358,1361,1362,1363,1364,1370,1376,1379,1383,1387,1391,1395,1398,1403,1407,1411,1416,1418,1423,1427,1431,1435,1438,1442,1444,1448,1452,1456,1460,1464,1467,1469,1473,1476,1479,1482,1484,1487,1490,1493,1496,1499,1502],{"path":1347,"title":1348,"uses":1338},"\u002Fdocs\u002Fconcepts\u002Fentity","Entity",{"path":1350,"title":1351,"uses":1338},"\u002Fdocs\u002Fconcepts\u002Fhandler","Handler",{"path":1353,"title":1354,"uses":1338},"\u002Fdocs\u002Fconcepts\u002Frepository","Repository",{"path":1356,"title":1357,"uses":1338},"\u002Fdocs\u002Fconcepts\u002Ffrond","Frond",{"path":1359,"title":1360,"uses":1338},"\u002Fdocs\u002Fconcepts\u002Ffacade","Facade",{"path":1295,"title":1296,"uses":1338},{"path":492,"title":493,"uses":1338},{"path":1341,"title":8,"uses":1338},{"path":1365,"title":1366,"uses":1367},"\u002Fdocs\u002Faccess\u002Fauthentication","Authentication",[1368,1369],"port","frond",{"path":1371,"title":1372,"uses":1373},"\u002Fdocs\u002Faccess\u002Fstate","Keep a caller's state",[1374,1375],"configuration","handler",{"path":649,"title":650,"uses":1377},[1378,1374],"entity",{"path":1380,"title":1381,"uses":1382},"\u002Fdocs\u002Fdata\u002Fseveral-databases","Several databases",[1374,1378],{"path":1384,"title":1385,"uses":1386},"\u002Fdocs\u002Fdata\u002Fcomputed-field","A computed field",[1378,1368],{"path":1388,"title":1389,"uses":1390},"\u002Fdocs\u002Fdata\u002Fevolve","Evolve a schema",[1378],{"path":1392,"title":1393,"uses":1394},"\u002Fdocs\u002Fdata\u002Fseeds","Seed data",[1378],{"path":654,"title":1396,"uses":1397},"Read settings and secrets",[1378,1374],{"path":1399,"title":1400,"uses":1401},"\u002Fdocs\u002Fdata\u002Fmirror","Mirror a source you cannot query",[1402],"repository",{"path":1404,"title":1405,"uses":1406},"\u002Fdocs\u002Fdata\u002Ftogether","Two writes as one",[1402],{"path":1408,"title":1409,"uses":1410},"\u002Fdocs\u002Fbehaviour\u002Faround-every-call","Around every call",[1368,1369],{"path":1412,"title":1413,"uses":1414},"\u002Fdocs\u002Fbehaviour\u002Ffinish-a-fact","Finish a fact",[1415],"fact",{"path":730,"title":731,"uses":1417},[1375,1374],{"path":1419,"title":1420,"uses":1421},"\u002Fdocs\u002Fserve\u002Fpages","Pages: queries and commands",[1375,1422],"facade",{"path":1424,"title":1425,"uses":1426},"\u002Fdocs\u002Fserve\u002Fforms","A form",[1378],{"path":1428,"title":1429,"uses":1430},"\u002Fdocs\u002Fserve\u002Fadmin","An admin panel",[1375],{"path":1432,"title":1433,"uses":1434},"\u002Fdocs\u002Frun\u002Fdeploy","Deploy a split",[1374,1369],{"path":1086,"title":1436,"uses":1437},"Secure calls between processes",[1374,1369],{"path":1439,"title":1440,"uses":1441},"\u002Fdocs\u002Frun\u002Flifecycle","Reload and shut down",[1374],{"path":1248,"title":1249,"uses":1443},[1374,1375],{"path":1445,"title":1446,"uses":1447},"\u002Fdocs\u002Frun\u002Fdev-panel","The dev panel",[1375],{"path":1449,"title":1450,"uses":1451},"\u002Fdocs\u002Frun\u002Ftest","Test",[1378,1368],{"path":1453,"title":1454,"uses":1455},"\u002Fdocs\u002Fadopt\u002Fnew-project","Start a project",[1369,1374],{"path":1457,"title":1458,"uses":1459},"\u002Fdocs\u002Fadopt\u002Fexisting-app","Add Fougere to an existing app",[1369,1374],{"path":1461,"title":1462,"uses":1463},"\u002Fdocs\u002Fadopt\u002Fbring-your-schema","Bring your schema",[1378],{"path":1465,"title":811,"uses":1466},"\u002Fdocs\u002Fadopt\u002Fhosts",[1374],{"path":1113,"title":1114,"uses":1468},[1422,1369],{"path":1470,"title":1471,"uses":1472},"\u002Fdocs\u002Fadopt\u002Fdemos","Demos",[],{"path":1474,"title":1475,"uses":1338},"\u002Fdocs\u002Fextending\u002Fscan","How the scan reads a project",{"path":1477,"title":1478,"uses":1338},"\u002Fdocs\u002Fextending\u002Fwithout-compiler","Boot without the compiler",{"path":1480,"title":1481,"uses":1338},"\u002Fdocs\u002Fextending\u002Fboot","The boot, step by step",{"path":1131,"title":1483,"uses":1338},"The card and the wire",{"path":1485,"title":1486,"uses":1338},"\u002Fdocs\u002Fextending\u002Fextension-points","Registries and extension points",{"path":1488,"title":1489,"uses":1338},"\u002Fdocs\u002Fextending\u002Fvocabulary","Teach a word",{"path":1491,"title":1492,"uses":1338},"\u002Fdocs\u002Fextending\u002Fextensions","Run code at boot and shutdown",{"path":1494,"title":1495,"uses":1338},"\u002Fdocs\u002Fextending\u002Fsource-adapter","Write a source adapter",{"path":1497,"title":1498,"uses":1338},"\u002Fdocs\u002Fextending\u002Fsurface","Write a surface",{"path":1500,"title":1501,"uses":1338},"\u002Fdocs\u002Fextending\u002Fforeign-frond","A frond in another language",{"path":1503,"title":1504,"uses":1338},"\u002Fdocs","What is Fougere",[1506],{"title":1507,"path":1503,"stem":1508,"children":1509,"page":-1},"Docs","docs",[1510,1512,1532,1541,1562,1571,1584,1601,1618],{"title":1504,"path":1503,"stem":1511},"docs\u002Findex",{"title":1513,"path":1514,"stem":1515,"children":1516,"page":5},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F1.concepts",[1517,1519,1521,1523,1525,1527,1529,1531],{"title":1348,"path":1347,"stem":1518},"docs\u002F1.concepts\u002F1.entity",{"title":1351,"path":1350,"stem":1520},"docs\u002F1.concepts\u002F2.handler",{"title":1354,"path":1353,"stem":1522},"docs\u002F1.concepts\u002F3.repository",{"title":1357,"path":1356,"stem":1524},"docs\u002F1.concepts\u002F4.frond",{"title":1360,"path":1359,"stem":1526},"docs\u002F1.concepts\u002F5.facade",{"title":1296,"path":1295,"stem":1528},"docs\u002F1.concepts\u002F6.fact",{"title":493,"path":492,"stem":1530},"docs\u002F1.concepts\u002F7.port",{"title":8,"path":1341,"stem":1343},{"title":1533,"path":1534,"stem":1535,"children":1536,"page":5},"Access","\u002Fdocs\u002Faccess","docs\u002F2.access",[1537,1539],{"title":1366,"path":1365,"stem":1538},"docs\u002F2.access\u002F1.authentication",{"title":1372,"path":1371,"stem":1540},"docs\u002F2.access\u002F2.state",{"title":1542,"path":1543,"stem":1544,"children":1545,"page":5},"Data","\u002Fdocs\u002Fdata","docs\u002F3.data",[1546,1548,1550,1552,1554,1556,1558,1560],{"title":650,"path":649,"stem":1547},"docs\u002F3.data\u002F1.sql",{"title":1381,"path":1380,"stem":1549},"docs\u002F3.data\u002F2.several-databases",{"title":1385,"path":1384,"stem":1551},"docs\u002F3.data\u002F3.computed-field",{"title":1389,"path":1388,"stem":1553},"docs\u002F3.data\u002F4.evolve",{"title":1393,"path":1392,"stem":1555},"docs\u002F3.data\u002F5.seeds",{"title":1396,"path":654,"stem":1557},"docs\u002F3.data\u002F6.values",{"title":1400,"path":1399,"stem":1559},"docs\u002F3.data\u002F7.mirror",{"title":1405,"path":1404,"stem":1561},"docs\u002F3.data\u002F8.together",{"title":1563,"path":1564,"stem":1565,"children":1566,"page":5},"Behaviour","\u002Fdocs\u002Fbehaviour","docs\u002F4.behaviour",[1567,1569],{"title":1409,"path":1408,"stem":1568},"docs\u002F4.behaviour\u002F1.around-every-call",{"title":1413,"path":1412,"stem":1570},"docs\u002F4.behaviour\u002F2.finish-a-fact",{"title":1572,"path":1573,"stem":1574,"children":1575,"page":5},"Serve","\u002Fdocs\u002Fserve","docs\u002F5.serve",[1576,1578,1580,1582],{"title":731,"path":730,"stem":1577},"docs\u002F5.serve\u002F1.rest-graphql",{"title":1420,"path":1419,"stem":1579},"docs\u002F5.serve\u002F2.pages",{"title":1425,"path":1424,"stem":1581},"docs\u002F5.serve\u002F3.forms",{"title":1429,"path":1428,"stem":1583},"docs\u002F5.serve\u002F4.admin",{"title":1585,"path":1586,"stem":1587,"children":1588,"page":5},"Run","\u002Fdocs\u002Frun","docs\u002F6.run",[1589,1591,1593,1595,1597,1599],{"title":1433,"path":1432,"stem":1590},"docs\u002F6.run\u002F1.deploy",{"title":1436,"path":1086,"stem":1592},"docs\u002F6.run\u002F2.secure",{"title":1440,"path":1439,"stem":1594},"docs\u002F6.run\u002F3.lifecycle",{"title":1249,"path":1248,"stem":1596},"docs\u002F6.run\u002F4.observe",{"title":1446,"path":1445,"stem":1598},"docs\u002F6.run\u002F5.dev-panel",{"title":1450,"path":1449,"stem":1600},"docs\u002F6.run\u002F6.test",{"title":1602,"path":1603,"stem":1604,"children":1605,"page":5},"Adopt","\u002Fdocs\u002Fadopt","docs\u002F7.adopt",[1606,1608,1610,1612,1614,1616],{"title":1454,"path":1453,"stem":1607},"docs\u002F7.adopt\u002F1.new-project",{"title":1458,"path":1457,"stem":1609},"docs\u002F7.adopt\u002F2.existing-app",{"title":1462,"path":1461,"stem":1611},"docs\u002F7.adopt\u002F3.bring-your-schema",{"title":811,"path":1465,"stem":1613},"docs\u002F7.adopt\u002F4.hosts",{"title":1114,"path":1113,"stem":1615},"docs\u002F7.adopt\u002F5.another-repository",{"title":1471,"path":1470,"stem":1617},"docs\u002F7.adopt\u002F6.demos",{"title":1619,"path":1620,"stem":1621,"children":1622,"page":5},"Extending","\u002Fdocs\u002Fextending","docs\u002F8.extending",[1623,1625,1627,1629,1631,1633,1635,1637,1639,1641],{"title":1475,"path":1474,"stem":1624},"docs\u002F8.extending\u002F1.scan",{"title":1478,"path":1477,"stem":1626},"docs\u002F8.extending\u002F10.without-compiler",{"title":1481,"path":1480,"stem":1628},"docs\u002F8.extending\u002F2.boot",{"title":1483,"path":1131,"stem":1630},"docs\u002F8.extending\u002F3.card-and-wire",{"title":1486,"path":1485,"stem":1632},"docs\u002F8.extending\u002F4.extension-points",{"title":1489,"path":1488,"stem":1634},"docs\u002F8.extending\u002F5.vocabulary",{"title":1492,"path":1491,"stem":1636},"docs\u002F8.extending\u002F6.extensions",{"title":1495,"path":1494,"stem":1638},"docs\u002F8.extending\u002F7.source-adapter",{"title":1498,"path":1497,"stem":1640},"docs\u002F8.extending\u002F8.surface",{"title":1501,"path":1500,"stem":1642},"docs\u002F8.extending\u002F9.foreign-frond",1794396614356]