[{"data":1,"prerenderedAt":1864},["ShallowReactive",2],{"bml-reference-getting-started":3},{"data":4,"body":5},{},{"type":6,"children":7},"root",[8,17,57,64,75,81,92,98,174,255,261,272,304,309,318,358,384,393,481,487,518,527,557,563,582,593,609,620,652,670,676,687,696,733,744,750,803,809,814,823,856,865,908,920,939,964,969,981,987,1060,1100,1111,1129,1136,1162,1171,1224,1229,1238,1250,1256,1261,1318,1324,1356,1365,1494,1545,1624,1630,1635,1689,1717,1723,1748,1820,1852],{"type":9,"tag":10,"props":11,"children":13},"element","h1",{"id":12},"getting-started-with-bml",[14],{"type":15,"value":16},"text","Getting started with BML",{"type":9,"tag":18,"props":19,"children":20},"p",{},[21,23,29,31,38,40,47,49,55],{"type":15,"value":22},"BML (Bosca Markup Language) builds ",{"type":9,"tag":24,"props":25,"children":26},"strong",{},[27],{"type":15,"value":28},"server-rendered websites, emails, and push templates",{"type":15,"value":30}," from ",{"type":9,"tag":32,"props":33,"children":35},"code",{"className":34},"",[36],{"type":15,"value":37},".bml",{"type":15,"value":39},"\nfiles — HTML-like markup with embedded server Kotlin and client TypeScript. See the\n",{"type":9,"tag":41,"props":42,"children":44},"a",{"href":43},"\u002Fbml-reference\u002Fgrammar",[45],{"type":15,"value":46},"grammar",{"type":15,"value":48}," for the full language and ",{"type":9,"tag":41,"props":50,"children":52},{"href":51},"\u002Fbml-reference\u002Fexamples",[53],{"type":15,"value":54},"examples",{"type":15,"value":56}," for samples.",{"type":9,"tag":58,"props":59,"children":61},"h2",{"id":60},"project-layout",[62],{"type":15,"value":63},"Project layout",{"type":9,"tag":65,"props":66,"children":70},"pre",{"className":67,"code":69,"filename":-1,"highlights":-1,"language":15,"meta":-1},[68],"language-text","your-site\u002F\n├── build.gradle.kts\n├── src\u002Fmain\u002Fbml\u002F\n│   ├── components\u002F         # reusable \u003Ccomponent> declarations\n│   └── home.bml            # a \u003Cpage route=\"\u002F\"> with its document skeleton\n└── src\u002Fmain\u002Fgraphql\u002F       # GraphQL operations (optional)\n",[71],{"type":9,"tag":32,"props":72,"children":73},{"__ignoreMap":34},[74],{"type":15,"value":69},{"type":9,"tag":58,"props":76,"children":78},{"id":77},"apply-the-gradle-plugin",[79],{"type":15,"value":80},"Apply the Gradle plugin",{"type":9,"tag":65,"props":82,"children":87},{"className":83,"code":85,"filename":-1,"highlights":-1,"language":86,"meta":34},[84],"language-kotlin","plugins {\n    kotlin(\"jvm\")\n    id(\"io.bosca.bml\")\n}\n\nbml {\n    sourceDir.set(layout.projectDirectory.dir(\"src\u002Fmain\u002Fbml\"))\n    packageName.set(\"mysite.generated\")\n}\n\ndependencies {\n    implementation(\"io.bosca:core-bml\")   \u002F\u002F render runtime + GraphQL client\n}\n","kotlin",[88],{"type":9,"tag":32,"props":89,"children":90},{"__ignoreMap":34},[91],{"type":15,"value":85},{"type":9,"tag":58,"props":93,"children":95},{"id":94},"how-a-build-works",[96],{"type":15,"value":97},"How a build works",{"type":9,"tag":99,"props":100,"children":101},"ol",{},[102,122,134],{"type":9,"tag":103,"props":104,"children":105},"li",{},[106,114,116,120],{"type":9,"tag":24,"props":107,"children":108},{},[109],{"type":9,"tag":32,"props":110,"children":111},{"className":34},[112],{"type":15,"value":113},"compileKotlin",{"type":15,"value":115}," treats ",{"type":9,"tag":32,"props":117,"children":118},{"className":34},[119],{"type":15,"value":37},{"type":15,"value":121}," files as compilation sources. The BML K2 compiler plugin parses\nthem and contributes generated Kotlin render objects directly to the compilation in memory.",{"type":9,"tag":103,"props":123,"children":124},{},[125,127,132],{"type":15,"value":126},"The same compilation writes generated client TypeScript, message resources, and metrics inputs\nunder ",{"type":9,"tag":32,"props":128,"children":129},{"className":34},[130],{"type":15,"value":131},"build\u002Fgenerated\u002Fbml\u002F",{"type":15,"value":133}," when the source uses those features.",{"type":9,"tag":103,"props":135,"children":136},{},[137,139,144,146,151,153,158,160,165,167,172],{"type":15,"value":138},"Each generated page implements ",{"type":9,"tag":32,"props":140,"children":141},{"className":34},[142],{"type":15,"value":143},"BmlPageRenderer",{"type":15,"value":145}," and is annotated ",{"type":9,"tag":32,"props":147,"children":148},{"className":34},[149],{"type":15,"value":150},"@BmlPage(route = \"…\")",{"type":15,"value":152},".\nSet ",{"type":9,"tag":32,"props":154,"children":155},{"className":34},[156],{"type":15,"value":157},"bml { generateKotlinSources = true }",{"type":15,"value":159}," to mirror generated ",{"type":9,"tag":32,"props":161,"children":162},{"className":34},[163],{"type":15,"value":164},".kt",{"type":15,"value":166}," and source-map files into\n",{"type":9,"tag":32,"props":168,"children":169},{"className":34},[170],{"type":15,"value":171},"build\u002Fgenerated\u002Fbml\u002Fkotlin",{"type":15,"value":173}," for inspection and debugging; those files are not compile inputs.",{"type":9,"tag":18,"props":175,"children":176},{},[177,179,184,186,191,193,198,200,205,207,212,214,219,221,225,227,232,234,239,241,246,248,253],{"type":15,"value":178},"Server code sees the render's ",{"type":9,"tag":32,"props":180,"children":181},{"className":34},[182],{"type":15,"value":183},"RenderContext",{"type":15,"value":185}," two ways: as the ",{"type":9,"tag":32,"props":187,"children":188},{"className":34},[189],{"type":15,"value":190},"ctx",{"type":15,"value":192}," value in scope inside\n",{"type":9,"tag":32,"props":194,"children":195},{"className":34},[196],{"type":15,"value":197},"\u003Cscript server>",{"type":15,"value":199}," \u002F ",{"type":9,"tag":32,"props":201,"children":202},{"className":34},[203],{"type":15,"value":204},"@click",{"type":15,"value":206}," expressions, and ",{"type":9,"tag":24,"props":208,"children":209},{},[210],{"type":15,"value":211},"ambiently",{"type":15,"value":213}," via\n",{"type":9,"tag":32,"props":215,"children":216},{"className":34},[217],{"type":15,"value":218},"bosca.bml.render.currentRenderContext()",{"type":15,"value":220}," — the server installs it on the coroutine context\naround every render and action, so site Kotlin arbitrarily deep in the call stack can read it\nwithout threading a ",{"type":9,"tag":32,"props":222,"children":223},{"className":34},[224],{"type":15,"value":190},{"type":15,"value":226}," parameter. The GraphQL data-plane client has its own shorthand,\n",{"type":9,"tag":32,"props":228,"children":229},{"className":34},[230],{"type":15,"value":231},"bosca.bml.render.client()",{"type":15,"value":233}," (",{"type":9,"tag":32,"props":235,"children":236},{"className":34},[237],{"type":15,"value":238},"currentRenderContext().gql",{"type":15,"value":240},"), and is ",{"type":9,"tag":24,"props":242,"children":243},{},[244],{"type":15,"value":245},"never null",{"type":15,"value":247},": with no\nendpoint configured, executing it fails fast with a message naming the fix, so loaders guard on\nreal conditions (sign-in, visibility) instead of null-checking. Code invoking a renderer\ndirectly (tests, custom hosts) wraps with ",{"type":9,"tag":32,"props":249,"children":250},{"className":34},[251],{"type":15,"value":252},"withRenderContext(ctx) { … }",{"type":15,"value":254},".",{"type":9,"tag":58,"props":256,"children":258},{"id":257},"write-a-page",[259],{"type":15,"value":260},"Write a page",{"type":9,"tag":65,"props":262,"children":267},{"className":263,"code":265,"filename":-1,"highlights":-1,"language":266,"meta":34},[264],"language-bml","\u003Cpage route=\"\u002F\">\n  \u003Chtml lang=\"en\">\n    \u003Chead>\u003Ctitle>Home\u003C\u002Ftitle>\u003C\u002Fhead>\n    \u003Cbody>\n      \u003Cscript server provides=\"greeting\">\"Hello, world\"\u003C\u002Fscript>\n      \u003Ch1>{ greeting }\u003C\u002Fh1>\n    \u003C\u002Fbody>\n  \u003C\u002Fhtml>\n\u003C\u002Fpage>\n","bml",[268],{"type":9,"tag":32,"props":269,"children":270},{"__ignoreMap":34},[271],{"type":15,"value":265},{"type":9,"tag":18,"props":273,"children":274},{},[275,280,282,287,289,295,297,302],{"type":9,"tag":32,"props":276,"children":277},{"className":34},[278],{"type":15,"value":279},"\u003Cscript server provides=\"greeting\">",{"type":15,"value":281}," binds its last expression into the page scope;\n",{"type":9,"tag":32,"props":283,"children":284},{"className":34},[285],{"type":15,"value":286},"{ greeting }",{"type":15,"value":288}," writes it (HTML-escaped). See the ",{"type":9,"tag":41,"props":290,"children":292},{"href":291},"\u002Fbml-reference\u002Ftag-reference",[293],{"type":15,"value":294},"tag reference",{"type":15,"value":296},".\nPages currently own their complete document skeleton. Template and ",{"type":9,"tag":32,"props":298,"children":299},{"className":34},[300],{"type":15,"value":301},"layout=",{"type":15,"value":303}," syntax is reserved but\ndoes not wrap page output.",{"type":9,"tag":18,"props":305,"children":306},{},[307],{"type":15,"value":308},"Host-provided dependencies use an explicit name and type and stay private to their enclosing\npage\u002Fcomponent\u002Fmessage render:",{"type":9,"tag":65,"props":310,"children":313},{"className":311,"code":312,"filename":-1,"highlights":-1,"language":266,"meta":34},[264],"\u003Cinject name=\"search\" type=\"com.example.SearchService\" init=\"load\" \u002F>\n",[314],{"type":9,"tag":32,"props":315,"children":316},{"__ignoreMap":34},[317],{"type":15,"value":312},{"type":9,"tag":18,"props":319,"children":320},{},[321,323,328,330,335,337,342,344,349,351,356],{"type":15,"value":322},"The generated renderer calls ",{"type":9,"tag":32,"props":324,"children":325},{"className":34},[326],{"type":15,"value":327},"bosca.di.provide\u003Ccom.example.SearchService>()",{"type":15,"value":329},", binds the result as\n",{"type":9,"tag":32,"props":331,"children":332},{"className":34},[333],{"type":15,"value":334},"search",{"type":15,"value":336},", and calls ",{"type":9,"tag":32,"props":338,"children":339},{"className":34},[340],{"type":15,"value":341},"search.load()",{"type":15,"value":343},". Omit ",{"type":9,"tag":32,"props":345,"children":346},{"className":34},[347],{"type":15,"value":348},"init",{"type":15,"value":350}," for lookup only, or add ",{"type":9,"tag":32,"props":352,"children":353},{"className":34},[354],{"type":15,"value":355},"provider=\"key\"",{"type":15,"value":357}," to select a\nnamed Bosca DI binding.",{"type":9,"tag":18,"props":359,"children":360},{},[361,363,368,370,375,377,382],{"type":15,"value":362},"If the injected value is an ",{"type":9,"tag":32,"props":364,"children":365},{"className":34},[366],{"type":15,"value":367},"@Serializable",{"type":15,"value":369}," view model, add the bare ",{"type":9,"tag":32,"props":371,"children":372},{"className":34},[373],{"type":15,"value":374},"server",{"type":15,"value":376}," marker to use it as\nlive state exactly like a constructor-typed ",{"type":9,"tag":32,"props":378,"children":379},{"className":34},[380],{"type":15,"value":381},"\u003Cscript server provides=\"…\">",{"type":15,"value":383},":",{"type":9,"tag":65,"props":385,"children":388},{"className":386,"code":387,"filename":-1,"highlights":-1,"language":266,"meta":34},[264],"\u003Cinject server name=\"headerAuth\" type=\"com.example.HeaderAuthViewModel\" \u002F>\n\u003Cisland name=\"header-auth\">\n  \u003Cspan>{ headerAuth.displayName }\u003C\u002Fspan>\n\u003C\u002Fisland>\n\u003Cbutton @click=\"headerAuth.signOut\">Sign out\u003C\u002Fbutton>\n",[389],{"type":9,"tag":32,"props":390,"children":391},{"__ignoreMap":34},[392],{"type":15,"value":387},{"type":9,"tag":18,"props":394,"children":395},{},[396,398,403,405,410,412,417,419,424,426,431,433,438,440,445,447,452,454,459,461,465,467,472,474,479],{"type":15,"value":397},"BML serializes ",{"type":9,"tag":32,"props":399,"children":400},{"className":34},[401],{"type":15,"value":402},"headerAuth",{"type":15,"value":404}," for the page, decodes it when the action is posted, runs ",{"type":9,"tag":32,"props":406,"children":407},{"className":34},[408],{"type":15,"value":409},"signOut()",{"type":15,"value":411}," on\nthe server, and re-renders the island. Add ",{"type":9,"tag":32,"props":413,"children":414},{"className":34},[415],{"type":15,"value":416},"scope=\"client-session\"",{"type":15,"value":418},", ",{"type":9,"tag":32,"props":420,"children":421},{"className":34},[422],{"type":15,"value":423},"scope=\"client-local\"",{"type":15,"value":425},", or\n",{"type":9,"tag":32,"props":427,"children":428},{"className":34},[429],{"type":15,"value":430},"scope=\"server-session\"",{"type":15,"value":432}," when the default page lifetime is not appropriate. ",{"type":9,"tag":32,"props":434,"children":435},{"className":34},[436],{"type":15,"value":437},"client-local",{"type":15,"value":439}," uses\nbrowser ",{"type":9,"tag":32,"props":441,"children":442},{"className":34},[443],{"type":15,"value":444},"localStorage",{"type":15,"value":446},", survives browser restarts, and must not hold secrets or sensitive user data.\nAdd the bare ",{"type":9,"tag":32,"props":448,"children":449},{"className":34},[450],{"type":15,"value":451},"clear-on-sign-out",{"type":15,"value":453}," marker only when that browser-backed model belongs to the signed-in\nidentity and should be removed when ",{"type":9,"tag":32,"props":455,"children":456},{"className":34},[457],{"type":15,"value":458},"clearBmlClientState()",{"type":15,"value":460}," handles an explicit identity change.\nCleanup clears marked browser state without disturbing unmarked browser state, replaces the opaque\nserver session on the next stateful render, and reloads by default so server-rendered shell inputs are\nrecomputed for the new identity. After an explicit sign-out completes, use\n",{"type":9,"tag":32,"props":462,"children":463},{"className":34},[464],{"type":15,"value":458},{"type":15,"value":466}," to obtain one fresh signed-out render; do not attach cleanup\ndirectly to the auth client's broader ",{"type":9,"tag":32,"props":468,"children":469},{"className":34},[470],{"type":15,"value":471},"signedOut",{"type":15,"value":473}," event.\nFor a component model intentionally shared across routes, declare ",{"type":9,"tag":32,"props":475,"children":476},{"className":34},[477],{"type":15,"value":478},"\u003Ccomponent scope=\"site\">",{"type":15,"value":480},"; this\nkeeps the model component-owned while giving its durable state one cross-page identity.",{"type":9,"tag":58,"props":482,"children":484},{"id":483},"serve-it",[485],{"type":15,"value":486},"Serve it",{"type":9,"tag":18,"props":488,"children":489},{},[490,492,497,499,503,505,509,511,516],{"type":15,"value":491},"Embed ",{"type":9,"tag":32,"props":493,"children":494},{"className":34},[495],{"type":15,"value":496},"bml-server",{"type":15,"value":498},": pass the generated pages (each implements ",{"type":9,"tag":32,"props":500,"children":501},{"className":34},[502],{"type":15,"value":143},{"type":15,"value":504},") and start the\nserver. ",{"type":9,"tag":32,"props":506,"children":507},{"className":34},[508],{"type":15,"value":496},{"type":15,"value":510}," registers them directly on Bosca Server's router — Bosca does the routing,\nincluding ",{"type":9,"tag":32,"props":512,"children":513},{"className":34},[514],{"type":15,"value":515},"{param}",{"type":15,"value":517}," patterns; the server threads path params + the request token into the render.",{"type":9,"tag":65,"props":519,"children":522},{"className":520,"code":521,"filename":-1,"highlights":-1,"language":86,"meta":34},[84],"import bosca.bml.project.CompiledProject\nimport bosca.bml.server.BmlServer\n\nfun main() {\n    val pages = listOf(mysite.generated.HomePage)   \u002F\u002F generated objects implement BmlPageRenderer\n    BmlServer(\n        CompiledProject(\"my-site\", \"1.0.0\"),\n        pages,\n        port = 8080,\n        graphqlEndpoint = \"http:\u002F\u002Flocalhost:8080\u002Fgraphql\",\n        installationEndpoint = \"http:\u002F\u002Flocalhost:8081\u002Fapi\u002Fv1\u002Finstallation\",\n    ).start()\n}\n",[523],{"type":9,"tag":32,"props":524,"children":525},{"__ignoreMap":34},[526],{"type":15,"value":521},{"type":9,"tag":18,"props":528,"children":529},{},[530,535,537,542,544,548,550,555],{"type":9,"tag":32,"props":531,"children":532},{"className":34},[533],{"type":15,"value":534},"installationEndpoint",{"type":15,"value":536}," is the analytics collector's full installation-registration URL; it is\nnot derived from ",{"type":9,"tag":32,"props":538,"children":539},{"className":34},[540],{"type":15,"value":541},"graphqlEndpoint",{"type":15,"value":543},". If the constructor argument is omitted, ",{"type":9,"tag":32,"props":545,"children":546},{"className":34},[547],{"type":15,"value":496},{"type":15,"value":549}," reads\n",{"type":9,"tag":32,"props":551,"children":552},{"className":34},[553],{"type":15,"value":554},"BML_INSTALLATION_ENDPOINT",{"type":15,"value":556},". Leave both unset when the site does not use installation identity.",{"type":9,"tag":58,"props":558,"children":560},{"id":559},"develop-with-hot-reload",[561],{"type":15,"value":562},"Develop with hot reload",{"type":9,"tag":18,"props":564,"children":565},{},[566,568,573,575,580],{"type":15,"value":567},"The BML Gradle plugin adds ",{"type":9,"tag":32,"props":569,"children":570},{"className":34},[571],{"type":15,"value":572},"bmlDev",{"type":15,"value":574}," to projects that also apply Gradle's ",{"type":9,"tag":32,"props":576,"children":577},{"className":34},[578],{"type":15,"value":579},"application",{"type":15,"value":581},"\nplugin:",{"type":9,"tag":65,"props":583,"children":588},{"className":584,"code":586,"filename":-1,"highlights":-1,"language":587,"meta":34},[585],"language-bash",".\u002Fgradlew bmlDev\n","bash",[589],{"type":9,"tag":32,"props":590,"children":591},{"__ignoreMap":34},[592],{"type":15,"value":586},{"type":9,"tag":18,"props":594,"children":595},{},[596,600,602,607],{"type":9,"tag":32,"props":597,"children":598},{"className":34},[599],{"type":15,"value":572},{"type":15,"value":601}," builds the application and client bundles, starts its configured main class in BML\ndevelopment mode, and then lets Gradle watch the real inputs of that task graph. An edit to BML,\nKotlin, GraphQL, resources, client TypeScript\u002FCSS, or a configured local client runtime triggers an\nincremental rebuild. After a successful build, Gradle snapshots the application classes and\nresources and the persistent launcher loads them in a fresh child classloader. The new ",{"type":9,"tag":32,"props":603,"children":604},{"className":34},[605],{"type":15,"value":606},"BmlServer",{"type":15,"value":608},"\nconfiguration atomically replaces the current page\u002Fcomponent\u002Fcontract state; Netty keeps the same\nPID and port, and server-scoped sessions remain intact. The server announces the new generation over\nSSE so open browser tabs reload themselves. A compilation failure leaves the last good generation\nserving while Gradle keeps watching; fixing the source swaps the next successful generation in.",{"type":9,"tag":18,"props":610,"children":611},{},[612,614,618],{"type":15,"value":613},"The hot-swap boundary is the application output: BML-generated code, project Kotlin, generated\nGraphQL code, and project resources. Client bundles are rebuilt and served from their live output\ndirectory. Changes to BML framework or other runtime dependency jars require stopping and starting\n",{"type":9,"tag":32,"props":615,"children":616},{"className":34},[617],{"type":15,"value":572},{"type":15,"value":619},", because those libraries intentionally stay in the parent classloader.",{"type":9,"tag":18,"props":621,"children":622},{},[623,625,630,632,636,638,643,645,650],{"type":15,"value":624},"In IntelliJ, run ",{"type":9,"tag":24,"props":626,"children":627},{},[628],{"type":15,"value":629},"Tasks → bml → bmlDev",{"type":15,"value":631}," from the Gradle tool window (or create a Gradle run\nconfiguration for the ",{"type":9,"tag":32,"props":633,"children":634},{"className":34},[635],{"type":15,"value":572},{"type":15,"value":637}," task). The task enters Gradle's reloadable-deployment mode itself;\nno ",{"type":9,"tag":32,"props":639,"children":640},{"className":34},[641],{"type":15,"value":642},"--continuous",{"type":15,"value":644}," flag or separate ",{"type":9,"tag":32,"props":646,"children":647},{"className":34},[648],{"type":15,"value":649},"bosca",{"type":15,"value":651}," CLI process is required after a successful initial\nbuild. Stopping the IntelliJ run configuration stops both the Gradle watch and the managed server\nJVM.",{"type":9,"tag":18,"props":653,"children":654},{},[655,657,662,664,668],{"type":15,"value":656},"The ordinary ",{"type":9,"tag":32,"props":658,"children":659},{"className":34},[660],{"type":15,"value":661},"run",{"type":15,"value":663}," task remains useful for one compile-and-run cycle. The BML plugin enables its\ndevelopment-mode SSE and current client-bundle directory automatically, but ",{"type":9,"tag":32,"props":665,"children":666},{"className":34},[667],{"type":15,"value":661},{"type":15,"value":669}," alone does not\nwatch sources or hot-swap application classes.",{"type":9,"tag":58,"props":671,"children":673},{"id":672},"cli",[674],{"type":15,"value":675},"CLI",{"type":9,"tag":18,"props":677,"children":678},{},[679,681,685],{"type":15,"value":680},"The ",{"type":9,"tag":32,"props":682,"children":683},{"className":34},[684],{"type":15,"value":649},{"type":15,"value":686}," CLI scaffolds and compiles BML projects (BML-REQ-19\u002F20):",{"type":9,"tag":65,"props":688,"children":691},{"className":689,"code":690,"filename":-1,"highlights":-1,"language":587,"meta":34},[585],"bosca bml init my-site          # scaffold a project\nbosca bml compile my-site       # generate .kt once (.bml → build\u002Fgenerated\u002Fbml\u002Fkotlin)\nbosca bml dev my-site           # delegate to .\u002Fgradlew bmlDev\n",[692],{"type":9,"tag":32,"props":693,"children":694},{"__ignoreMap":34},[695],{"type":15,"value":690},{"type":9,"tag":18,"props":697,"children":698},{},[699,704,706,711,713,718,720,724,726,731],{"type":9,"tag":32,"props":700,"children":701},{"className":34},[702],{"type":15,"value":703},"bosca bml dev",{"type":15,"value":705}," delegates directly to the project's wrapper (or ",{"type":9,"tag":32,"props":707,"children":708},{"className":34},[709],{"type":15,"value":710},"gradle",{"type":15,"value":712}," on ",{"type":9,"tag":32,"props":714,"children":715},{"className":34},[716],{"type":15,"value":717},"PATH",{"type":15,"value":719}," when there is\nno wrapper) and its ",{"type":9,"tag":32,"props":721,"children":722},{"className":34},[723],{"type":15,"value":572},{"type":15,"value":725}," task. Gradle therefore owns the same incremental compile, bundle,\npersistent server JVM, child-classloader swap, and browser reload lifecycle used from IntelliJ.\nUse ",{"type":9,"tag":32,"props":727,"children":728},{"className":34},[729],{"type":15,"value":730},"--gradle-task",{"type":15,"value":732}," when the project exposes that lifecycle under a custom task path.",{"type":9,"tag":18,"props":734,"children":735},{},[736,738,743],{"type":15,"value":737},"For one-shot source generation without an application lifecycle, use ",{"type":9,"tag":32,"props":739,"children":740},{"className":34},[741],{"type":15,"value":742},"bosca bml compile",{"type":15,"value":254},{"type":9,"tag":58,"props":745,"children":747},{"id":746},"data-via-graphql",[748],{"type":15,"value":749},"Data via GraphQL",{"type":9,"tag":18,"props":751,"children":752},{},[753,755,760,762,766,768,773,775,780,782,787,789,794,796,801],{"type":15,"value":754},"All data is fetched through the ",{"type":9,"tag":24,"props":756,"children":757},{},[758],{"type":15,"value":759},"Bosca GraphQL API",{"type":15,"value":761}," — never direct Bosca services.\nThe endpoint is configurable and the caller's token is forwarded (passthrough), so\nlocal dev can point at a remote Bosca and the same code runs unchanged once deployed.\nIn a ",{"type":9,"tag":32,"props":763,"children":764},{"className":34},[765],{"type":15,"value":197},{"type":15,"value":767}," use the in-scope GraphQL client; islands call it client-side too.\nWhen both ",{"type":9,"tag":32,"props":769,"children":770},{"className":34},[771],{"type":15,"value":772},"io.bosca.bml",{"type":15,"value":774}," and ",{"type":9,"tag":32,"props":776,"children":777},{"className":34},[778],{"type":15,"value":779},"io.bosca.graphql",{"type":15,"value":781}," are applied, the build generates Kotlin operations\nand browser TypeScript operations from the same ",{"type":9,"tag":32,"props":783,"children":784},{"className":34},[785],{"type":15,"value":786},"src\u002Fmain\u002Fgraphql",{"type":15,"value":788}," documents. Client modules import\ntyped functions from ",{"type":9,"tag":32,"props":790,"children":791},{"className":34},[792],{"type":15,"value":793},".\u002Fgraphql\u002F\u003COperationName>",{"type":15,"value":795},"; ",{"type":9,"tag":32,"props":797,"children":798},{"className":34},[799],{"type":15,"value":800},"bmlBundleClient",{"type":15,"value":802}," orders generation before esbuild.",{"type":9,"tag":58,"props":804,"children":806},{"id":805},"feature-flags",[807],{"type":15,"value":808},"Feature flags",{"type":9,"tag":18,"props":810,"children":811},{},[812],{"type":15,"value":813},"Feature flags are evaluated through Bosca's GraphQL API and can be used directly as BML control flow:",{"type":9,"tag":65,"props":815,"children":818},{"className":816,"code":817,"filename":-1,"highlights":-1,"language":266,"meta":34},[264],"\u003Cif flag=\"new-checkout\">\n  \u003Ccheckout-v2\u002F>\n\u003Celse-if flag=\"checkout-layout\" variation=\"compact\">\n  \u003Ccompact-checkout\u002F>\n\u003Celse-if flag=\"checkout\" :when='flag.value is kotlinx.serialization.json.JsonObject && !flag.degraded'>\n  \u003Cconfigured-checkout\u002F>\n\u003Celse>\n  \u003Ccheckout-v1\u002F>\n\u003C\u002Fif>\n",[819],{"type":9,"tag":32,"props":820,"children":821},{"__ignoreMap":34},[822],{"type":15,"value":817},{"type":9,"tag":18,"props":824,"children":825},{},[826,828,833,835,840,842,847,849,854],{"type":15,"value":827},"The boolean and variation forms cover common cases. ",{"type":9,"tag":32,"props":829,"children":830},{"className":34},[831],{"type":15,"value":832},":when",{"type":15,"value":834}," accepts Kotlin and binds ",{"type":9,"tag":32,"props":836,"children":837},{"className":34},[838],{"type":15,"value":839},"flag",{"type":15,"value":841}," to the\ncomplete ",{"type":9,"tag":32,"props":843,"children":844},{"className":34},[845],{"type":15,"value":846},"FeatureFlagEvaluation",{"type":15,"value":848},", so it can inspect structured ",{"type":9,"tag":32,"props":850,"children":851},{"className":34},[852],{"type":15,"value":853},"value",{"type":15,"value":855}," data or targeting metadata.\nServer scripts and site Kotlin can use the same facade directly:",{"type":9,"tag":65,"props":857,"children":860},{"className":858,"code":859,"filename":-1,"highlights":-1,"language":86,"meta":34},[84],"val flags = bosca.bml.render.currentRenderContext().featureFlags\nval evaluation = flags.evaluate(\"checkout\")\nval enabled = flags.enabled(\"new-checkout\")\n",[861],{"type":9,"tag":32,"props":862,"children":863},{"__ignoreMap":34},[864],{"type":15,"value":859},{"type":9,"tag":18,"props":866,"children":867},{},[868,870,875,876,881,882,887,888,893,895,899,901,906],{"type":15,"value":869},"The facade also provides ",{"type":9,"tag":32,"props":871,"children":872},{"className":34},[873],{"type":15,"value":874},"evaluateAll",{"type":15,"value":418},{"type":9,"tag":32,"props":877,"children":878},{"className":34},[879],{"type":15,"value":880},"variation",{"type":15,"value":418},{"type":9,"tag":32,"props":883,"children":884},{"className":34},[885],{"type":15,"value":886},"string",{"type":15,"value":418},{"type":9,"tag":32,"props":889,"children":890},{"className":34},[891],{"type":15,"value":892},"number",{"type":15,"value":894},", and raw ",{"type":9,"tag":32,"props":896,"children":897},{"className":34},[898],{"type":15,"value":853},{"type":15,"value":900}," helpers.\nResults are cached for the current render. BML Server obtains a stable anonymous installation id\nfrom Bosca and stores it in the browser-readable ",{"type":9,"tag":32,"props":902,"children":903},{"className":34},[904],{"type":15,"value":905},"bml_iid",{"type":15,"value":907}," first-party cookie; authenticated\nrequests still carry their normal token, allowing Bosca to resolve the principal.",{"type":9,"tag":18,"props":909,"children":910},{},[911,913,918],{"type":15,"value":912},"Feature evaluation is fail-closed: an unavailable flag request is logged and becomes a degraded,\nunknown evaluation with a blank variation key and JSON ",{"type":9,"tag":32,"props":914,"children":915},{"className":34},[916],{"type":15,"value":917},"null",{"type":15,"value":919}," value, so boolean and variation\nconditions select their ordinary fallback branch instead of preventing the page from rendering.\nExplicit helper defaults are honored as usual.",{"type":9,"tag":18,"props":921,"children":922},{},[923,925,930,932,937],{"type":15,"value":924},"Client islands use the site's existing configured ",{"type":9,"tag":32,"props":926,"children":927},{"className":34},[928],{"type":15,"value":929},"FeatureFlagClient",{"type":15,"value":931}," from\n",{"type":9,"tag":32,"props":933,"children":934},{"className":34},[935],{"type":15,"value":936},"@bosca\u002Fanalytics-client-browser\u002Fcore",{"type":15,"value":938},". BML does not create a second browser feature client.",{"type":9,"tag":18,"props":940,"children":941},{},[942,944,948,950,955,957,962],{"type":15,"value":943},"The Bosca-issued ",{"type":9,"tag":32,"props":945,"children":946},{"className":34},[947],{"type":15,"value":905},{"type":15,"value":949}," cookie is available before response scripts run and is canonical because\nthe page's variation has already been selected with it. Bosca analytics reads that cookie first, so\nanonymous conversion events join the same assignment. Outside BML, analytics retains its existing\n",{"type":9,"tag":32,"props":951,"children":952},{"className":34},[953],{"type":15,"value":954},"__iid",{"type":15,"value":956}," storage and registration behavior and writes newly registered IDs to the same cookie.\nAuthenticated sites use the analytics client's normal ",{"type":9,"tag":32,"props":958,"children":959},{"className":34},[960],{"type":15,"value":961},"BoscaSink.setUserId(principalId)",{"type":15,"value":963}," integration;\nfeature flags add no second user-identity mechanism.",{"type":9,"tag":18,"props":965,"children":966},{},[967],{"type":15,"value":968},"Flag values are not copied into every analytics event. Bosca records the variation assignment when\nthe flag is evaluated, and analytics events carry the stable principal or installation join key.\nThis keeps event payloads bounded while preserving variation attribution during aggregation.",{"type":9,"tag":18,"props":970,"children":971},{},[972,974,979],{"type":15,"value":973},"Feature-flag conditions are unavailable in ",{"type":9,"tag":32,"props":975,"children":976},{"className":34},[977],{"type":15,"value":978},"\u003Cmessage>",{"type":15,"value":980}," renders because messages currently have no\nrecipient feature identity. BML rejects direct message conditions; a separately compiled component\nthat attempts an evaluation receives the same degraded, unknown fallback used for other unavailable\nfeature evaluations, avoiding assignments to the message producer instead.",{"type":9,"tag":58,"props":982,"children":984},{"id":983},"locales-bml-spec-3",[985],{"type":15,"value":986},"Locales (BML-SPEC-3)",{"type":9,"tag":18,"props":988,"children":989},{},[990,995,997,1002,1004,1009,1011,1016,1018,1023,1025,1030,1032,1037,1039,1044,1046,1051,1053,1058],{"type":9,"tag":24,"props":991,"children":992},{},[993],{"type":15,"value":994},"The site's Bosca localization project defines its locales",{"type":15,"value":996}," — the project's source language is\nthe default and its declared target languages are the rest, so the site and its translators can\nnever drift apart, and adding a language in Bosca reaches the site without a redeploy. Every\nrequest then negotiates its locale: an explicit ",{"type":9,"tag":32,"props":998,"children":999},{"className":34},[1000],{"type":15,"value":1001},"?lang",{"type":15,"value":1003}," override, else the site-managed\n",{"type":9,"tag":32,"props":1005,"children":1006},{"className":34},[1007],{"type":15,"value":1008},"bml_locale",{"type":15,"value":1010}," cookie, else full ",{"type":9,"tag":32,"props":1012,"children":1013},{"className":34},[1014],{"type":15,"value":1015},"Accept-Language",{"type":15,"value":1017}," negotiation (RFC 4647 — q-weights, ",{"type":9,"tag":32,"props":1019,"children":1020},{"className":34},[1021],{"type":15,"value":1022},"en;q=0",{"type":15,"value":1024},"\nexclusions, ",{"type":9,"tag":32,"props":1026,"children":1027},{"className":34},[1028],{"type":15,"value":1029},"es-MX",{"type":15,"value":1031}," → ",{"type":9,"tag":32,"props":1033,"children":1034},{"className":34},[1035],{"type":15,"value":1036},"es",{"type":15,"value":1038}," truncation, broad ",{"type":9,"tag":32,"props":1040,"children":1041},{"className":34},[1042],{"type":15,"value":1043},"pt",{"type":15,"value":1045}," served by a ",{"type":9,"tag":32,"props":1047,"children":1048},{"className":34},[1049],{"type":15,"value":1050},"pt-BR",{"type":15,"value":1052},"-only site), always\nconstrained to the project's list. A site with no localization project is single-locale ",{"type":9,"tag":32,"props":1054,"children":1055},{"className":34},[1056],{"type":15,"value":1057},"en",{"type":15,"value":1059},"\nand negotiation is inert.",{"type":9,"tag":18,"props":1061,"children":1062},{},[1063,1065,1070,1072,1077,1079,1084,1086,1091,1093,1098],{"type":15,"value":1064},"The result is ",{"type":9,"tag":32,"props":1066,"children":1067},{"className":34},[1068],{"type":15,"value":1069},"ctx.locale",{"type":15,"value":1071}," (a ",{"type":9,"tag":32,"props":1073,"children":1074},{"className":34},[1075],{"type":15,"value":1076},"java.util.Locale",{"type":15,"value":1078}," — feed it to formatters) with the BCP-47 tag as\n",{"type":9,"tag":32,"props":1080,"children":1081},{"className":34},[1082],{"type":15,"value":1083},"ctx.lang",{"type":15,"value":1085},"; deep site code reads it ambiently via ",{"type":9,"tag":32,"props":1087,"children":1088},{"className":34},[1089],{"type":15,"value":1090},"currentLocale()",{"type":15,"value":1092},". Pages own their ",{"type":9,"tag":32,"props":1094,"children":1095},{"className":34},[1096],{"type":15,"value":1097},"\u003Chtml>",{"type":15,"value":1099},"\nskeleton, so set the document language from it:",{"type":9,"tag":65,"props":1101,"children":1106},{"className":1102,"code":1104,"filename":-1,"highlights":-1,"language":1105,"meta":34},[1103],"language-html","\u003Chtml lang=\"{ ctx.lang }\">\n","html",[1107],{"type":9,"tag":32,"props":1108,"children":1109},{"__ignoreMap":34},[1110],{"type":15,"value":1104},{"type":9,"tag":18,"props":1112,"children":1113},{},[1114,1116,1120,1122,1127],{"type":15,"value":1115},"A locale-switcher is site code, not framework code: set the ",{"type":9,"tag":32,"props":1117,"children":1118},{"className":34},[1119],{"type":15,"value":1008},{"type":15,"value":1121}," cookie from client JS\n(like ",{"type":9,"tag":32,"props":1123,"children":1124},{"className":34},[1125],{"type":15,"value":1126},"bml_token",{"type":15,"value":1128},") and reload. Language direction for RTL locales can be derived from the\nplatform language registry's attributes when a site needs it.",{"type":9,"tag":1130,"props":1131,"children":1133},"h3",{"id":1132},"localized-strings",[1134],{"type":15,"value":1135},"Localized strings",{"type":9,"tag":18,"props":1137,"children":1138},{},[1139,1141,1146,1148,1153,1155,1160],{"type":15,"value":1140},"Bind the site to its localization project and every ",{"type":9,"tag":32,"props":1142,"children":1143},{"className":34},[1144],{"type":15,"value":1145},"t",{"type":15,"value":1147},"\u002F",{"type":9,"tag":32,"props":1149,"children":1150},{"className":34},[1151],{"type":15,"value":1152},"t:",{"type":15,"value":1154}," lookup renders that project's\n",{"type":9,"tag":32,"props":1156,"children":1157},{"className":34},[1158],{"type":15,"value":1159},"PUBLISHED",{"type":15,"value":1161}," translations (see grammar.md §8.1 for the authoring syntax):",{"type":9,"tag":65,"props":1163,"children":1166},{"className":1164,"code":1165,"filename":-1,"highlights":-1,"language":587,"meta":34},[585],"BML_LOCALIZATION_PROJECT=acme-site        # project name or UUID — also defines the locales\nBML_LOCALIZATION_TOKEN=\u003Cservice token>    # catalog reads are server-initiated\nBML_LOCALIZATION_TTL_SECONDS=300          # refresh cadence (0 = every read, for dev)\nBML_LOCALIZATION_STATES=PUBLISHED         # widen (e.g. +IN_REVIEW) for preview environments\n",[1167],{"type":9,"tag":32,"props":1168,"children":1169},{"__ignoreMap":34},[1170],{"type":15,"value":1165},{"type":9,"tag":18,"props":1172,"children":1173},{},[1174,1176,1181,1183,1188,1189,1194,1196,1201,1203,1208,1210,1215,1217,1222],{"type":15,"value":1175},"Catalogs cache in-process with stale-while-revalidate; an unreachable Bosca degrades to the\nauthored fallbacks, never a failed page. Client islands can localize too: ",{"type":9,"tag":32,"props":1177,"children":1178},{"className":34},[1179],{"type":15,"value":1180},"loadMessages()",{"type":15,"value":1182}," +\n",{"type":9,"tag":32,"props":1184,"children":1185},{"className":34},[1186],{"type":15,"value":1187},"t()",{"type":15,"value":30},{"type":9,"tag":32,"props":1190,"children":1191},{"className":34},[1192],{"type":15,"value":1193},"@bosca\u002Fbml",{"type":15,"value":1195}," fetch the merged catalog from ",{"type":9,"tag":32,"props":1197,"children":1198},{"className":34},[1199],{"type":15,"value":1200},"\u002F_bml\u002Fi18n\u002F\u003Clocale>.json",{"type":15,"value":1202}," (zero extra\nbytes for pages that don't use it). Message projects use the same machinery on the message server\n(",{"type":9,"tag":32,"props":1204,"children":1205},{"className":34},[1206],{"type":15,"value":1207},"BML_GRAPHQL_ENDPOINT",{"type":15,"value":1209}," + ",{"type":9,"tag":32,"props":1211,"children":1212},{"className":34},[1213],{"type":15,"value":1214},"BML_MESSAGE_LOCALIZATION_*",{"type":15,"value":1216},"), rendering each message in the recipient's\n",{"type":9,"tag":32,"props":1218,"children":1219},{"className":34},[1220],{"type":15,"value":1221},"bosca.profiles.locale",{"type":15,"value":1223}," setting; Studio's Email Preview has a locale picker.",{"type":9,"tag":18,"props":1225,"children":1226},{},[1227],{"type":15,"value":1228},"The authoring loop: build, then",{"type":9,"tag":65,"props":1230,"children":1233},{"className":1231,"code":1232,"filename":-1,"highlights":-1,"language":587,"meta":34},[585],"bosca bml i18n extract                    # what the compiled project declares\nbosca bml i18n push --project \u003Cuuid>      # create keys + seed source-language text\nbosca bml i18n status --project \u003Cuuid>    # translation coverage per language\n",[1234],{"type":9,"tag":32,"props":1235,"children":1236},{"__ignoreMap":34},[1237],{"type":15,"value":1232},{"type":9,"tag":18,"props":1239,"children":1240},{},[1241,1243,1248],{"type":15,"value":1242},"Native images must bundle locale data (",{"type":9,"tag":32,"props":1244,"children":1245},{"className":34},[1246],{"type":15,"value":1247},"-H:+IncludeAllLocales",{"type":15,"value":1249}," — without it, number\u002Fdate\nformatting silently degrades to root-locale output; see the bml-message-server build file).\nAll locales deliberately: the localization project defines the platform's locales as runtime\ndata, so an enumerated build-time list would silently break any language added after the build.",{"type":9,"tag":58,"props":1251,"children":1253},{"id":1252},"targets",[1254],{"type":15,"value":1255},"Targets",{"type":9,"tag":18,"props":1257,"children":1258},{},[1259],{"type":15,"value":1260},"The same language compiles to four presentation targets (BML-SPEC-1 §8):",{"type":9,"tag":1262,"props":1263,"children":1264},"ul",{},[1265,1275,1292,1308],{"type":9,"tag":103,"props":1266,"children":1267},{},[1268,1273],{"type":9,"tag":24,"props":1269,"children":1270},{},[1271],{"type":15,"value":1272},"web",{"type":15,"value":1274}," — full HTML + islands (default),",{"type":9,"tag":103,"props":1276,"children":1277},{},[1278,1283,1285,1290],{"type":9,"tag":24,"props":1279,"children":1280},{},[1281],{"type":15,"value":1282},"email",{"type":15,"value":1284}," — inlined CSS, table-safe, no JS (",{"type":9,"tag":32,"props":1286,"children":1287},{"className":34},[1288],{"type":15,"value":1289},"EmailRenderer",{"type":15,"value":1291},"),",{"type":9,"tag":103,"props":1293,"children":1294},{},[1295,1300,1302,1307],{"type":9,"tag":24,"props":1296,"children":1297},{},[1298],{"type":15,"value":1299},"plain text",{"type":15,"value":1301}," — a readable text projection (",{"type":9,"tag":32,"props":1303,"children":1304},{"className":34},[1305],{"type":15,"value":1306},"PlainTextRenderer",{"type":15,"value":1291},{"type":9,"tag":103,"props":1309,"children":1310},{},[1311,1316],{"type":9,"tag":24,"props":1312,"children":1313},{},[1314],{"type":15,"value":1315},"push",{"type":15,"value":1317}," — localized title\u002Fbody plus provider-neutral delivery metadata.",{"type":9,"tag":58,"props":1319,"children":1321},{"id":1320},"message-templates-bml-spec-2",[1322],{"type":15,"value":1323},"Message templates (BML-SPEC-2)",{"type":9,"tag":18,"props":1325,"children":1326},{},[1327,1329,1334,1336,1341,1343,1348,1349,1354],{"type":15,"value":1328},"A ",{"type":9,"tag":24,"props":1330,"children":1331},{},[1332],{"type":15,"value":1333},"message project",{"type":15,"value":1335}," authors each communication as a ",{"type":9,"tag":32,"props":1337,"children":1338},{"className":34},[1339],{"type":15,"value":1340},"\u003Cmessage key=\"…\">",{"type":15,"value":1342}," unit. Shared server\nKotlin sits at the message level; sibling ",{"type":9,"tag":32,"props":1344,"children":1345},{"className":34},[1346],{"type":15,"value":1347},"\u003Cemail>",{"type":15,"value":774},{"type":9,"tag":32,"props":1350,"children":1351},{"className":34},[1352],{"type":15,"value":1353},"\u003Cpush>",{"type":15,"value":1355}," regions opt into channels:",{"type":9,"tag":65,"props":1357,"children":1360},{"className":1358,"code":1359,"filename":-1,"highlights":-1,"language":1105,"meta":34},[1103],"\u003Cmessage key=\"welcome\">\n  \u003Cscript server provides=\"m\">message.payload(WelcomePayload.serializer())\u003C\u002Fscript>\n  \u003Cpush>\n    \u003Ctitle t=\"welcome.push.title\">Welcome!\u003C\u002Ftitle>\n    \u003Cbody t=\"welcome.push.body\">Your account is ready.\u003C\u002Fbody>\n    \u003Caction id=\"open\" default t=\"welcome.push.action.open\">Open Bosca\u003C\u002Faction>\n    \u003Cimage\u002F>\n    \u003Cattachments\u002F>\n    \u003Cconversation\u002F>\n  \u003C\u002Fpush>\n  \u003Cemail>\n    \u003Csubject t=\"welcome.subject\">Welcome, { message.recipientName ?: \"friend\" }!\u003C\u002Fsubject>\n    \u003Chtml>\u003Cbody>\u003Ch1>{ m.courseName }\u003C\u002Fh1>\u003C\u002Fbody>\u003C\u002Fhtml>\n  \u003C\u002Femail>\n\u003C\u002Fmessage>\n",[1361],{"type":9,"tag":32,"props":1362,"children":1363},{"__ignoreMap":34},[1364],{"type":15,"value":1359},{"type":9,"tag":18,"props":1366,"children":1367},{},[1368,1370,1375,1377,1382,1384,1389,1391,1396,1398,1403,1404,1409,1411,1416,1418,1423,1425,1430,1432,1437,1439,1444,1446,1451,1453,1458,1460,1465,1467,1472,1473,1478,1480,1485,1487,1492],{"type":15,"value":1369},"The compiler lowers each unit to an object implementing\n",{"type":9,"tag":32,"props":1371,"children":1372},{"className":34},[1373],{"type":15,"value":1374},"bosca.bml.message.BmlMessageTemplate",{"type":15,"value":1376}," — ",{"type":9,"tag":32,"props":1378,"children":1379},{"className":34},[1380],{"type":15,"value":1381},"renderMessage(message: BmlMessageContext)",{"type":15,"value":1383}," returns\n",{"type":9,"tag":32,"props":1385,"children":1386},{"className":34},[1387],{"type":15,"value":1388},"RenderedMessage(email, push)",{"type":15,"value":1390}," — and lists them in ",{"type":9,"tag":32,"props":1392,"children":1393},{"className":34},[1394],{"type":15,"value":1395},"bml.generated.BmlMessages",{"type":15,"value":1397},". Email HTML has\nscripts stripped and includes a plain-text alternative. The typed payload crosses as JSON and is\ndecoded inside the template, so hosts stay payload-type-agnostic. Every channel shares the same\npayload, locale, message source, and published version. ",{"type":9,"tag":32,"props":1399,"children":1400},{"className":34},[1401],{"type":15,"value":1402},"t=\"key\"",{"type":15,"value":712},{"type":9,"tag":32,"props":1405,"children":1406},{"className":34},[1407],{"type":15,"value":1408},"\u003Csubject>",{"type":15,"value":1410},", push ",{"type":9,"tag":32,"props":1412,"children":1413},{"className":34},[1414],{"type":15,"value":1415},"\u003Ctitle>",{"type":15,"value":1417},",\n",{"type":9,"tag":32,"props":1419,"children":1420},{"className":34},[1421],{"type":15,"value":1422},"\u003Cbody>",{"type":15,"value":1424},", or ",{"type":9,"tag":32,"props":1426,"children":1427},{"className":34},[1428],{"type":15,"value":1429},"\u003Caction>",{"type":15,"value":1431}," records the authored fallback in the i18n manifest and resolves it at render time.\nThe push region also inherits the producer-supplied\n",{"type":9,"tag":32,"props":1433,"children":1434},{"className":34},[1435],{"type":15,"value":1436},"BmlPushOptions",{"type":15,"value":1438}," render context, including ",{"type":9,"tag":32,"props":1440,"children":1441},{"className":34},[1442],{"type":15,"value":1443},"BmlPushRichContent",{"type":15,"value":1445}," for remote image\u002Fmedia URLs or a\nsmall conversation preview. Localized ",{"type":9,"tag":32,"props":1447,"children":1448},{"className":34},[1449],{"type":15,"value":1450},"\u003Caction id=\"…\">",{"type":15,"value":1452}," tags select producer-supplied actions and\noverlay their visible labels while retaining their destinations and routing data. Mark at most one\naction ",{"type":9,"tag":32,"props":1454,"children":1455},{"className":34},[1456],{"type":15,"value":1457},"default",{"type":15,"value":1459}," for notification-open behavior. Use an explicit ",{"type":9,"tag":32,"props":1461,"children":1462},{"className":34},[1463],{"type":15,"value":1464},":options",{"type":15,"value":1466}," binding only when the template deliberately overrides\nthat delivery metadata. ",{"type":9,"tag":32,"props":1468,"children":1469},{"className":34},[1470],{"type":15,"value":1471},"\u003Cimage\u002F>",{"type":15,"value":418},{"type":9,"tag":32,"props":1474,"children":1475},{"className":34},[1476],{"type":15,"value":1477},"\u003Cattachments\u002F>",{"type":15,"value":1479},", and ",{"type":9,"tag":32,"props":1481,"children":1482},{"className":34},[1483],{"type":15,"value":1484},"\u003Cconversation\u002F>",{"type":15,"value":1486}," select concepts from\nthat producer-owned rich content; the tags do not contain mapping code or data. Do not place full\nchat history or media bytes in a provider payload.\nSee ",{"type":9,"tag":32,"props":1488,"children":1489},{"className":34},[1490],{"type":15,"value":1491},"docs\u002Fgrammar.md",{"type":15,"value":1493}," §4.1b.",{"type":9,"tag":18,"props":1495,"children":1496},{},[1497,1502,1504,1509,1511,1515,1517,1522,1524,1529,1531,1536,1538,1543],{"type":9,"tag":24,"props":1498,"children":1499},{},[1500],{"type":15,"value":1501},"Packaging (REQ-26):",{"type":15,"value":1503}," a message project is an ordinary standalone BML build; its plain\n",{"type":9,"tag":32,"props":1505,"children":1506},{"className":34},[1507],{"type":15,"value":1508},"jar",{"type":15,"value":1510}," IS the deployable unit — compiled templates + ",{"type":9,"tag":32,"props":1512,"children":1513},{"className":34},[1514],{"type":15,"value":1395},{"type":15,"value":1516},", with\n",{"type":9,"tag":32,"props":1518,"children":1519},{"className":34},[1520],{"type":15,"value":1521},"core-bml",{"type":15,"value":1523}," as a dependency (never bundled: the host shares it via the parent classloader).\nThe compiler embeds the versioned artifact manifest at\n",{"type":9,"tag":32,"props":1525,"children":1526},{"className":34},[1527],{"type":15,"value":1528},"META-INF\u002Fbml\u002Fmessage-manifest.json",{"type":15,"value":1530},"\nlisting the module entry point and every template key, so registries can describe a jar\nwithout classloading it. Published artifacts follow ",{"type":9,"tag":32,"props":1532,"children":1533},{"className":34},[1534],{"type":15,"value":1535},"bosca.bml.message.BmlMessageArtifacts",{"type":15,"value":1537},":\n",{"type":9,"tag":32,"props":1539,"children":1540},{"className":34},[1541],{"type":15,"value":1542},"(type=raw, namespace=bml-message, coordinate=\u003CprojectKey>, version)",{"type":15,"value":1544},". Those artifact and deployment\nidentifiers define the message runtime's artifact contract.",{"type":9,"tag":18,"props":1546,"children":1547},{},[1548,1553,1555,1560,1562,1567,1569,1574,1576,1581,1583,1588,1590,1595,1597,1602,1604,1609,1611,1616,1618,1623],{"type":9,"tag":24,"props":1549,"children":1550},{},[1551],{"type":15,"value":1552},"Publishing (REQ-27):",{"type":15,"value":1554}," the project commits a git-ci pipeline (",{"type":9,"tag":32,"props":1556,"children":1557},{"className":34},[1558],{"type":15,"value":1559},".bosca\u002Fpipelines\u002F*.yaml",{"type":15,"value":1561},")\nthat, on push to main, runs ",{"type":9,"tag":32,"props":1563,"children":1564},{"className":34},[1565],{"type":15,"value":1566},".\u002Fgradlew build",{"type":15,"value":1568}," and PUTs the jar to the raw registry\n(",{"type":9,"tag":32,"props":1570,"children":1571},{"className":34},[1572],{"type":15,"value":1573},"\u002Fraw\u002Fbml-message\u002Fapi\u002F\u003CprojectKey>\u002F\u003Cversion>\u002F\u003Cfile>",{"type":15,"value":1575},", auth from ",{"type":9,"tag":32,"props":1577,"children":1578},{"className":34},[1579],{"type":15,"value":1580},"setup-registry",{"type":15,"value":1582},"). Push\nruns mint their version in-step (",{"type":9,"tag":32,"props":1584,"children":1585},{"className":34},[1586],{"type":15,"value":1587},"\u003Cutc-timestamp>-\u003Cshort-sha>",{"type":15,"value":1589}," — lexicographically\nmonotonic), so the declarative ",{"type":9,"tag":32,"props":1591,"children":1592},{"className":34},[1593],{"type":15,"value":1594},"artifacts:",{"type":15,"value":1596}," block doesn't apply; the step verifies its own\nupload. Creating the version makes the registry publish the existing\n",{"type":9,"tag":32,"props":1598,"children":1599},{"className":34},[1600],{"type":15,"value":1601},"ArtifactVersionPublished",{"type":15,"value":1603}," event on ",{"type":9,"tag":32,"props":1605,"children":1606},{"className":34},[1607],{"type":15,"value":1608},"bosca.artifacts.version.published",{"type":15,"value":1610}," — the runner's\nmessage runtime subscribes there and filters ",{"type":9,"tag":32,"props":1612,"children":1613},{"className":34},[1614],{"type":15,"value":1615},"namespace == \"bml-message\"",{"type":15,"value":1617},"; no new event\nmachinery. Studio commits reach the same trigger via ",{"type":9,"tag":32,"props":1619,"children":1620},{"className":34},[1621],{"type":15,"value":1622},"RefUpdateNotifier",{"type":15,"value":254},{"type":9,"tag":58,"props":1625,"children":1627},{"id":1626},"measuring-page-weight-bml-40",[1628],{"type":15,"value":1629},"Measuring page weight (BML-40)",{"type":9,"tag":18,"props":1631,"children":1632},{},[1633],{"type":15,"value":1634},"Page size is a build output, not a guess. Two tools ship with the toolchain:",{"type":9,"tag":18,"props":1636,"children":1637},{},[1638,1646,1648,1653,1655,1660,1662,1667,1669,1674,1675,1680,1682,1687],{"type":9,"tag":24,"props":1639,"children":1640},{},[1641],{"type":9,"tag":32,"props":1642,"children":1643},{"className":34},[1644],{"type":15,"value":1645},".\u002Fgradlew bmlMetrics",{"type":15,"value":1647}," — reports every page's first-load payload from the compiled\nsite: the island JS bundle, the CSS chunks of the components the page renders\n(transitive, resolved at compile time), and the site's global tier\n(",{"type":9,"tag":32,"props":1649,"children":1650},{"className":34},[1651],{"type":15,"value":1652},"bml { metricsGlobalAssets }",{"type":15,"value":1654},", seeded with the CSS under ",{"type":9,"tag":32,"props":1656,"children":1657},{"className":34},[1658],{"type":15,"value":1659},"src\u002Fmain\u002Fclient",{"type":15,"value":1661},"), each in raw\nand gzip bytes. Prints a table and writes ",{"type":9,"tag":32,"props":1663,"children":1664},{"className":34},[1665],{"type":15,"value":1666},"build\u002Freports\u002Fbml\u002Fsite-metrics.json",{"type":15,"value":1668}," for CI\ntrend lines. The data comes from ",{"type":9,"tag":32,"props":1670,"children":1671},{"className":34},[1672],{"type":15,"value":1673},"build\u002Fgenerated\u002Fbml\u002Fmetrics\u002F",{"type":15,"value":1071},{"type":9,"tag":32,"props":1676,"children":1677},{"className":34},[1678],{"type":15,"value":1679},"manifest.tsv",{"type":15,"value":1681}," plus one\n",{"type":9,"tag":32,"props":1683,"children":1684},{"className":34},[1685],{"type":15,"value":1686},"css\u002F\u003Ctag>.css",{"type":15,"value":1688}," per styled component), written by the compiler plugin during compilation.",{"type":9,"tag":18,"props":1690,"children":1691},{},[1692,1700,1702,1708,1710,1715],{"type":9,"tag":24,"props":1693,"children":1694},{},[1695],{"type":9,"tag":32,"props":1696,"children":1697},{"className":34},[1698],{"type":15,"value":1699},"bosca bml audit \u003Cbase-url> [-r \u002Froute]... [--json out.json]",{"type":15,"value":1701}," — measures a ",{"type":9,"tag":1703,"props":1704,"children":1705},"em",{},[1706],{"type":15,"value":1707},"running",{"type":15,"value":1709},"\nsite over HTTP: fetches each route's HTML, discovers the assets it declares (stylesheets,\nscripts, preloads, images), and records real transfer bytes (compressed, as served),\ndecoded bytes, and per-request timing. It is deliberately framework-agnostic — point it at\na BML deployment and at the same pages on any other stack for a 1:1 comparison. Assets\nreferenced from ",{"type":9,"tag":1703,"props":1711,"children":1712},{},[1713],{"type":15,"value":1714},"inside",{"type":15,"value":1716}," CSS (fonts, background images) are counted but not fetched, since\nbrowsers download only the subsets they need.",{"type":9,"tag":1130,"props":1718,"children":1720},{"id":1719},"the-production-asset-shape-bml-43",[1721],{"type":15,"value":1722},"The production asset shape (BML-43)",{"type":9,"tag":18,"props":1724,"children":1725},{},[1726,1728,1733,1735,1740,1742,1747],{"type":15,"value":1727},"In production (",{"type":9,"tag":32,"props":1729,"children":1730},{"className":34},[1731],{"type":15,"value":1732},"BmlServer(dev = false)",{"type":15,"value":1734},"), a page downloads at most ",{"type":9,"tag":24,"props":1736,"children":1737},{},[1738],{"type":15,"value":1739},"one page stylesheet and one\npage bundle",{"type":15,"value":1741}," on top of ",{"type":9,"tag":24,"props":1743,"children":1744},{},[1745],{"type":15,"value":1746},"one global stylesheet and one global script",{"type":15,"value":383},{"type":9,"tag":1262,"props":1749,"children":1750},{},[1751,1768,1778],{"type":9,"tag":103,"props":1752,"children":1753},{},[1754,1759,1761,1766],{"type":9,"tag":32,"props":1755,"children":1756},{"className":34},[1757],{"type":15,"value":1758},"\u002F_bml\u002Fapp.css",{"type":15,"value":1760}," — the site's global CSS ",{"type":9,"tag":24,"props":1762,"children":1763},{},[1764],{"type":15,"value":1765},"plus",{"type":15,"value":1767}," the scoped styles of components rendered by\nevery page (the normalized shared set).",{"type":9,"tag":103,"props":1769,"children":1770},{},[1771,1776],{"type":9,"tag":32,"props":1772,"children":1773},{"className":34},[1774],{"type":15,"value":1775},"\u002F_bml\u002Fcss\u002F\u003Cslug>.page.css",{"type":15,"value":1777}," — the page's remaining component styles, merged in chunk-link order.",{"type":9,"tag":103,"props":1779,"children":1780},{},[1781,1786,1788,1793,1795,1799,1801,1806,1808,1818],{"type":9,"tag":32,"props":1782,"children":1783},{"className":34},[1784],{"type":15,"value":1785},"\u002F_bml\u002Fjs\u002F\u003Cslug>.page.js",{"type":15,"value":1787}," — the page's client code and its closure components', bundled as one\nfile by ",{"type":9,"tag":32,"props":1789,"children":1790},{"className":34},[1791],{"type":15,"value":1792},"bundle.mjs --manifest … --prod-out …",{"type":15,"value":1794}," (run automatically by ",{"type":9,"tag":32,"props":1796,"children":1797},{"className":34},[1798],{"type":15,"value":800},{"type":15,"value":1800}," into\n",{"type":9,"tag":32,"props":1802,"children":1803},{"className":34},[1804],{"type":15,"value":1805},"build\u002Fgenerated\u002Fbml\u002Fjs-prod",{"type":15,"value":1807},"). ",{"type":9,"tag":24,"props":1809,"children":1810},{},[1811,1813],{"type":15,"value":1812},"Production deployments must pass that directory as\n",{"type":9,"tag":32,"props":1814,"children":1815},{"className":34},[1816],{"type":15,"value":1817},"BmlServer(clientDir = …)",{"type":15,"value":1819}," — the per-module dev files are no longer injected.",{"type":9,"tag":18,"props":1821,"children":1822},{},[1823,1825,1830,1832,1837,1839,1843,1845,1850],{"type":15,"value":1824},"Production HTML appends one deterministic deployment digest (for example ",{"type":9,"tag":32,"props":1826,"children":1827},{"className":34},[1828],{"type":15,"value":1829},"?_ts=9c48…",{"type":15,"value":1831},") to every\ngenerated CSS and JS URL. The digest covers the project version, generated page and component\nsource, compiled asset maps, global assets, and bundled client files. Replicas running the same\ndeployment therefore emit the same URLs, while a relevant source or asset change produces a new URL.\nThe generated asset responses use ",{"type":9,"tag":32,"props":1833,"children":1834},{"className":34},[1835],{"type":15,"value":1836},"Cache-Control: public, max-age=31536000, immutable",{"type":15,"value":1838},"; the token\nmakes that one-year TTL safe by changing the URL on the next deployment. The underlying routes stay\nunchanged. Production JS uses syntax, whitespace, and local-identifier minification without\nproperty-name mangling (public globals, datasets, and generated contracts keep their runtime names),\nand production source maps are not emitted. Files in ",{"type":9,"tag":32,"props":1840,"children":1841},{"className":34},[1842],{"type":15,"value":1659},{"type":15,"value":1844}," are also parsed, bundled, and\nminified into ",{"type":9,"tag":32,"props":1846,"children":1847},{"className":34},[1848],{"type":15,"value":1849},"build\u002Fgenerated\u002Fbml\u002Fclient-assets",{"type":15,"value":1851},"; CSS uses esbuild's CSS parser rather than unsafe\ntext-level whitespace removal.",{"type":9,"tag":18,"props":1853,"children":1854},{},[1855,1857,1862],{"type":15,"value":1856},"Dev mode keeps the per-component chunks and per-module JS so an edit invalidates one small file.\n",{"type":9,"tag":32,"props":1858,"children":1859},{"className":34},[1860],{"type":15,"value":1861},"bmlMetrics",{"type":15,"value":1863}," prices the production shape whenever the prod bundles exist.",1790541170515]