[{"data":1,"prerenderedAt":817},["ShallowReactive",2],{"doc-page:adr\u002F0012-cross-framework-distribution-via-web-components":3},{"data":4,"body":7,"toc":810},{"title":5,"description":6},"ADR 0012 — Cross-framework distribution via single-source Web Components","",{"type":8,"children":9},"root",[10,18,44,51,88,190,242,252,258,263,363,390,423,428,452,464,470,676,682],{"type":11,"tag":12,"props":13,"children":15},"element","h1",{"id":14},"adr-0012-cross-framework-distribution-via-single-source-web-components",[16],{"type":17,"value":5},"text",{"type":11,"tag":19,"props":20,"children":21},"ul",{},[22,34],{"type":11,"tag":23,"props":24,"children":25},"li",{},[26,32],{"type":11,"tag":27,"props":28,"children":29},"strong",{},[30],{"type":17,"value":31},"Date",{"type":17,"value":33},": 2026-06-03",{"type":11,"tag":23,"props":35,"children":36},{},[37,42],{"type":11,"tag":27,"props":38,"children":39},{},[40],{"type":17,"value":41},"Status",{"type":17,"value":43},": Accepted — the gating feasibility spike passed (see \"Spike\noutcome\" below); the \"compile directly from current source\" path is\nconfirmed, so the fallback re-author path is not required.",{"type":11,"tag":45,"props":46,"children":48},"h2",{"id":47},"spike-outcome-2026-06-03",[49],{"type":17,"value":50},"Spike outcome (2026-06-03)",{"type":11,"tag":52,"props":53,"children":54},"p",{},[55,57,64,66,71,73,78,80,86],{"type":17,"value":56},"A spike under ",{"type":11,"tag":58,"props":59,"children":61},"code",{"className":60},[],[62],{"type":17,"value":63},"spike\u002Fweb-components\u002F",{"type":17,"value":65}," compiled two ",{"type":11,"tag":27,"props":67,"children":68},{},[69],{"type":17,"value":70},"unmodified",{"type":17,"value":72}," real\ncomponents to ",{"type":11,"tag":27,"props":74,"children":75},{},[76],{"type":17,"value":77},"light-DOM",{"type":17,"value":79}," custom elements (",{"type":11,"tag":58,"props":81,"children":83},{"className":82},[],[84],{"type":17,"value":85},"shadowRoot: false",{"type":17,"value":87},") and loaded\nthem in a plain HTML host:",{"type":11,"tag":19,"props":89,"children":90},{},[91,129],{"type":11,"tag":23,"props":92,"children":93},{},[94,103,105,111,113,119,121,127],{"type":11,"tag":27,"props":95,"children":96},{},[97],{"type":11,"tag":58,"props":98,"children":100},{"className":99},[],[101],{"type":17,"value":102},"TuxBigStat",{"type":17,"value":104}," (tux-native, scoped styles + token vars) — rendered\npixel-correct; ",{"type":11,"tag":58,"props":106,"children":108},{"className":107},[],[109],{"type":17,"value":110},"data-theme",{"type":17,"value":112}," switching (",{"type":11,"tag":58,"props":114,"children":116},{"className":115},[],[117],{"type":17,"value":118},"tti",{"type":17,"value":120}," → ",{"type":11,"tag":58,"props":122,"children":124},{"className":123},[],[125],{"type":17,"value":126},"tti-dark",{"type":17,"value":128},") re-themed it\nwith zero JS (maroon → documented lifted-teal).",{"type":11,"tag":23,"props":130,"children":131},{},[132,141,143,149,151,157,159,164,166,172,174,180,182,188],{"type":11,"tag":27,"props":133,"children":134},{},[135],{"type":11,"tag":58,"props":136,"children":138},{"className":137},[],[139],{"type":17,"value":140},"TuxBadge",{"type":17,"value":142}," (wraps Nuxt UI ",{"type":11,"tag":58,"props":144,"children":146},{"className":145},[],[147],{"type":17,"value":148},"UBadge",{"type":17,"value":150}," + ",{"type":11,"tag":58,"props":152,"children":154},{"className":153},[],[155],{"type":17,"value":156},"UIcon",{"type":17,"value":158},") — ",{"type":11,"tag":27,"props":160,"children":161},{},[162],{"type":17,"value":163},"rendered with zero\nconsole errors\u002Fwarnings.",{"type":17,"value":165}," Nuxt UI survives the custom-element boundary\nvia ",{"type":11,"tag":58,"props":167,"children":169},{"className":168},[],[170],{"type":17,"value":171},"@nuxt\u002Fui\u002Fvue-plugin",{"type":17,"value":173}," installed through Vue 3.5's\n",{"type":11,"tag":58,"props":175,"children":177},{"className":176},[],[178],{"type":17,"value":179},"defineCustomElement({ configureApp })",{"type":17,"value":181},", with ",{"type":11,"tag":58,"props":183,"children":185},{"className":184},[],[186],{"type":17,"value":187},"@nuxt\u002Fui\u002Fvite",{"type":17,"value":189}," providing\nthe same auto-imports as Nuxt.",{"type":11,"tag":52,"props":191,"children":192},{},[193,195,200,202,208,210,216,218,224,226,232,234,240],{"type":17,"value":194},"Two requirements for full ",{"type":11,"tag":27,"props":196,"children":197},{},[198],{"type":17,"value":199},"brand parity",{"type":17,"value":201}," were confirmed as config ports,\nnot blockers: (1) load the same CSS chain (Tailwind + ",{"type":11,"tag":58,"props":203,"children":205},{"className":204},[],[206],{"type":17,"value":207},"@nuxt\u002Fui",{"type":17,"value":209}," + tokens +\ntux utilities) globally — light DOM lets it apply; (2) replicate\n",{"type":11,"tag":58,"props":211,"children":213},{"className":212},[],[214],{"type":17,"value":215},"app\u002Fapp.config.ts",{"type":17,"value":217}," ",{"type":11,"tag":58,"props":219,"children":221},{"className":220},[],[222],{"type":17,"value":223},"ui.colors",{"type":17,"value":225}," (e.g. ",{"type":11,"tag":58,"props":227,"children":229},{"className":228},[],[230],{"type":17,"value":231},"primary → maroon",{"type":17,"value":233},") into the build —\nthe maroon shade vars already live in ",{"type":11,"tag":58,"props":235,"children":237},{"className":236},[],[238],{"type":17,"value":239},"tokens.css",{"type":17,"value":241},". With both, the\nNuxt-UI-wrapped badges mapped onto the TTI palette correctly.",{"type":11,"tag":52,"props":243,"children":244},{},[245,250],{"type":11,"tag":27,"props":246,"children":247},{},[248],{"type":17,"value":249},"Known consumer caveat (React):",{"type":17,"value":251}," custom elements pass complex props as\nattributes; React \u003C 19 needs the generated wrapper (or refs) to bind\nobject\u002Farray props and custom events. React 19 handles them natively.\nString\u002Fnumber props (most components) work as plain attributes today. This\nis exactly the boilerplate the CEM-driven generator removes.",{"type":11,"tag":45,"props":253,"children":255},{"id":254},"context",[256],{"type":17,"value":257},"Context",{"type":11,"tag":52,"props":259,"children":260},{},[261],{"type":17,"value":262},"tux is authored in Vue 3 + Nuxt UI and today only ships to Nuxt apps via\nthe layer model (ADR-0003). But the real consumer landscape across TTI is\nnot Nuxt:",{"type":11,"tag":19,"props":264,"children":265},{},[266,298,331],{"type":11,"tag":23,"props":267,"children":268},{},[269,274,276,282,284,289,291,296],{"type":11,"tag":27,"props":270,"children":271},{},[272],{"type":17,"value":273},"WordPress sites",{"type":17,"value":275}," (research microsites + the intranet\n",{"type":11,"tag":58,"props":277,"children":279},{"className":278},[],[280],{"type":17,"value":281},"my.tti.tamu.edu",{"type":17,"value":283},", which runs ",{"type":11,"tag":27,"props":285,"children":286},{},[287],{"type":17,"value":288},"Kadence theme + Kadence Blocks",{"type":17,"value":290}," — i.e.\nalready Gutenberg\u002FReact, with in-house custom plugins). Page-building\nacross the fleet spans ",{"type":11,"tag":27,"props":292,"children":293},{},[294],{"type":17,"value":295},"Gutenberg\u002FKadence Blocks and Elementor",{"type":17,"value":297},"; both\nmust be covered.",{"type":11,"tag":23,"props":299,"children":300},{},[301,306,308,314,316,322,324,329],{"type":11,"tag":27,"props":302,"children":303},{},[304],{"type":17,"value":305},"ASP.NET MVC 5.3 Razor",{"type":17,"value":307}," apps (",{"type":11,"tag":58,"props":309,"children":311},{"className":310},[],[312],{"type":17,"value":313},"rims.tti.tamu.edu",{"type":17,"value":315},") — server-rendered\n",{"type":11,"tag":58,"props":317,"children":319},{"className":318},[],[320],{"type":17,"value":321},".cshtml",{"type":17,"value":323},", ",{"type":11,"tag":27,"props":325,"children":326},{},[327],{"type":17,"value":328},"Bootstrap 4",{"type":17,"value":330}," + jQuery + FontAwesome, mostly stock classes.",{"type":11,"tag":23,"props":332,"children":333},{},[334,339,341,347,349,353,355,361],{"type":11,"tag":27,"props":335,"children":336},{},[337],{"type":17,"value":338},"Vue 2 SPAs",{"type":17,"value":340}," (",{"type":11,"tag":58,"props":342,"children":344},{"className":343},[],[345],{"type":17,"value":346},"bims.tti.tamu.edu",{"type":17,"value":348},", Vue CLI on an ASP.NET\u002FIIS backend) —\n",{"type":11,"tag":27,"props":350,"children":351},{},[352],{"type":17,"value":328},{"type":17,"value":354}," + a hand-rolled ",{"type":11,"tag":58,"props":356,"children":358},{"className":357},[],[359],{"type":17,"value":360},"bg-maroon",{"type":17,"value":362},". Vue 2 is EOL.",{"type":11,"tag":52,"props":364,"children":365},{},[366,368,373,375,381,383,388],{"type":17,"value":367},"The goal is to make tux ",{"type":11,"tag":27,"props":369,"children":370},{},[371],{"type":17,"value":372},"easily consumable by everything",{"type":17,"value":374}," as a ",{"type":11,"tag":376,"props":377,"children":378},"em",{},[379],{"type":17,"value":380},"bridge",{"type":17,"value":382},"\nuntil consumers migrate to Nuxt\u002FVue, and to make it cheap for developers:\nwhen they write or update one component, native support for every target\nshould be ",{"type":11,"tag":27,"props":384,"children":385},{},[386],{"type":17,"value":387},"generated",{"type":17,"value":389},", not hand-maintained.",{"type":11,"tag":52,"props":391,"children":392},{},[393,395,400,402,407,409,414,416,421],{"type":17,"value":394},"The migration thesis behind this is deliberate: ",{"type":11,"tag":27,"props":396,"children":397},{},[398],{"type":17,"value":399},"change the visuals first,\nswap the structure later.",{"type":17,"value":401}," Get every app ",{"type":11,"tag":376,"props":403,"children":404},{},[405],{"type":17,"value":406},"looking",{"type":17,"value":408}," like tux through the\nshared visual layer while it keeps its existing WordPress \u002F Razor \u002F Vue 2\ninternals, so that the eventual re-platform to Vue\u002FNuxt is ",{"type":11,"tag":27,"props":410,"children":411},{},[412],{"type":17,"value":413},"invisible to\nend users",{"type":17,"value":415}," — nothing appears to change on \"upgrade\" because the pixels\nwere already tux. This makes ",{"type":11,"tag":27,"props":417,"children":418},{},[419],{"type":17,"value":420},"pixel-level visual parity across every\ntarget a hard requirement",{"type":17,"value":422},", not a nice-to-have: it is the property the\nwhole migration depends on.",{"type":11,"tag":52,"props":424,"children":425},{},[426],{"type":17,"value":427},"Two hard constraints shaped the decision:",{"type":11,"tag":429,"props":430,"children":431},"ol",{},[432,442],{"type":11,"tag":23,"props":433,"children":434},{},[435,440],{"type":11,"tag":27,"props":436,"children":437},{},[438],{"type":17,"value":439},"There is no reliable Vue→React\u002FC# transpiler",{"type":17,"value":441}," for arbitrary\ncomponents. \"Author in Vue, get idiomatic React\u002FRazor for free\" is not\nreal at production quality.",{"type":11,"tag":23,"props":443,"children":444},{},[445,450],{"type":11,"tag":27,"props":446,"children":447},{},[448],{"type":17,"value":449},"Hand-writing idiomatic components per framework does not scale",{"type":17,"value":451}," to\na wide consumer fleet with a single maintainer. The maintenance cost, not the\nper-target polish, is the binding constraint.",{"type":11,"tag":52,"props":453,"children":454},{},[455,457,462],{"type":17,"value":456},"The only primitive that genuinely runs unmodified in WordPress, React,\nRazor, and plain HTML — and can be produced from our existing Vue source —\nis the ",{"type":11,"tag":27,"props":458,"children":459},{},[460],{"type":17,"value":461},"Web Component (Custom Element)",{"type":17,"value":463},".",{"type":11,"tag":45,"props":465,"children":467},{"id":466},"decision",[468],{"type":17,"value":469},"Decision",{"type":11,"tag":429,"props":471,"children":472},{},[473,499,509,542,582,628,659],{"type":11,"tag":23,"props":474,"children":475},{},[476,481,483,489,491,497],{"type":11,"tag":27,"props":477,"children":478},{},[479],{"type":17,"value":480},"Web Components are the cross-framework distribution primitive.",{"type":17,"value":482}," tux\nships a ",{"type":11,"tag":58,"props":484,"children":486},{"className":485},[],[487],{"type":17,"value":488},"\u003Ctux-*>",{"type":17,"value":490}," custom-element bundle built from Vue via\n",{"type":11,"tag":58,"props":492,"children":494},{"className":493},[],[495],{"type":17,"value":496},"defineCustomElement",{"type":17,"value":498},". This is a generated artifact, not a second source\ntree.",{"type":11,"tag":23,"props":500,"children":501},{},[502,507],{"type":11,"tag":27,"props":503,"children":504},{},[505],{"type":17,"value":506},"The Vue SFC stays the canonical authoring format.",{"type":17,"value":508}," Developers keep\nwriting Tux components as they do today.",{"type":11,"tag":23,"props":510,"children":511},{},[512,517,519,524,526,532,534,540],{"type":11,"tag":27,"props":513,"children":514},{},[515],{"type":17,"value":516},"A Custom Elements Manifest (CEM) is the codegen source of truth.",{"type":17,"value":518}," A\nbuild step analyzes the components and emits CEM JSON (props\u002Fslots\u002F\nevents), from which we ",{"type":11,"tag":27,"props":520,"children":521},{},[522],{"type":17,"value":523},"auto-generate",{"type":17,"value":525}," the thin per-framework\nadapters: React wrappers (which in turn power Gutenberg ",{"type":11,"tag":58,"props":527,"children":529},{"className":528},[],[530],{"type":17,"value":531},"edit",{"type":17,"value":533},"\u002F",{"type":11,"tag":58,"props":535,"children":537},{"className":536},[],[538],{"type":17,"value":539},"save",{"type":17,"value":541},"\nblocks), Razor tag helpers, TypeScript types, and docs. Generated code\nis binding glue, never a reimplementation.",{"type":11,"tag":23,"props":543,"children":544},{},[545,550,552,558,560,566,567,573,575,580],{"type":11,"tag":27,"props":546,"children":547},{},[548],{"type":17,"value":549},"Distribution = CDN-via-jsDelivr now, npm later.",{"type":17,"value":551}," We do not stand up\nor pay for a CDN. jsDelivr serves directly from GitHub\n(",{"type":11,"tag":58,"props":553,"children":555},{"className":554},[],[556],{"type":17,"value":557},"cdn.jsdelivr.net\u002Fgh\u002Fttitamu\u002Ftti-ux@\u003Ctag>\u002Fdist\u002F...",{"type":17,"value":559},"), giving WordPress\nsites a ",{"type":11,"tag":58,"props":561,"children":563},{"className":562},[],[564],{"type":17,"value":565},"\u003Cscript>",{"type":17,"value":150},{"type":11,"tag":58,"props":568,"children":570},{"className":569},[],[571],{"type":17,"value":572},"\u003Clink>",{"type":17,"value":574}," story ",{"type":11,"tag":27,"props":576,"children":577},{},[578],{"type":17,"value":579},"today",{"type":17,"value":581},", before the npm org of\nADR-0003 exists. When npm lands, the same artifacts mirror to\njsDelivr\u002Funpkg and we switch the URL base. This supplements ADR-0003;\nit does not supersede it.",{"type":11,"tag":23,"props":583,"children":584},{},[585,590,592,597,599,612,614,626],{"type":11,"tag":27,"props":586,"children":587},{},[588],{"type":17,"value":589},"A compiled, Tailwind-free CSS + token kit ships first and broadest —\nit is the visual layer the migration thesis rides on.",{"type":17,"value":591}," It includes a\n",{"type":11,"tag":27,"props":593,"children":594},{},[595],{"type":17,"value":596},"Bootstrap-4 theme variant",{"type":17,"value":598}," (tux tokens → BS4 SCSS variables) and a\nWordPress ",{"type":11,"tag":27,"props":600,"children":601},{},[602,604,610],{"type":17,"value":603},"global-styles \u002F ",{"type":11,"tag":58,"props":605,"children":607},{"className":606},[],[608],{"type":17,"value":609},"theme.json",{"type":17,"value":611}," mapping",{"type":17,"value":613},". One artifact re-skins\nRIMS (Razor) and BIMS (Vue 2), and — critically for WordPress — restyles\n",{"type":11,"tag":27,"props":615,"children":616},{},[617,619,624],{"type":17,"value":618},"Gutenberg\u002FKadence Blocks ",{"type":11,"tag":376,"props":620,"children":621},{},[622],{"type":17,"value":623},"and",{"type":17,"value":625}," Elementor at once",{"type":17,"value":627},", since both render\ninto DOM the global CSS can target. This is the \"dogfood the visuals\"\nshipment: apps adopt it without changing how content is built. Builds on\nADR-0004 (tokens already live outside the Nuxt UI theme).",{"type":11,"tag":23,"props":629,"children":630},{},[631,636,638,643,645,650,652,657],{"type":11,"tag":27,"props":632,"children":633},{},[634],{"type":17,"value":635},"WordPress gets two layers.",{"type":17,"value":637}," Layer 1 is the global-styles CSS above\n(visual parity for the whole fleet, both builders, immediately). Layer 2\nis ",{"type":11,"tag":376,"props":639,"children":640},{},[641],{"type":17,"value":642},"authoring",{"type":17,"value":644}," adapters generated from the CEM: native ",{"type":11,"tag":27,"props":646,"children":647},{},[648],{"type":17,"value":649},"Gutenberg\nblocks",{"type":17,"value":651}," (via the React adapters) ",{"type":11,"tag":27,"props":653,"children":654},{},[655],{"type":17,"value":656},"and Elementor widgets",{"type":17,"value":658}," (Elementor's\nPHP widget + controls API), so authors get first-class tux components in\nwhichever builder a site uses. Layer 1 is the priority; Layer 2 follows.",{"type":11,"tag":23,"props":660,"children":661},{},[662,667,669,674],{"type":11,"tag":27,"props":663,"children":664},{},[665],{"type":17,"value":666},"This reverses an earlier informal lean toward hand-idiomatic\nper-framework components.",{"type":17,"value":668}," We consciously trade some native-feel in\nReact\u002FRazor (consumers use a ",{"type":11,"tag":58,"props":670,"children":672},{"className":671},[],[673],{"type":17,"value":488},{"type":17,"value":675}," element rather than a native\ncomponent) for single-source authoring + automatic generation. At\nmulti-consumer, bridge-period scale, single-source wins.",{"type":11,"tag":45,"props":677,"children":679},{"id":678},"consequences",[680],{"type":17,"value":681},"Consequences",{"type":11,"tag":19,"props":683,"children":684},{},[685,710,720,738,756,766,783,800],{"type":11,"tag":23,"props":686,"children":687},{},[688,693,695,700,702,708],{"type":11,"tag":27,"props":689,"children":690},{},[691],{"type":17,"value":692},"Gating spike — RESOLVED (see \"Spike outcome\" above):",{"type":17,"value":694}," the concern was\nthat the ~70% of Tux components wrapping Nuxt UI primitives might not\nsurvive the custom-element boundary. The spike proved they do, compiling\n",{"type":11,"tag":27,"props":696,"children":697},{},[698],{"type":17,"value":699},"directly from current source",{"type":17,"value":701},". The fallback (re-authoring the core as\ntux-native) is therefore not needed. Remaining boundary work — light-DOM\nstyle loading and the ",{"type":11,"tag":58,"props":703,"children":705},{"className":704},[],[706],{"type":17,"value":707},"app.config",{"type":17,"value":709}," color port — is confirmed mechanical.\nThe plain-HTML host stands in for any non-Vue host; React\u002FWP differ only\nin the thin prop-binding wrapper noted above, not in whether the element\nruns.",{"type":11,"tag":23,"props":711,"children":712},{},[713,718],{"type":11,"tag":27,"props":714,"children":715},{},[716],{"type":17,"value":717},"Authoring discipline:",{"type":17,"value":719}," a component is cross-framework-eligible only if\nit exposes a clean props\u002Fslots\u002Fevents contract with no reliance on Nuxt\napp context. Some components will remain Nuxt-only, and that is an\nacceptable, documented tier — not every Tux component must cross the\nboundary.",{"type":11,"tag":23,"props":721,"children":722},{},[723,728,730,736],{"type":11,"tag":27,"props":724,"children":725},{},[726],{"type":17,"value":727},"New build + CI surface:",{"type":17,"value":729}," compile custom elements, emit CEM, run the\nadapter generators, publish ",{"type":11,"tag":58,"props":731,"children":733},{"className":732},[],[734],{"type":17,"value":735},"dist\u002F",{"type":17,"value":737},", and push versioned tags so jsDelivr\nhas stable URLs. This is the first time tux produces a distributable\nbuild rather than running only as a Nuxt layer.",{"type":11,"tag":23,"props":739,"children":740},{},[741,746,748,754],{"type":11,"tag":27,"props":742,"children":743},{},[744],{"type":17,"value":745},"Versioned CDN tags become the update story",{"type":17,"value":747}," for non-npm consumers\n(especially WordPress): pin ",{"type":11,"tag":58,"props":749,"children":751},{"className":750},[],[752],{"type":17,"value":753},"@v1.6.0",{"type":17,"value":755},", bump deliberately. This is the\ncross-framework analog of ADR-0003's \"pull and restart.\"",{"type":11,"tag":23,"props":757,"children":758},{},[759,764],{"type":11,"tag":27,"props":760,"children":761},{},[762],{"type":17,"value":763},"Known custom-element caveats to handle:",{"type":17,"value":765}," form participation\n(form-associated custom elements), SSR\u002Fhydration in Razor and WP, and\nstyle isolation vs. the shared token CSS. These are tracked as pipeline\nwork, not blockers.",{"type":11,"tag":23,"props":767,"children":768},{},[769,774,776,781],{"type":11,"tag":27,"props":770,"children":771},{},[772],{"type":17,"value":773},"Gutenberg blocks are generated",{"type":17,"value":775}," (the React adapters double as block\nimplementations) so they ride the same pipeline. ",{"type":11,"tag":27,"props":777,"children":778},{},[779],{"type":17,"value":780},"Elementor widgets are\nthe one bespoke WordPress adapter",{"type":17,"value":782}," (Elementor's PHP widget API has no\nReact\u002FCEM bridge); they still consume the shared CSS contract, so they\ninherit visual parity even where the generator can't reach.",{"type":11,"tag":23,"props":784,"children":785},{},[786,791,793,798],{"type":11,"tag":27,"props":787,"children":788},{},[789],{"type":17,"value":790},"Visual parity is now an acceptance criterion, not a goal.",{"type":17,"value":792}," Because the\nmigration thesis depends on the structural swap being invisible, the\npipeline needs ",{"type":11,"tag":27,"props":794,"children":795},{},[796],{"type":17,"value":797},"cross-target visual-regression testing",{"type":17,"value":799}," — the same\ncomponent rendered as Vue (canonical), custom element, Razor, and WP block\nmust diff to ~zero against a reference. This is new CI surface beyond the\nexisting AAA-contrast and lint\u002Ftypecheck gates.",{"type":11,"tag":23,"props":801,"children":802},{},[803,808],{"type":11,"tag":27,"props":804,"children":805},{},[806],{"type":17,"value":807},"Rollout order follows the thesis:",{"type":17,"value":809}," ship the global-styles CSS layer\nfirst (visual parity everywhere, fastest adoption), then the custom-\nelement bundle + generated adapters, then per-builder authoring widgets.\nStructure swaps to Vue\u002FNuxt happen last, per consumer, after the pixels\nalready match.",{"title":6,"searchDepth":811,"depth":811,"links":812},2,[813,814,815,816],{"id":47,"depth":811,"text":50},{"id":254,"depth":811,"text":257},{"id":466,"depth":811,"text":469},{"id":678,"depth":811,"text":681},1792952322256]