[{"data":1,"prerenderedAt":3250},["ShallowReactive",2],{"navigation_docs":3,"-docs-deploy-nuxt":493,"-docs-deploy-nuxt-surround":3245},[4,46,135,218,257,292,355,377,420],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":45},"Getting Started","i-lucide-rocket","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"What is Heximon?","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F01.getting-started\u002F01.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F01.getting-started\u002F02.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fdocs\u002Fgetting-started\u002Fquick-start","docs\u002F01.getting-started\u002F03.quick-start","i-lucide-zap",{"title":26,"path":27,"stem":28,"icon":29},"Core Concepts","\u002Fdocs\u002Fgetting-started\u002Fcore-concepts","docs\u002F01.getting-started\u002F04.core-concepts","i-lucide-shapes",{"title":31,"path":32,"stem":33,"icon":34},"Examples","\u002Fdocs\u002Fgetting-started\u002Fexamples","docs\u002F01.getting-started\u002F05.examples","i-lucide-library",{"title":36,"path":37,"stem":38,"icon":39},"Where Next?","\u002Fdocs\u002Fgetting-started\u002Fwhere-next","docs\u002F01.getting-started\u002F06.where-next","i-lucide-signpost",{"title":41,"path":42,"stem":43,"icon":44},"Troubleshooting","\u002Fdocs\u002Fgetting-started\u002Ftroubleshooting","docs\u002F01.getting-started\u002F07.troubleshooting","i-lucide-life-buoy",false,{"title":47,"icon":48,"path":49,"stem":50,"children":51,"page":45},"Essentials","i-lucide-boxes","\u002Fdocs\u002Fessentials","docs\u002F02.essentials",[52,56,61,66,71,76,81,86,91,96,101,105,110,115,120,125,130],{"title":53,"path":54,"stem":55,"icon":48},"Modules & DI","\u002Fdocs\u002Fessentials\u002Fmodules-and-di","docs\u002F02.essentials\u002F01.modules-and-di",{"title":57,"path":58,"stem":59,"icon":60},"Controllers","\u002Fdocs\u002Fessentials\u002Fcontrollers","docs\u002F02.essentials\u002F02.controllers","i-lucide-route",{"title":62,"path":63,"stem":64,"icon":65},"Validation & DTOs","\u002Fdocs\u002Fessentials\u002Fvalidation","docs\u002F02.essentials\u002F03.validation","i-lucide-shield-check",{"title":67,"path":68,"stem":69,"icon":70},"Contracts","\u002Fdocs\u002Fessentials\u002Fcontracts","docs\u002F02.essentials\u002F04.contracts","i-lucide-file-signature",{"title":72,"path":73,"stem":74,"icon":75},"REST Client","\u002Fdocs\u002Fessentials\u002Fclient","docs\u002F02.essentials\u002F05.client","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":80},"Database","\u002Fdocs\u002Fessentials\u002Fdatabase","docs\u002F02.essentials\u002F06.database","i-lucide-database",{"title":82,"path":83,"stem":84,"icon":85},"Drizzle ORM","\u002Fdocs\u002Fessentials\u002Fdrizzle","docs\u002F02.essentials\u002F07.drizzle","i-lucide-database-zap",{"title":87,"path":88,"stem":89,"icon":90},"Persistence & Transactions","\u002Fdocs\u002Fessentials\u002Fpersistence","docs\u002F02.essentials\u002F08.persistence","i-lucide-database-backup",{"title":92,"path":93,"stem":94,"icon":95},"Migrations","\u002Fdocs\u002Fessentials\u002Fmigrations","docs\u002F02.essentials\u002F09.migrations","i-lucide-git-branch",{"title":97,"path":98,"stem":99,"icon":100},"Authentication","\u002Fdocs\u002Fessentials\u002Fauthentication","docs\u002F02.essentials\u002F10.authentication","i-lucide-key-round",{"title":102,"path":103,"stem":104,"icon":65},"Permissions & scopes","\u002Fdocs\u002Fessentials\u002Fpermissions","docs\u002F02.essentials\u002F11.permissions",{"title":106,"path":107,"stem":108,"icon":109},"Error Handling","\u002Fdocs\u002Fessentials\u002Ferrors","docs\u002F02.essentials\u002F12.errors","i-lucide-triangle-alert",{"title":111,"path":112,"stem":113,"icon":114},"Testing a Heximon App","\u002Fdocs\u002Fessentials\u002Ftesting","docs\u002F02.essentials\u002F13.testing","i-lucide-flask-conical",{"title":116,"path":117,"stem":118,"icon":119},"Test app harness","\u002Fdocs\u002Fessentials\u002Fcreatetestapp","docs\u002F02.essentials\u002F14.createtestapp","i-lucide-test-tube",{"title":121,"path":122,"stem":123,"icon":124},"Logging & Observability","\u002Fdocs\u002Fessentials\u002Flogging","docs\u002F02.essentials\u002F17.logging","i-lucide-scroll-text",{"title":126,"path":127,"stem":128,"icon":129},"Context & Lifecycle","\u002Fdocs\u002Fessentials\u002Fcontext-and-lifecycle","docs\u002F02.essentials\u002F18.context-and-lifecycle","i-lucide-radio",{"title":131,"path":132,"stem":133,"icon":134},"Project Structure","\u002Fdocs\u002Fessentials\u002Fproject-structure","docs\u002F02.essentials\u002F19.project-structure","i-lucide-folder-tree",{"title":136,"icon":137,"path":138,"stem":139,"children":140,"page":45},"Capabilities","i-lucide-sparkles","\u002Fdocs\u002Fcapabilities","docs\u002F03.capabilities",[141,145,150,155,160,164,169,174,179,184,188,193,198,203,208,213],{"title":142,"path":143,"stem":144,"icon":137},"Overview","\u002Fdocs\u002Fcapabilities\u002Foverview","docs\u002F03.capabilities\u002F01.overview",{"title":146,"path":147,"stem":148,"icon":149},"Events","\u002Fdocs\u002Fcapabilities\u002Fevents","docs\u002F03.capabilities\u002F02.events","i-lucide-radio-tower",{"title":151,"path":152,"stem":153,"icon":154},"Queue","\u002Fdocs\u002Fcapabilities\u002Fbackground-jobs","docs\u002F03.capabilities\u002F03.background-jobs","i-lucide-list-ordered",{"title":156,"path":157,"stem":158,"icon":159},"Scheduled Work","\u002Fdocs\u002Fcapabilities\u002Fscheduled-jobs","docs\u002F03.capabilities\u002F04.scheduled-jobs","i-lucide-clock",{"title":161,"path":162,"stem":163,"icon":85},"Caching","\u002Fdocs\u002Fcapabilities\u002Fcaching","docs\u002F03.capabilities\u002F05.caching",{"title":165,"path":166,"stem":167,"icon":168},"Key\u002FValue Storage","\u002Fdocs\u002Fcapabilities\u002Fkey-value","docs\u002F03.capabilities\u002F06.key-value","i-lucide-hard-drive",{"title":170,"path":171,"stem":172,"icon":173},"Blob Storage","\u002Fdocs\u002Fcapabilities\u002Fblob","docs\u002F03.capabilities\u002F07.blob","i-lucide-folder-open",{"title":175,"path":176,"stem":177,"icon":178},"Health & Readiness","\u002Fdocs\u002Fcapabilities\u002Fhealth","docs\u002F03.capabilities\u002F08.health","i-lucide-heart-pulse",{"title":180,"path":181,"stem":182,"icon":183},"Notifications","\u002Fdocs\u002Fcapabilities\u002Fnotifications","docs\u002F03.capabilities\u002F09.notifications","i-lucide-mail",{"title":185,"path":186,"stem":187,"icon":65},"Idempotency","\u002Fdocs\u002Fcapabilities\u002Fidempotency","docs\u002F03.capabilities\u002F10.idempotency",{"title":189,"path":190,"stem":191,"icon":192},"Security Hardening","\u002Fdocs\u002Fcapabilities\u002Fsecurity","docs\u002F03.capabilities\u002F11.security","i-lucide-shield",{"title":194,"path":195,"stem":196,"icon":197},"Observability & Tracing","\u002Fdocs\u002Fcapabilities\u002Fobservability","docs\u002F03.capabilities\u002F12.observability","i-lucide-activity",{"title":199,"path":200,"stem":201,"icon":202},"OpenAPI","\u002Fdocs\u002Fcapabilities\u002Fopenapi","docs\u002F03.capabilities\u002F13.openapi","i-lucide-book-marked",{"title":204,"path":205,"stem":206,"icon":207},"MCP Server","\u002Fdocs\u002Fcapabilities\u002Fmcp","docs\u002F03.capabilities\u002F14.mcp","i-lucide-bot",{"title":209,"path":210,"stem":211,"icon":212},"Schema DTOs","\u002Fdocs\u002Fcapabilities\u002Fschema","docs\u002F03.capabilities\u002F15.schema","i-lucide-file-json",{"title":214,"path":215,"stem":216,"icon":217},"Branded IDs","\u002Fdocs\u002Fcapabilities\u002Fbranded-ids","docs\u002F03.capabilities\u002F16.branded-ids","i-lucide-tag",{"title":219,"icon":220,"path":221,"stem":222,"children":223,"page":45},"Architecture","i-lucide-building","\u002Fdocs\u002Farchitecture","docs\u002F04.architecture",[224,227,232,237,242,247,252],{"title":142,"path":225,"stem":226,"icon":220},"\u002Fdocs\u002Farchitecture\u002Foverview","docs\u002F04.architecture\u002F01.overview",{"title":228,"path":229,"stem":230,"icon":231},"Domain-Driven Design","\u002Fdocs\u002Farchitecture\u002Fddd","docs\u002F04.architecture\u002F02.ddd","i-lucide-hexagon",{"title":233,"path":234,"stem":235,"icon":236},"CQRS","\u002Fdocs\u002Farchitecture\u002Fcqrs","docs\u002F04.architecture\u002F03.cqrs","i-lucide-split",{"title":238,"path":239,"stem":240,"icon":241},"Repository Pattern","\u002Fdocs\u002Farchitecture\u002Frepository-pattern","docs\u002F04.architecture\u002F04.repository-pattern","i-lucide-archive",{"title":243,"path":244,"stem":245,"icon":246},"Integration Events","\u002Fdocs\u002Farchitecture\u002Fintegration-events","docs\u002F04.architecture\u002F05.integration-events","i-lucide-send-horizontal",{"title":248,"path":249,"stem":250,"icon":251},"Saga Orchestration","\u002Fdocs\u002Farchitecture\u002Fsagas","docs\u002F04.architecture\u002F06.sagas","i-lucide-hourglass",{"title":253,"path":254,"stem":255,"icon":256},"Durable Workflows","\u002Fdocs\u002Farchitecture\u002Fworkflows","docs\u002F04.architecture\u002F07.workflows","i-lucide-workflow",{"title":258,"icon":259,"path":260,"stem":261,"children":262,"page":45},"Realtime","i-lucide-cable","\u002Fdocs\u002Frealtime","docs\u002F05.realtime",[263,266,270,274,279,284,288],{"title":142,"path":264,"stem":265,"icon":259},"\u002Fdocs\u002Frealtime\u002Foverview","docs\u002F05.realtime\u002F01.overview",{"title":267,"path":268,"stem":269,"icon":129},"WebSockets","\u002Fdocs\u002Frealtime\u002Fwebsockets","docs\u002F05.realtime\u002F02.websockets",{"title":271,"path":272,"stem":273,"icon":70},"WebSocket Contracts","\u002Fdocs\u002Frealtime\u002Fwebsocket-contracts","docs\u002F05.realtime\u002F03.websocket-contracts",{"title":275,"path":276,"stem":277,"icon":278},"Server-Sent Events","\u002Fdocs\u002Frealtime\u002Fserver-sent-events","docs\u002F05.realtime\u002F04.server-sent-events","i-lucide-rss",{"title":280,"path":281,"stem":282,"icon":283},"Typed Clients","\u002Fdocs\u002Frealtime\u002Ftyped-clients","docs\u002F05.realtime\u002F05.typed-clients","i-lucide-plug-zap",{"title":285,"path":286,"stem":287,"icon":259},"AsyncAPI","\u002Fdocs\u002Frealtime\u002Fasyncapi","docs\u002F05.realtime\u002F06.asyncapi",{"title":289,"path":290,"stem":291,"icon":80},"Durable Objects","\u002Fdocs\u002Frealtime\u002Fdurable-objects","docs\u002F05.realtime\u002F07.durable-objects",{"title":293,"icon":294,"path":295,"stem":296,"children":297,"page":45},"Deploy","i-lucide-cloud-upload","\u002Fdocs\u002Fdeploy","docs\u002F06.deploy",[298,301,306,311,316,321,326,331,336,341,345,350],{"title":142,"path":299,"stem":300,"icon":6},"\u002Fdocs\u002Fdeploy\u002Foverview","docs\u002F06.deploy\u002F01.overview",{"title":302,"path":303,"stem":304,"icon":305},"Node","\u002Fdocs\u002Fdeploy\u002Fnode","docs\u002F06.deploy\u002F02.node","la:node-js",{"title":307,"path":308,"stem":309,"icon":310},"Cloudflare","\u002Fdocs\u002Fdeploy\u002Fcloudflare","docs\u002F06.deploy\u002F03.cloudflare","simple-icons:cloudflare",{"title":312,"path":313,"stem":314,"icon":315},"Vercel","\u002Fdocs\u002Fdeploy\u002Fvercel","docs\u002F06.deploy\u002F04.vercel","ri:vercel-fill",{"title":317,"path":318,"stem":319,"icon":320},"Netlify","\u002Fdocs\u002Fdeploy\u002Fnetlify","docs\u002F06.deploy\u002F05.netlify","i-simple-icons-netlify",{"title":322,"path":323,"stem":324,"icon":325},"AWS Lambda","\u002Fdocs\u002Fdeploy\u002Faws-lambda","docs\u002F06.deploy\u002F06.aws-lambda","hugeicons:aws-lambda",{"title":327,"path":328,"stem":329,"icon":330},"Deno Deploy","\u002Fdocs\u002Fdeploy\u002Fdeno-deploy","docs\u002F06.deploy\u002F07.deno-deploy","simple-icons:denodeploy",{"title":332,"path":333,"stem":334,"icon":335},"Nitro","\u002Fdocs\u002Fdeploy\u002Fnitro","docs\u002F06.deploy\u002F08.nitro","i-unjs-nitro",{"title":337,"path":338,"stem":339,"icon":340},"Nuxt","\u002Fdocs\u002Fdeploy\u002Fnuxt","docs\u002F06.deploy\u002F09.nuxt","i-devicon-nuxt",{"title":342,"path":343,"stem":344,"icon":236},"Mixed-runtime split","\u002Fdocs\u002Fdeploy\u002Fmixed-runtime-split","docs\u002F06.deploy\u002F10.mixed-runtime-split",{"title":346,"path":347,"stem":348,"icon":349},"Hosts","\u002Fdocs\u002Fdeploy\u002Fhosts","docs\u002F06.deploy\u002F11.hosts","i-lucide-map",{"title":351,"path":352,"stem":353,"icon":354},"Cross-service events","\u002Fdocs\u002Fdeploy\u002Fcross-service-events","docs\u002F06.deploy\u002F12.cross-service-events","i-lucide-network",{"title":356,"icon":357,"path":358,"stem":359,"children":360,"page":45},"CLI","i-lucide-terminal","\u002Fdocs\u002Fcli","docs\u002F07.cli",[361,365,369,373],{"title":362,"path":363,"stem":364,"icon":357},"The heximon CLI","\u002Fdocs\u002Fcli\u002Foverview","docs\u002F07.cli\u002F01.overview",{"title":366,"path":367,"stem":368,"icon":137},"Create a New App","\u002Fdocs\u002Fcli\u002Fcreate","docs\u002F07.cli\u002F02.create",{"title":370,"path":371,"stem":372,"icon":95},"Migrations from the CLI","\u002Fdocs\u002Fcli\u002Fmigrations","docs\u002F07.cli\u002F03.migrations",{"title":374,"path":375,"stem":376,"icon":6},"Deploying a Heximon app","\u002Fdocs\u002Fcli\u002Fdeploy","docs\u002F07.cli\u002F04.deploy",{"title":378,"icon":379,"path":380,"stem":381,"children":382,"page":45},"Under the Hood","i-lucide-wrench","\u002Fdocs\u002Funder-the-hood","docs\u002F08.under-the-hood",[383,388,393,397,402,407,411,415],{"title":384,"path":385,"stem":386,"icon":387},"How the Compiler Works","\u002Fdocs\u002Funder-the-hood\u002Fhow-the-compiler-works","docs\u002F08.under-the-hood\u002F01.how-the-compiler-works","i-lucide-cog",{"title":389,"path":390,"stem":391,"icon":392},"Compiler","\u002Fdocs\u002Funder-the-hood\u002Fextending-the-compiler","docs\u002F08.under-the-hood\u002F02.extending-the-compiler","i-lucide-cpu",{"title":394,"path":395,"stem":396,"icon":357},"Compiler Diagnostics","\u002Fdocs\u002Funder-the-hood\u002Fcompiler-diagnostics","docs\u002F08.under-the-hood\u002F03.compiler-diagnostics",{"title":398,"path":399,"stem":400,"icon":401},"Library Mode","\u002Fdocs\u002Funder-the-hood\u002Flibrary-mode","docs\u002F08.under-the-hood\u002F04.library-mode","i-lucide-package",{"title":403,"path":404,"stem":405,"icon":406},"Other bundlers","\u002Fdocs\u002Funder-the-hood\u002Falternate-bundlers","docs\u002F08.under-the-hood\u002F05.alternate-bundlers","i-lucide-blocks",{"title":408,"path":409,"stem":410,"icon":401},"Packages","\u002Fdocs\u002Funder-the-hood\u002Fpackages","docs\u002F08.under-the-hood\u002F06.packages",{"title":412,"path":413,"stem":414,"icon":207},"AI Skills","\u002Fdocs\u002Funder-the-hood\u002Fai-and-agents","docs\u002F08.under-the-hood\u002F07.ai-and-agents",{"title":416,"path":417,"stem":418,"icon":419},"Advanced DI","\u002Fdocs\u002Funder-the-hood\u002Fadvanced-di","docs\u002F08.under-the-hood\u002F08.advanced-di","i-lucide-git-fork",{"title":421,"icon":422,"path":423,"stem":424,"children":425,"page":45},"Recipes","i-lucide-book-open-check","\u002Fdocs\u002Frecipes","docs\u002F09.recipes",[426,431,436,440,444,448,452,456,460,465,469,474,479,484,488],{"title":427,"path":428,"stem":429,"icon":430},"Send an Email","\u002Fdocs\u002Frecipes\u002Fsend-an-email","docs\u002F09.recipes\u002F01.send-an-email","i-lucide-send",{"title":432,"path":433,"stem":434,"icon":435},"Upload a File","\u002Fdocs\u002Frecipes\u002Fupload-a-file","docs\u002F09.recipes\u002F02.upload-a-file","i-lucide-upload",{"title":437,"path":438,"stem":439,"icon":24},"Cache an Expensive Call","\u002Fdocs\u002Frecipes\u002Fcache-an-expensive-call","docs\u002F09.recipes\u002F03.cache-an-expensive-call",{"title":441,"path":442,"stem":443,"icon":154},"Paginate a List","\u002Fdocs\u002Frecipes\u002Fpaginate-a-list","docs\u002F09.recipes\u002F04.paginate-a-list",{"title":445,"path":446,"stem":447,"icon":65},"Protect Admin Routes","\u002Fdocs\u002Frecipes\u002Fprotect-admin-routes","docs\u002F09.recipes\u002F05.protect-admin-routes",{"title":449,"path":450,"stem":451,"icon":178},"Health Probes and a Nightly Job","\u002Fdocs\u002Frecipes\u002Fhealth-probes-and-a-nightly-job","docs\u002F09.recipes\u002F06.health-probes-and-a-nightly-job",{"title":453,"path":454,"stem":455,"icon":80},"Build a CRUD API","\u002Fdocs\u002Frecipes\u002Fcrud-api","docs\u002F09.recipes\u002F07.crud-api",{"title":457,"path":458,"stem":459,"icon":100},"Add Authentication","\u002Fdocs\u002Frecipes\u002Fadd-authentication","docs\u002F09.recipes\u002F08.add-authentication",{"title":461,"path":462,"stem":463,"icon":464},"Background Jobs","\u002Fdocs\u002Frecipes\u002Fbackground-jobs","docs\u002F09.recipes\u002F09.background-jobs","i-lucide-timer",{"title":466,"path":467,"stem":468,"icon":149},"Decouple Features with Events","\u002Fdocs\u002Frecipes\u002Fevent-driven-module","docs\u002F09.recipes\u002F10.event-driven-module",{"title":470,"path":471,"stem":472,"icon":473},"Build a DDD Aggregate","\u002Fdocs\u002Frecipes\u002Fddd-aggregate","docs\u002F09.recipes\u002F11.ddd-aggregate","i-lucide-box",{"title":475,"path":476,"stem":477,"icon":478},"Publish a Feature Package","\u002Fdocs\u002Frecipes\u002Ffeature-package","docs\u002F09.recipes\u002F12.feature-package","i-lucide-package-open",{"title":480,"path":481,"stem":482,"icon":483},"Reliable Integration Events","\u002Fdocs\u002Frecipes\u002Freliable-integration-events","docs\u002F09.recipes\u002F13.reliable-integration-events","i-lucide-inbox",{"title":485,"path":486,"stem":487,"icon":95},"Reactive Choreography","\u002Fdocs\u002Frecipes\u002Freactive-choreography","docs\u002F09.recipes\u002F14.reactive-choreography",{"title":489,"path":490,"stem":491,"icon":492},"Build a Production CRUD API","\u002Fdocs\u002Frecipes\u002Fproduction-crud-api","docs\u002F09.recipes\u002F15.production-crud-api","i-lucide-layers",{"id":494,"title":337,"body":495,"description":3238,"extension":3239,"links":3240,"meta":3241,"navigation":3242,"path":338,"seo":3243,"stem":339,"__hash__":3244},"docs\u002Fdocs\u002F06.deploy\u002F09.nuxt.md",{"type":496,"value":497,"toc":3225},"minimark",[498,511,516,522,586,596,600,624,725,829,849,853,864,1154,1172,1178,1195,1204,1757,1769,1773,1779,1909,1919,2007,2013,2021,2025,2039,2331,2334,2341,2345,2358,2407,2431,2449,2654,2675,2692,2769,2788,2935,2975,3000,3004,3010,3038,3049,3053,3079,3115,3150,3172,3176,3221],[499,500,501,502,506,507,510],"p",{},"Ship a full-stack app from one process: your Vue pages and your Heximon API served by the same Nuxt server,\nsharing the same request. During server-side rendering, Nuxt forwards the browser's cookies to your\nin-process Heximon routes automatically — so a signed-in visitor's personalized HTML is rendered on the\nserver, before a single byte of JavaScript runs in the browser. You add one module to ",[503,504,505],"code",{},"nuxt.config.ts"," and\nwrite your controllers under ",[503,508,509],{},"server\u002F","; there's no separate API host, no proxy, and no compile script.",[512,513,515],"h2",{"id":514},"install-the-module","Install the module",[499,517,518,521],{},[503,519,520],{},"@heximon\u002Fnuxt"," runs Heximon inside Nuxt's own Nitro server. Install it and the HTTP layer you'll\nwrite controllers against:",[523,524,525,553,570],"code-group",{},[526,527,533],"pre",{"className":528,"code":529,"filename":530,"language":531,"meta":532,"style":532},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @heximon\u002Fnuxt @heximon\u002Fhttp\n","pnpm","bash","",[503,534,535],{"__ignoreMap":532},[536,537,540,543,547,550],"span",{"class":538,"line":539},"line",1,[536,541,530],{"class":542},"sBMFI",[536,544,546],{"class":545},"sfazB"," add",[536,548,549],{"class":545}," @heximon\u002Fnuxt",[536,551,552],{"class":545}," @heximon\u002Fhttp\n",[526,554,557],{"className":528,"code":555,"filename":556,"language":531,"meta":532,"style":532},"npm install @heximon\u002Fnuxt @heximon\u002Fhttp\n","npm",[503,558,559],{"__ignoreMap":532},[536,560,561,563,566,568],{"class":538,"line":539},[536,562,556],{"class":542},[536,564,565],{"class":545}," install",[536,567,549],{"class":545},[536,569,552],{"class":545},[526,571,574],{"className":528,"code":572,"filename":573,"language":531,"meta":532,"style":532},"yarn add @heximon\u002Fnuxt @heximon\u002Fhttp\n","yarn",[503,575,576],{"__ignoreMap":532},[536,577,578,580,582,584],{"class":538,"line":539},[536,579,573],{"class":542},[536,581,546],{"class":545},[536,583,549],{"class":545},[536,585,552],{"class":545},[499,587,588,591,592,595],{},[503,589,590],{},"@nuxt\u002Fkit"," is an optional peer — a real Nuxt 5 app already pulls it in through ",[503,593,594],{},"nuxt",", so you don't install\nit yourself.",[512,597,599],{"id":598},"register-the-nuxt-module","Register the Nuxt module",[499,601,602,603,606,607,610,611,615,616,619,620,623],{},"Add the module's string specifier to ",[503,604,605],{},"modules"," — it takes no inline options. Config lives in\n",[503,608,609],{},"heximon.config.ts"," at the project root, the ",[612,613,614],"strong",{},"same file"," every Heximon host reads: describe what\nto compile via ",[503,617,618],{},"plugins"," — here just ",[503,621,622],{},"HttpPlugin",", since this app is HTTP-only.",[526,625,629],{"className":626,"code":627,"filename":505,"language":628,"meta":532,"style":532},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  compatibilityDate: \"2025-07-04\",\n  srcDir: \"app\",\n  modules: [\"@heximon\u002Fnuxt\"],\n});\n","ts",[503,630,631,652,674,691,713],{"__ignoreMap":532},[536,632,633,637,640,644,648],{"class":538,"line":539},[536,634,636],{"class":635},"s7zQu","export",[536,638,639],{"class":635}," default",[536,641,643],{"class":642},"s2Zo4"," defineNuxtConfig",[536,645,647],{"class":646},"sTEyZ","(",[536,649,651],{"class":650},"sMK4o","{\n",[536,653,655,659,662,665,668,671],{"class":538,"line":654},2,[536,656,658],{"class":657},"swJcz","  compatibilityDate",[536,660,661],{"class":650},":",[536,663,664],{"class":650}," \"",[536,666,667],{"class":545},"2025-07-04",[536,669,670],{"class":650},"\"",[536,672,673],{"class":650},",\n",[536,675,677,680,682,684,687,689],{"class":538,"line":676},3,[536,678,679],{"class":657},"  srcDir",[536,681,661],{"class":650},[536,683,664],{"class":650},[536,685,686],{"class":545},"app",[536,688,670],{"class":650},[536,690,673],{"class":650},[536,692,694,697,699,702,704,706,708,711],{"class":538,"line":693},4,[536,695,696],{"class":657},"  modules",[536,698,661],{"class":650},[536,700,701],{"class":646}," [",[536,703,670],{"class":650},[536,705,520],{"class":545},[536,707,670],{"class":650},[536,709,710],{"class":646},"]",[536,712,673],{"class":650},[536,714,716,719,722],{"class":538,"line":715},5,[536,717,718],{"class":650},"}",[536,720,721],{"class":646},")",[536,723,724],{"class":650},";\n",[526,726,728],{"className":626,"code":727,"filename":609,"language":628,"meta":532,"style":532},"import { defineHeximonConfig } from \"@heximon\u002Fbuild\";\nimport { HttpPlugin } from \"@heximon\u002Fhttp\u002Fcompiler\";\n\nexport default defineHeximonConfig({\n  plugins: [new HttpPlugin()], \u002F\u002F add new EventEmitterPlugin(), … to compile those tiers too\n});\n",[503,729,730,756,778,784,796,820],{"__ignoreMap":532},[536,731,732,735,738,741,744,747,749,752,754],{"class":538,"line":539},[536,733,734],{"class":635},"import",[536,736,737],{"class":650}," {",[536,739,740],{"class":646}," defineHeximonConfig",[536,742,743],{"class":650}," }",[536,745,746],{"class":635}," from",[536,748,664],{"class":650},[536,750,751],{"class":545},"@heximon\u002Fbuild",[536,753,670],{"class":650},[536,755,724],{"class":650},[536,757,758,760,762,765,767,769,771,774,776],{"class":538,"line":654},[536,759,734],{"class":635},[536,761,737],{"class":650},[536,763,764],{"class":646}," HttpPlugin",[536,766,743],{"class":650},[536,768,746],{"class":635},[536,770,664],{"class":650},[536,772,773],{"class":545},"@heximon\u002Fhttp\u002Fcompiler",[536,775,670],{"class":650},[536,777,724],{"class":650},[536,779,780],{"class":538,"line":676},[536,781,783],{"emptyLinePlaceholder":782},true,"\n",[536,785,786,788,790,792,794],{"class":538,"line":693},[536,787,636],{"class":635},[536,789,639],{"class":635},[536,791,740],{"class":642},[536,793,647],{"class":646},[536,795,651],{"class":650},[536,797,798,801,803,805,808,810,813,816],{"class":538,"line":715},[536,799,800],{"class":657},"  plugins",[536,802,661],{"class":650},[536,804,701],{"class":646},[536,806,807],{"class":650},"new",[536,809,764],{"class":642},[536,811,812],{"class":646},"()]",[536,814,815],{"class":650},",",[536,817,819],{"class":818},"sHwdD"," \u002F\u002F add new EventEmitterPlugin(), … to compile those tiers too\n",[536,821,823,825,827],{"class":538,"line":822},6,[536,824,718],{"class":650},[536,826,721],{"class":646},[536,828,724],{"class":650},[499,830,831,832,835,836,838,839,841,842,845,846,848],{},"That's the entire integration — ",[612,833,834],{},"no compile step, no compile script, no alias, no compiler import in app\ncode."," When Nuxt builds, the module reads ",[503,837,609],{},", compiles your ",[503,840,509],{}," directory with the\nlisted plugins, and wires the resulting routes onto Nitro's HTTP layer. The Vite host uses a ",[503,843,844],{},"heximon()","\nplugin fed by the same file; here, adding the string to ",[503,847,605],{}," does the same job declaratively.",[512,850,852],{"id":851},"share-a-contract-between-the-server-and-the-client","Share a contract between the server and the client",[499,854,855,856,859,860,863],{},"Nuxt already resolves one directory from both sides of the split: ",[503,857,858],{},"shared\u002F",". That makes it the natural home\nfor a ",[503,861,862],{},"Contract"," — the class the server's controller binds to and the Vue app constructs directly as its\ntyped client, later on this page, with no hand-written request\u002Fresponse types on either side.",[526,865,868],{"className":626,"code":866,"filename":867,"language":628,"meta":532,"style":532},"import { Contract, Route } from \"@heximon\u002Fcontract\";\nimport { profileSchema, signInResultSchema, signInSchema, signOutResultSchema } from \".\u002Fschemas\";\n\nexport class GreetingApi extends Contract({\n  prefix: \"\u002Fapi\",\n  routes: {\n    signIn: Route.post(\"\u002Fsign-in\").body(signInSchema).responses({ 200: signInResultSchema }),\n    signOut: Route.post(\"\u002Fsign-out\").responses({ 200: signOutResultSchema }),\n    profile: Route.get(\"\u002Fprofile\").responses({ 200: profileSchema }),\n  },\n}) {}\n","shared\u002Fgreeting\u002Fcontract.ts",[503,869,870,897,934,938,958,974,984,1044,1090,1137,1143],{"__ignoreMap":532},[536,871,872,874,876,879,881,884,886,888,890,893,895],{"class":538,"line":539},[536,873,734],{"class":635},[536,875,737],{"class":650},[536,877,878],{"class":646}," Contract",[536,880,815],{"class":650},[536,882,883],{"class":646}," Route",[536,885,743],{"class":650},[536,887,746],{"class":635},[536,889,664],{"class":650},[536,891,892],{"class":545},"@heximon\u002Fcontract",[536,894,670],{"class":650},[536,896,724],{"class":650},[536,898,899,901,903,906,908,911,913,916,918,921,923,925,927,930,932],{"class":538,"line":654},[536,900,734],{"class":635},[536,902,737],{"class":650},[536,904,905],{"class":646}," profileSchema",[536,907,815],{"class":650},[536,909,910],{"class":646}," signInResultSchema",[536,912,815],{"class":650},[536,914,915],{"class":646}," signInSchema",[536,917,815],{"class":650},[536,919,920],{"class":646}," signOutResultSchema",[536,922,743],{"class":650},[536,924,746],{"class":635},[536,926,664],{"class":650},[536,928,929],{"class":545},".\u002Fschemas",[536,931,670],{"class":650},[536,933,724],{"class":650},[536,935,936],{"class":538,"line":676},[536,937,783],{"emptyLinePlaceholder":782},[536,939,940,942,946,949,952,954,956],{"class":538,"line":693},[536,941,636],{"class":635},[536,943,945],{"class":944},"spNyl"," class",[536,947,948],{"class":542}," GreetingApi",[536,950,951],{"class":944}," extends",[536,953,878],{"class":642},[536,955,647],{"class":646},[536,957,651],{"class":650},[536,959,960,963,965,967,970,972],{"class":538,"line":715},[536,961,962],{"class":657},"  prefix",[536,964,661],{"class":650},[536,966,664],{"class":650},[536,968,969],{"class":545},"\u002Fapi",[536,971,670],{"class":650},[536,973,673],{"class":650},[536,975,976,979,981],{"class":538,"line":822},[536,977,978],{"class":657},"  routes",[536,980,661],{"class":650},[536,982,983],{"class":650}," {\n",[536,985,987,990,992,994,997,1000,1002,1004,1007,1009,1011,1013,1016,1019,1021,1024,1026,1029,1033,1035,1038,1040,1042],{"class":538,"line":986},7,[536,988,989],{"class":657},"    signIn",[536,991,661],{"class":650},[536,993,883],{"class":646},[536,995,996],{"class":650},".",[536,998,999],{"class":642},"post",[536,1001,647],{"class":646},[536,1003,670],{"class":650},[536,1005,1006],{"class":545},"\u002Fsign-in",[536,1008,670],{"class":650},[536,1010,721],{"class":646},[536,1012,996],{"class":650},[536,1014,1015],{"class":642},"body",[536,1017,1018],{"class":646},"(signInSchema)",[536,1020,996],{"class":650},[536,1022,1023],{"class":642},"responses",[536,1025,647],{"class":646},[536,1027,1028],{"class":650},"{",[536,1030,1032],{"class":1031},"sbssI"," 200",[536,1034,661],{"class":650},[536,1036,1037],{"class":646}," signInResultSchema ",[536,1039,718],{"class":650},[536,1041,721],{"class":646},[536,1043,673],{"class":650},[536,1045,1047,1050,1052,1054,1056,1058,1060,1062,1065,1067,1069,1071,1073,1075,1077,1079,1081,1084,1086,1088],{"class":538,"line":1046},8,[536,1048,1049],{"class":657},"    signOut",[536,1051,661],{"class":650},[536,1053,883],{"class":646},[536,1055,996],{"class":650},[536,1057,999],{"class":642},[536,1059,647],{"class":646},[536,1061,670],{"class":650},[536,1063,1064],{"class":545},"\u002Fsign-out",[536,1066,670],{"class":650},[536,1068,721],{"class":646},[536,1070,996],{"class":650},[536,1072,1023],{"class":642},[536,1074,647],{"class":646},[536,1076,1028],{"class":650},[536,1078,1032],{"class":1031},[536,1080,661],{"class":650},[536,1082,1083],{"class":646}," signOutResultSchema ",[536,1085,718],{"class":650},[536,1087,721],{"class":646},[536,1089,673],{"class":650},[536,1091,1093,1096,1098,1100,1102,1105,1107,1109,1112,1114,1116,1118,1120,1122,1124,1126,1128,1131,1133,1135],{"class":538,"line":1092},9,[536,1094,1095],{"class":657},"    profile",[536,1097,661],{"class":650},[536,1099,883],{"class":646},[536,1101,996],{"class":650},[536,1103,1104],{"class":642},"get",[536,1106,647],{"class":646},[536,1108,670],{"class":650},[536,1110,1111],{"class":545},"\u002Fprofile",[536,1113,670],{"class":650},[536,1115,721],{"class":646},[536,1117,996],{"class":650},[536,1119,1023],{"class":642},[536,1121,647],{"class":646},[536,1123,1028],{"class":650},[536,1125,1032],{"class":1031},[536,1127,661],{"class":650},[536,1129,1130],{"class":646}," profileSchema ",[536,1132,718],{"class":650},[536,1134,721],{"class":646},[536,1136,673],{"class":650},[536,1138,1140],{"class":538,"line":1139},10,[536,1141,1142],{"class":650},"  },\n",[536,1144,1146,1148,1151],{"class":538,"line":1145},11,[536,1147,718],{"class":650},[536,1149,1150],{"class":646},") ",[536,1152,1153],{"class":650},"{}\n",[499,1155,1156,1159,1160,1163,1164,1167,1168,1171],{},[503,1157,1158],{},"signInSchema"," and the response schemas are just Standard Schema validators — any library works; see\n",[1161,1162,62],"a",{"href":63},". The contract's own ",[503,1165,1166],{},"prefix: \"\u002Fapi\""," owns the whole\n",[503,1169,1170],{},"\u002Fapi\u002F*"," subtree, so nothing about the mount point lives in Nuxt config.",[512,1173,1175,1176],{"id":1174},"write-a-controller-under-server","Write a controller under ",[503,1177,509],{},[499,1179,1180,1181,1183,1184,1187,1188,1191,1192,1194],{},"Heximon modules and controllers live under Nuxt's ",[503,1182,509],{}," directory — the convention Nuxt already uses for\nserver code — while your Vue pages live under ",[503,1185,1186],{},"srcDir",". The split is deliberate: ",[503,1189,1190],{},"app\u002F"," is the frontend\nbundle, ",[503,1193,509],{}," is everything that runs only on the server, and the compiler scans the latter.",[499,1196,1197,1200,1201,996],{},[503,1198,1199],{},"implements Controller\u003CGreetingApi>"," binds the controller to the contract above: it reads the route table\noff the type argument, so there's no host mount prefix to configure, and each handler is typed per route\nwith ",[503,1202,1203],{},"Action\u003CGreetingApi, \"key\">",[526,1205,1208],{"className":626,"code":1206,"filename":1207,"language":628,"meta":532,"style":532},"import type { Action, Controller } from \"@heximon\u002Fhttp\";\nimport { GreetingApi } from \"..\u002F..\u002Fshared\u002Fgreeting\u002Fcontract\";\nimport { GreetingService } from \".\u002Fgreeting.service\";\n\nexport class GreetingController implements Controller\u003CGreetingApi> {\n  constructor(private readonly greetings: GreetingService) {}\n\n  public async signIn(action: Action\u003CGreetingApi, \"signIn\">) {\n    const payload = await action.request.readValidatedBody();\n\n    action.response.setCookie(GreetingService.visitorCookieName, encodeURIComponent(payload.name), {\n      httpOnly: true,\n      sameSite: \"lax\",\n      path: \"\u002F\",\n      maxAge: 60 * 60 * 24,\n    });\n\n    return { name: payload.name };\n  }\n\n  public async profile(action: Action\u003CGreetingApi, \"profile\">) {\n    const rawCookie = action.request.getCookie(GreetingService.visitorCookieName);\n\n    if (rawCookie === undefined || rawCookie === \"\") {\n      return this.greetings.signedOutProfile();\n    }\n\n    return this.greetings.signedInProfile(decodeURIComponent(rawCookie));\n  }\n}\n","server\u002Fgreeting\u002Fgreeting.controller.ts",[503,1209,1210,1240,1261,1283,1287,1312,1338,1342,1380,1412,1416,1462,1476,1493,1510,1533,1543,1548,1570,1576,1581,1616,1649,1654,1686,1707,1713,1718,1746,1751],{"__ignoreMap":532},[536,1211,1212,1214,1217,1219,1222,1224,1227,1229,1231,1233,1236,1238],{"class":538,"line":539},[536,1213,734],{"class":635},[536,1215,1216],{"class":635}," type",[536,1218,737],{"class":650},[536,1220,1221],{"class":646}," Action",[536,1223,815],{"class":650},[536,1225,1226],{"class":646}," Controller",[536,1228,743],{"class":650},[536,1230,746],{"class":635},[536,1232,664],{"class":650},[536,1234,1235],{"class":545},"@heximon\u002Fhttp",[536,1237,670],{"class":650},[536,1239,724],{"class":650},[536,1241,1242,1244,1246,1248,1250,1252,1254,1257,1259],{"class":538,"line":654},[536,1243,734],{"class":635},[536,1245,737],{"class":650},[536,1247,948],{"class":646},[536,1249,743],{"class":650},[536,1251,746],{"class":635},[536,1253,664],{"class":650},[536,1255,1256],{"class":545},"..\u002F..\u002Fshared\u002Fgreeting\u002Fcontract",[536,1258,670],{"class":650},[536,1260,724],{"class":650},[536,1262,1263,1265,1267,1270,1272,1274,1276,1279,1281],{"class":538,"line":676},[536,1264,734],{"class":635},[536,1266,737],{"class":650},[536,1268,1269],{"class":646}," GreetingService",[536,1271,743],{"class":650},[536,1273,746],{"class":635},[536,1275,664],{"class":650},[536,1277,1278],{"class":545},".\u002Fgreeting.service",[536,1280,670],{"class":650},[536,1282,724],{"class":650},[536,1284,1285],{"class":538,"line":693},[536,1286,783],{"emptyLinePlaceholder":782},[536,1288,1289,1291,1293,1296,1299,1301,1304,1307,1310],{"class":538,"line":715},[536,1290,636],{"class":635},[536,1292,945],{"class":944},[536,1294,1295],{"class":542}," GreetingController",[536,1297,1298],{"class":944}," implements",[536,1300,1226],{"class":542},[536,1302,1303],{"class":650},"\u003C",[536,1305,1306],{"class":542},"GreetingApi",[536,1308,1309],{"class":650},">",[536,1311,983],{"class":650},[536,1313,1314,1317,1319,1322,1325,1329,1331,1333,1335],{"class":538,"line":822},[536,1315,1316],{"class":944},"  constructor",[536,1318,647],{"class":650},[536,1320,1321],{"class":944},"private",[536,1323,1324],{"class":944}," readonly",[536,1326,1328],{"class":1327},"sHdIc"," greetings",[536,1330,661],{"class":650},[536,1332,1269],{"class":542},[536,1334,721],{"class":650},[536,1336,1337],{"class":650}," {}\n",[536,1339,1340],{"class":538,"line":986},[536,1341,783],{"emptyLinePlaceholder":782},[536,1343,1344,1347,1350,1353,1355,1358,1360,1362,1364,1366,1368,1370,1373,1375,1378],{"class":538,"line":1046},[536,1345,1346],{"class":944},"  public",[536,1348,1349],{"class":944}," async",[536,1351,1352],{"class":657}," signIn",[536,1354,647],{"class":650},[536,1356,1357],{"class":1327},"action",[536,1359,661],{"class":650},[536,1361,1221],{"class":542},[536,1363,1303],{"class":650},[536,1365,1306],{"class":542},[536,1367,815],{"class":650},[536,1369,664],{"class":650},[536,1371,1372],{"class":545},"signIn",[536,1374,670],{"class":650},[536,1376,1377],{"class":650},">)",[536,1379,983],{"class":650},[536,1381,1382,1385,1388,1391,1394,1397,1399,1402,1404,1407,1410],{"class":538,"line":1092},[536,1383,1384],{"class":944},"    const",[536,1386,1387],{"class":646}," payload",[536,1389,1390],{"class":650}," =",[536,1392,1393],{"class":635}," await",[536,1395,1396],{"class":646}," action",[536,1398,996],{"class":650},[536,1400,1401],{"class":646},"request",[536,1403,996],{"class":650},[536,1405,1406],{"class":642},"readValidatedBody",[536,1408,1409],{"class":657},"()",[536,1411,724],{"class":650},[536,1413,1414],{"class":538,"line":1139},[536,1415,783],{"emptyLinePlaceholder":782},[536,1417,1418,1421,1423,1426,1428,1431,1433,1436,1438,1441,1443,1446,1448,1451,1453,1456,1458,1460],{"class":538,"line":1145},[536,1419,1420],{"class":646},"    action",[536,1422,996],{"class":650},[536,1424,1425],{"class":646},"response",[536,1427,996],{"class":650},[536,1429,1430],{"class":642},"setCookie",[536,1432,647],{"class":657},[536,1434,1435],{"class":646},"GreetingService",[536,1437,996],{"class":650},[536,1439,1440],{"class":646},"visitorCookieName",[536,1442,815],{"class":650},[536,1444,1445],{"class":642}," encodeURIComponent",[536,1447,647],{"class":657},[536,1449,1450],{"class":646},"payload",[536,1452,996],{"class":650},[536,1454,1455],{"class":646},"name",[536,1457,721],{"class":657},[536,1459,815],{"class":650},[536,1461,983],{"class":650},[536,1463,1465,1468,1470,1474],{"class":538,"line":1464},12,[536,1466,1467],{"class":657},"      httpOnly",[536,1469,661],{"class":650},[536,1471,1473],{"class":1472},"sfNiH"," true",[536,1475,673],{"class":650},[536,1477,1479,1482,1484,1486,1489,1491],{"class":538,"line":1478},13,[536,1480,1481],{"class":657},"      sameSite",[536,1483,661],{"class":650},[536,1485,664],{"class":650},[536,1487,1488],{"class":545},"lax",[536,1490,670],{"class":650},[536,1492,673],{"class":650},[536,1494,1496,1499,1501,1503,1506,1508],{"class":538,"line":1495},14,[536,1497,1498],{"class":657},"      path",[536,1500,661],{"class":650},[536,1502,664],{"class":650},[536,1504,1505],{"class":545},"\u002F",[536,1507,670],{"class":650},[536,1509,673],{"class":650},[536,1511,1513,1516,1518,1521,1524,1526,1528,1531],{"class":538,"line":1512},15,[536,1514,1515],{"class":657},"      maxAge",[536,1517,661],{"class":650},[536,1519,1520],{"class":1031}," 60",[536,1522,1523],{"class":650}," *",[536,1525,1520],{"class":1031},[536,1527,1523],{"class":650},[536,1529,1530],{"class":1031}," 24",[536,1532,673],{"class":650},[536,1534,1536,1539,1541],{"class":538,"line":1535},16,[536,1537,1538],{"class":650},"    }",[536,1540,721],{"class":657},[536,1542,724],{"class":650},[536,1544,1546],{"class":538,"line":1545},17,[536,1547,783],{"emptyLinePlaceholder":782},[536,1549,1551,1554,1556,1559,1561,1563,1565,1567],{"class":538,"line":1550},18,[536,1552,1553],{"class":635},"    return",[536,1555,737],{"class":650},[536,1557,1558],{"class":657}," name",[536,1560,661],{"class":650},[536,1562,1387],{"class":646},[536,1564,996],{"class":650},[536,1566,1455],{"class":646},[536,1568,1569],{"class":650}," };\n",[536,1571,1573],{"class":538,"line":1572},19,[536,1574,1575],{"class":650},"  }\n",[536,1577,1579],{"class":538,"line":1578},20,[536,1580,783],{"emptyLinePlaceholder":782},[536,1582,1584,1586,1588,1591,1593,1595,1597,1599,1601,1603,1605,1607,1610,1612,1614],{"class":538,"line":1583},21,[536,1585,1346],{"class":944},[536,1587,1349],{"class":944},[536,1589,1590],{"class":657}," profile",[536,1592,647],{"class":650},[536,1594,1357],{"class":1327},[536,1596,661],{"class":650},[536,1598,1221],{"class":542},[536,1600,1303],{"class":650},[536,1602,1306],{"class":542},[536,1604,815],{"class":650},[536,1606,664],{"class":650},[536,1608,1609],{"class":545},"profile",[536,1611,670],{"class":650},[536,1613,1377],{"class":650},[536,1615,983],{"class":650},[536,1617,1619,1621,1624,1626,1628,1630,1632,1634,1637,1639,1641,1643,1645,1647],{"class":538,"line":1618},22,[536,1620,1384],{"class":944},[536,1622,1623],{"class":646}," rawCookie",[536,1625,1390],{"class":650},[536,1627,1396],{"class":646},[536,1629,996],{"class":650},[536,1631,1401],{"class":646},[536,1633,996],{"class":650},[536,1635,1636],{"class":642},"getCookie",[536,1638,647],{"class":657},[536,1640,1435],{"class":646},[536,1642,996],{"class":650},[536,1644,1440],{"class":646},[536,1646,721],{"class":657},[536,1648,724],{"class":650},[536,1650,1652],{"class":538,"line":1651},23,[536,1653,783],{"emptyLinePlaceholder":782},[536,1655,1657,1660,1663,1666,1669,1672,1675,1677,1679,1682,1684],{"class":538,"line":1656},24,[536,1658,1659],{"class":635},"    if",[536,1661,1662],{"class":657}," (",[536,1664,1665],{"class":646},"rawCookie",[536,1667,1668],{"class":650}," ===",[536,1670,1671],{"class":650}," undefined",[536,1673,1674],{"class":650}," ||",[536,1676,1623],{"class":646},[536,1678,1668],{"class":650},[536,1680,1681],{"class":650}," \"\"",[536,1683,1150],{"class":657},[536,1685,651],{"class":650},[536,1687,1689,1692,1695,1698,1700,1703,1705],{"class":538,"line":1688},25,[536,1690,1691],{"class":635},"      return",[536,1693,1694],{"class":650}," this.",[536,1696,1697],{"class":646},"greetings",[536,1699,996],{"class":650},[536,1701,1702],{"class":642},"signedOutProfile",[536,1704,1409],{"class":657},[536,1706,724],{"class":650},[536,1708,1710],{"class":538,"line":1709},26,[536,1711,1712],{"class":650},"    }\n",[536,1714,1716],{"class":538,"line":1715},27,[536,1717,783],{"emptyLinePlaceholder":782},[536,1719,1721,1723,1725,1727,1729,1732,1734,1737,1739,1741,1744],{"class":538,"line":1720},28,[536,1722,1553],{"class":635},[536,1724,1694],{"class":650},[536,1726,1697],{"class":646},[536,1728,996],{"class":650},[536,1730,1731],{"class":642},"signedInProfile",[536,1733,647],{"class":657},[536,1735,1736],{"class":642},"decodeURIComponent",[536,1738,647],{"class":657},[536,1740,1665],{"class":646},[536,1742,1743],{"class":657},"))",[536,1745,724],{"class":650},[536,1747,1749],{"class":538,"line":1748},29,[536,1750,1575],{"class":650},[536,1752,1754],{"class":538,"line":1753},30,[536,1755,1756],{"class":650},"}\n",[499,1758,1759,1761,1762,1764,1765,1768],{},[503,1760,1372],{}," validates the request body against the contract's own ",[503,1763,1158],{}," before the handler runs — an\ninvalid body is rejected with a ",[503,1766,1767],{},"400 application\u002Fproblem+json"," before your code runs. This is exactly the\ncontroller you'd write for the Vite or Nitro hosts; nothing about it is Nuxt-specific.",[512,1770,1772],{"id":1771},"declare-the-module","Declare the module",[499,1774,1775,1776,1778],{},"A module lists what it owns. The ",[503,1777,1435],{}," is a plain provider; the controller is named under the\nHTTP plugin's namespace. The compiler reads this config plus the controller's constructor and generates the\nwiring — there's no runtime container resolving anything by reflection.",[526,1780,1783],{"className":626,"code":1781,"filename":1782,"language":628,"meta":532,"style":532},"import { Module } from \"@heximon\u002Fruntime\";\nimport { GreetingController } from \".\u002Fgreeting.controller\";\nimport { GreetingService } from \".\u002Fgreeting.service\";\n\nexport class GreetingModule extends Module({\n  providers: [GreetingService],\n  http: { controllers: [GreetingController] },\n}) {}\n","server\u002Fgreeting\u002Fgreeting.module.ts",[503,1784,1785,1807,1828,1848,1852,1869,1881,1901],{"__ignoreMap":532},[536,1786,1787,1789,1791,1794,1796,1798,1800,1803,1805],{"class":538,"line":539},[536,1788,734],{"class":635},[536,1790,737],{"class":650},[536,1792,1793],{"class":646}," Module",[536,1795,743],{"class":650},[536,1797,746],{"class":635},[536,1799,664],{"class":650},[536,1801,1802],{"class":545},"@heximon\u002Fruntime",[536,1804,670],{"class":650},[536,1806,724],{"class":650},[536,1808,1809,1811,1813,1815,1817,1819,1821,1824,1826],{"class":538,"line":654},[536,1810,734],{"class":635},[536,1812,737],{"class":650},[536,1814,1295],{"class":646},[536,1816,743],{"class":650},[536,1818,746],{"class":635},[536,1820,664],{"class":650},[536,1822,1823],{"class":545},".\u002Fgreeting.controller",[536,1825,670],{"class":650},[536,1827,724],{"class":650},[536,1829,1830,1832,1834,1836,1838,1840,1842,1844,1846],{"class":538,"line":676},[536,1831,734],{"class":635},[536,1833,737],{"class":650},[536,1835,1269],{"class":646},[536,1837,743],{"class":650},[536,1839,746],{"class":635},[536,1841,664],{"class":650},[536,1843,1278],{"class":545},[536,1845,670],{"class":650},[536,1847,724],{"class":650},[536,1849,1850],{"class":538,"line":693},[536,1851,783],{"emptyLinePlaceholder":782},[536,1853,1854,1856,1858,1861,1863,1865,1867],{"class":538,"line":715},[536,1855,636],{"class":635},[536,1857,945],{"class":944},[536,1859,1860],{"class":542}," GreetingModule",[536,1862,951],{"class":944},[536,1864,1793],{"class":642},[536,1866,647],{"class":646},[536,1868,651],{"class":650},[536,1870,1871,1874,1876,1879],{"class":538,"line":822},[536,1872,1873],{"class":657},"  providers",[536,1875,661],{"class":650},[536,1877,1878],{"class":646}," [GreetingService]",[536,1880,673],{"class":650},[536,1882,1883,1886,1888,1890,1893,1895,1898],{"class":538,"line":986},[536,1884,1885],{"class":657},"  http",[536,1887,661],{"class":650},[536,1889,737],{"class":650},[536,1891,1892],{"class":657}," controllers",[536,1894,661],{"class":650},[536,1896,1897],{"class":646}," [GreetingController] ",[536,1899,1900],{"class":650},"},\n",[536,1902,1903,1905,1907],{"class":538,"line":1046},[536,1904,718],{"class":650},[536,1906,1150],{"class":646},[536,1908,1153],{"class":650},[499,1910,1911,1912,1914,1915,1918],{},"A root module under ",[503,1913,509],{}," composes your feature modules with ",[503,1916,1917],{},"imports",", and the compiler picks it up as\nthe app — the same root-module convention every Heximon host uses.",[526,1920,1923],{"className":626,"code":1921,"filename":1922,"language":628,"meta":532,"style":532},"import { Module } from \"@heximon\u002Fruntime\";\nimport { GreetingModule } from \".\u002Fgreeting\u002Fgreeting.module\";\n\nexport class AppModule extends Module({\n  imports: [GreetingModule],\n}) {}\n","server\u002Fapp.module.ts",[503,1924,1925,1945,1966,1970,1987,1999],{"__ignoreMap":532},[536,1926,1927,1929,1931,1933,1935,1937,1939,1941,1943],{"class":538,"line":539},[536,1928,734],{"class":635},[536,1930,737],{"class":650},[536,1932,1793],{"class":646},[536,1934,743],{"class":650},[536,1936,746],{"class":635},[536,1938,664],{"class":650},[536,1940,1802],{"class":545},[536,1942,670],{"class":650},[536,1944,724],{"class":650},[536,1946,1947,1949,1951,1953,1955,1957,1959,1962,1964],{"class":538,"line":654},[536,1948,734],{"class":635},[536,1950,737],{"class":650},[536,1952,1860],{"class":646},[536,1954,743],{"class":650},[536,1956,746],{"class":635},[536,1958,664],{"class":650},[536,1960,1961],{"class":545},".\u002Fgreeting\u002Fgreeting.module",[536,1963,670],{"class":650},[536,1965,724],{"class":650},[536,1967,1968],{"class":538,"line":676},[536,1969,783],{"emptyLinePlaceholder":782},[536,1971,1972,1974,1976,1979,1981,1983,1985],{"class":538,"line":693},[536,1973,636],{"class":635},[536,1975,945],{"class":944},[536,1977,1978],{"class":542}," AppModule",[536,1980,951],{"class":944},[536,1982,1793],{"class":642},[536,1984,647],{"class":646},[536,1986,651],{"class":650},[536,1988,1989,1992,1994,1997],{"class":538,"line":715},[536,1990,1991],{"class":657},"  imports",[536,1993,661],{"class":650},[536,1995,1996],{"class":646}," [GreetingModule]",[536,1998,673],{"class":650},[536,2000,2001,2003,2005],{"class":538,"line":822},[536,2002,718],{"class":650},[536,2004,1150],{"class":646},[536,2006,1153],{"class":650},[499,2008,2009,2010,2012],{},"The full project then has a clean front\u002Fback split, with ",[503,2011,858],{}," bridging the two:",[526,2014,2019],{"className":2015,"code":2017,"language":2018},[2016],"language-text","app\u002F                          # Vue frontend (srcDir)\n├── app.vue                   # \u003CNuxtPage \u002F> shell — pages mode\n├── plugins\u002F\n│   └── vue-query.ts          # installs TanStack Vue Query (SSR dehydrate\u002Fhydrate)\n└── pages\u002F\n    ├── index.vue              # useFetch\u002F$fetch against \u002Fapi\u002F*\n    └── typed.vue               # the typed contract client + vue-query (see below)\nshared\u002F                       # Nuxt's app-and-server directory — the contract lives here\n└── greeting\u002F\n    ├── schemas.ts             # Standard Schema validators\n    └── contract.ts             # GreetingApi extends Contract({ prefix: \"\u002Fapi\", routes: {...} })\nserver\u002F                       # Heximon modules — compiled by the Nuxt module\n├── app.module.ts\n└── greeting\u002F\n    ├── greeting.module.ts\n    ├── greeting.controller.ts\n    └── greeting.service.ts\nnuxt.config.ts\n","text",[503,2020,2017],{"__ignoreMap":532},[512,2022,2024],{"id":2023},"call-the-api-from-a-vue-page","Call the API from a Vue page",[499,2026,2027,2028,2031,2032,2035,2036,2038],{},"The frontend calls your routes with Nuxt's own ",[503,2029,2030],{},"useFetch"," \u002F ",[503,2033,2034],{},"$fetch"," — they hit the in-process Heximon API on\nthe same server, so there's no base URL and no CORS to think about. The payoff lands during SSR: when\n",[503,2037,2030],{}," runs on the server, Nuxt forwards the incoming request's cookies to your Heximon route, so the\nsigned-in greeting is computed server-side and ships inside the initial HTML.",[526,2040,2045],{"className":2041,"code":2042,"filename":2043,"language":2044,"meta":532,"style":532},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\ntype Profile = { signedIn: true; name: string; greeting: string } | { signedIn: false };\n\nconst name = ref(\"Alice\");\n\n\u002F\u002F Runs during SSR: Nuxt forwards the request's cookies to the in-process Heximon API,\n\u002F\u002F so a signed-in visitor's greeting is already in the HTML when the page loads.\nconst { data: profile, refresh } = await useFetch\u003CProfile>(\"\u002Fapi\u002Fprofile\");\n\nasync function signIn(): Promise\u003Cvoid> {\n  await $fetch(\"\u002Fapi\u002Fsign-in\", { method: \"POST\", body: { name: name.value } });\n  await refresh();\n}\n\u003C\u002Fscript>\n","app\u002Fpages\u002Findex.vue","vue",[503,2046,2047,2072,2126,2130,2156,2160,2165,2170,2217,2221,2246,2307,2318,2322],{"__ignoreMap":532},[536,2048,2049,2051,2054,2057,2060,2063,2065,2067,2069],{"class":538,"line":539},[536,2050,1303],{"class":650},[536,2052,2053],{"class":657},"script",[536,2055,2056],{"class":944}," setup",[536,2058,2059],{"class":944}," lang",[536,2061,2062],{"class":650},"=",[536,2064,670],{"class":650},[536,2066,628],{"class":545},[536,2068,670],{"class":650},[536,2070,2071],{"class":650},">\n",[536,2073,2074,2077,2080,2082,2084,2087,2089,2091,2094,2096,2098,2101,2103,2106,2108,2110,2112,2115,2117,2119,2121,2124],{"class":538,"line":654},[536,2075,2076],{"class":944},"type",[536,2078,2079],{"class":542}," Profile",[536,2081,1390],{"class":650},[536,2083,737],{"class":650},[536,2085,2086],{"class":657}," signedIn",[536,2088,661],{"class":650},[536,2090,1473],{"class":542},[536,2092,2093],{"class":650},";",[536,2095,1558],{"class":657},[536,2097,661],{"class":650},[536,2099,2100],{"class":542}," string",[536,2102,2093],{"class":650},[536,2104,2105],{"class":657}," greeting",[536,2107,661],{"class":650},[536,2109,2100],{"class":542},[536,2111,743],{"class":650},[536,2113,2114],{"class":650}," |",[536,2116,737],{"class":650},[536,2118,2086],{"class":657},[536,2120,661],{"class":650},[536,2122,2123],{"class":542}," false",[536,2125,1569],{"class":650},[536,2127,2128],{"class":538,"line":676},[536,2129,783],{"emptyLinePlaceholder":782},[536,2131,2132,2135,2138,2140,2143,2145,2147,2150,2152,2154],{"class":538,"line":693},[536,2133,2134],{"class":944},"const",[536,2136,2137],{"class":646}," name ",[536,2139,2062],{"class":650},[536,2141,2142],{"class":642}," ref",[536,2144,647],{"class":646},[536,2146,670],{"class":650},[536,2148,2149],{"class":545},"Alice",[536,2151,670],{"class":650},[536,2153,721],{"class":646},[536,2155,724],{"class":650},[536,2157,2158],{"class":538,"line":715},[536,2159,783],{"emptyLinePlaceholder":782},[536,2161,2162],{"class":538,"line":822},[536,2163,2164],{"class":818},"\u002F\u002F Runs during SSR: Nuxt forwards the request's cookies to the in-process Heximon API,\n",[536,2166,2167],{"class":538,"line":986},[536,2168,2169],{"class":818},"\u002F\u002F so a signed-in visitor's greeting is already in the HTML when the page loads.\n",[536,2171,2172,2174,2176,2179,2181,2183,2185,2188,2190,2192,2194,2197,2199,2202,2204,2206,2208,2211,2213,2215],{"class":538,"line":1046},[536,2173,2134],{"class":944},[536,2175,737],{"class":650},[536,2177,2178],{"class":657}," data",[536,2180,661],{"class":650},[536,2182,1590],{"class":646},[536,2184,815],{"class":650},[536,2186,2187],{"class":646}," refresh ",[536,2189,718],{"class":650},[536,2191,1390],{"class":650},[536,2193,1393],{"class":635},[536,2195,2196],{"class":642}," useFetch",[536,2198,1303],{"class":650},[536,2200,2201],{"class":542},"Profile",[536,2203,1309],{"class":650},[536,2205,647],{"class":646},[536,2207,670],{"class":650},[536,2209,2210],{"class":545},"\u002Fapi\u002Fprofile",[536,2212,670],{"class":650},[536,2214,721],{"class":646},[536,2216,724],{"class":650},[536,2218,2219],{"class":538,"line":1092},[536,2220,783],{"emptyLinePlaceholder":782},[536,2222,2223,2226,2229,2231,2234,2237,2239,2242,2244],{"class":538,"line":1139},[536,2224,2225],{"class":944},"async",[536,2227,2228],{"class":944}," function",[536,2230,1352],{"class":642},[536,2232,2233],{"class":650},"():",[536,2235,2236],{"class":542}," Promise",[536,2238,1303],{"class":650},[536,2240,2241],{"class":542},"void",[536,2243,1309],{"class":650},[536,2245,983],{"class":650},[536,2247,2248,2251,2254,2256,2258,2261,2263,2265,2267,2270,2272,2274,2277,2279,2281,2284,2286,2288,2290,2292,2294,2296,2299,2301,2303,2305],{"class":538,"line":1145},[536,2249,2250],{"class":635},"  await",[536,2252,2253],{"class":642}," $fetch",[536,2255,647],{"class":657},[536,2257,670],{"class":650},[536,2259,2260],{"class":545},"\u002Fapi\u002Fsign-in",[536,2262,670],{"class":650},[536,2264,815],{"class":650},[536,2266,737],{"class":650},[536,2268,2269],{"class":657}," method",[536,2271,661],{"class":650},[536,2273,664],{"class":650},[536,2275,2276],{"class":545},"POST",[536,2278,670],{"class":650},[536,2280,815],{"class":650},[536,2282,2283],{"class":657}," body",[536,2285,661],{"class":650},[536,2287,737],{"class":650},[536,2289,1558],{"class":657},[536,2291,661],{"class":650},[536,2293,1558],{"class":646},[536,2295,996],{"class":650},[536,2297,2298],{"class":646},"value",[536,2300,743],{"class":650},[536,2302,743],{"class":650},[536,2304,721],{"class":657},[536,2306,724],{"class":650},[536,2308,2309,2311,2314,2316],{"class":538,"line":1464},[536,2310,2250],{"class":635},[536,2312,2313],{"class":642}," refresh",[536,2315,1409],{"class":657},[536,2317,724],{"class":650},[536,2319,2320],{"class":538,"line":1478},[536,2321,1756],{"class":650},[536,2323,2324,2327,2329],{"class":538,"line":1495},[536,2325,2326],{"class":650},"\u003C\u002F",[536,2328,2053],{"class":657},[536,2330,2071],{"class":650},[499,2332,2333],{},"To see that the work really happened on the server, sign in, then reload the page with JavaScript disabled\nin DevTools — the personalized greeting is still there, because it came from the cookie during SSR, not from\na client-side fetch. That's the whole reason to host the API in-process: shared cookies, no auth round-trip\nto a separate origin, and authenticated state in the first paint.",[499,2335,2336,1505,2338,2340],{},[503,2337,2030],{},[503,2339,2034],{}," is the simple default — the next section reads the exact same routes through the typed\ncontract client instead.",[512,2342,2344],{"id":2343},"call-the-api-with-the-typed-contract-client","Call the API with the typed contract client",[499,2346,2347,2349,2350,2353,2354,2357],{},[503,2348,1306],{}," isn't only a server binding — the Vue app can construct it directly as its client\n(",[503,2351,2352],{},"new GreetingApi(transport)",", from ",[503,2355,2356],{},"@heximon\u002Fclient","), so request and response types come from the\ncontract, with nothing hand-written and nothing to keep in sync when a route changes.",[523,2359,2360,2377,2392],{},[526,2361,2363],{"className":528,"code":2362,"filename":530,"language":531,"meta":532,"style":532},"pnpm add @heximon\u002Fclient @tanstack\u002Fvue-query\n",[503,2364,2365],{"__ignoreMap":532},[536,2366,2367,2369,2371,2374],{"class":538,"line":539},[536,2368,530],{"class":542},[536,2370,546],{"class":545},[536,2372,2373],{"class":545}," @heximon\u002Fclient",[536,2375,2376],{"class":545}," @tanstack\u002Fvue-query\n",[526,2378,2380],{"className":528,"code":2379,"filename":556,"language":531,"meta":532,"style":532},"npm install @heximon\u002Fclient @tanstack\u002Fvue-query\n",[503,2381,2382],{"__ignoreMap":532},[536,2383,2384,2386,2388,2390],{"class":538,"line":539},[536,2385,556],{"class":542},[536,2387,565],{"class":545},[536,2389,2373],{"class":545},[536,2391,2376],{"class":545},[526,2393,2395],{"className":528,"code":2394,"filename":573,"language":531,"meta":532,"style":532},"yarn add @heximon\u002Fclient @tanstack\u002Fvue-query\n",[503,2396,2397],{"__ignoreMap":532},[536,2398,2399,2401,2403,2405],{"class":538,"line":539},[536,2400,573],{"class":542},[536,2402,546],{"class":545},[536,2404,2373],{"class":545},[536,2406,2376],{"class":545},[499,2408,2409,2412,2413,2416,2417,2419,2420,2422,2423,2426,2427,2430],{},[503,2410,2411],{},"@tanstack\u002Fvue-query"," is only needed for the reactive ",[503,2414,2415],{},"vue-query"," bindings below — the plain typed call\nneeds just ",[503,2418,2356],{},". See ",[1161,2421,72],{"href":73}," for the full ",[503,2424,2425],{},"ClientTransport"," \u002F\n",[503,2428,2429],{},"raw()"," \u002F interceptor reference; this section covers what's Nuxt-specific: SSR cookie forwarding, and how the\ntyped client interacts with Nuxt's own data fetching.",[499,2432,2433,2436,2437,2440,2441,2444,2445,2448],{},[503,2434,2435],{},"ClientTransport.fetch"," takes only ",[503,2438,2439],{},"{ baseUrl?, fetch? }"," — no header option — so forwarding the visitor's\ncookie during SSR rides the ",[612,2442,2443],{},"contract's own"," ",[503,2446,2447],{},"ClientOptions.headers"," (the second constructor argument)\ninstead:",[526,2450,2453],{"className":626,"code":2451,"filename":2452,"language":628,"meta":532,"style":532},"import { ClientTransport } from \"@heximon\u002Fclient\";\nimport { GreetingApi } from \"..\u002F..\u002Fshared\u002Fgreeting\u002Fcontract\";\n\nconst requestUrl = useRequestURL();\nconst forwardedCookie = useRequestHeaders([\"cookie\"]).cookie;\nconst transport = ClientTransport.fetch({ baseUrl: requestUrl.origin });\nconst clientOptions = forwardedCookie ? { headers: { cookie: forwardedCookie } } : undefined;\n\nconst api = new GreetingApi(transport, clientOptions);\n","app\u002Fpages\u002Ftyped.vue",[503,2454,2455,2476,2496,2500,2516,2547,2586,2626,2630],{"__ignoreMap":532},[536,2456,2457,2459,2461,2464,2466,2468,2470,2472,2474],{"class":538,"line":539},[536,2458,734],{"class":635},[536,2460,737],{"class":650},[536,2462,2463],{"class":646}," ClientTransport",[536,2465,743],{"class":650},[536,2467,746],{"class":635},[536,2469,664],{"class":650},[536,2471,2356],{"class":545},[536,2473,670],{"class":650},[536,2475,724],{"class":650},[536,2477,2478,2480,2482,2484,2486,2488,2490,2492,2494],{"class":538,"line":654},[536,2479,734],{"class":635},[536,2481,737],{"class":650},[536,2483,948],{"class":646},[536,2485,743],{"class":650},[536,2487,746],{"class":635},[536,2489,664],{"class":650},[536,2491,1256],{"class":545},[536,2493,670],{"class":650},[536,2495,724],{"class":650},[536,2497,2498],{"class":538,"line":676},[536,2499,783],{"emptyLinePlaceholder":782},[536,2501,2502,2504,2507,2509,2512,2514],{"class":538,"line":693},[536,2503,2134],{"class":944},[536,2505,2506],{"class":646}," requestUrl ",[536,2508,2062],{"class":650},[536,2510,2511],{"class":642}," useRequestURL",[536,2513,1409],{"class":646},[536,2515,724],{"class":650},[536,2517,2518,2520,2523,2525,2528,2531,2533,2536,2538,2541,2543,2545],{"class":538,"line":715},[536,2519,2134],{"class":944},[536,2521,2522],{"class":646}," forwardedCookie ",[536,2524,2062],{"class":650},[536,2526,2527],{"class":642}," useRequestHeaders",[536,2529,2530],{"class":646},"([",[536,2532,670],{"class":650},[536,2534,2535],{"class":545},"cookie",[536,2537,670],{"class":650},[536,2539,2540],{"class":646},"])",[536,2542,996],{"class":650},[536,2544,2535],{"class":646},[536,2546,724],{"class":650},[536,2548,2549,2551,2554,2556,2558,2560,2563,2565,2567,2570,2572,2575,2577,2580,2582,2584],{"class":538,"line":822},[536,2550,2134],{"class":944},[536,2552,2553],{"class":646}," transport ",[536,2555,2062],{"class":650},[536,2557,2463],{"class":646},[536,2559,996],{"class":650},[536,2561,2562],{"class":642},"fetch",[536,2564,647],{"class":646},[536,2566,1028],{"class":650},[536,2568,2569],{"class":657}," baseUrl",[536,2571,661],{"class":650},[536,2573,2574],{"class":646}," requestUrl",[536,2576,996],{"class":650},[536,2578,2579],{"class":646},"origin ",[536,2581,718],{"class":650},[536,2583,721],{"class":646},[536,2585,724],{"class":650},[536,2587,2588,2590,2593,2595,2597,2600,2602,2605,2607,2609,2612,2614,2616,2618,2620,2623],{"class":538,"line":986},[536,2589,2134],{"class":944},[536,2591,2592],{"class":646}," clientOptions ",[536,2594,2062],{"class":650},[536,2596,2522],{"class":646},[536,2598,2599],{"class":650},"?",[536,2601,737],{"class":650},[536,2603,2604],{"class":657}," headers",[536,2606,661],{"class":650},[536,2608,737],{"class":650},[536,2610,2611],{"class":657}," cookie",[536,2613,661],{"class":650},[536,2615,2522],{"class":646},[536,2617,718],{"class":650},[536,2619,743],{"class":650},[536,2621,2622],{"class":650}," :",[536,2624,2625],{"class":650}," undefined;\n",[536,2627,2628],{"class":538,"line":1046},[536,2629,783],{"emptyLinePlaceholder":782},[536,2631,2632,2634,2637,2639,2642,2644,2647,2649,2652],{"class":538,"line":1092},[536,2633,2134],{"class":944},[536,2635,2636],{"class":646}," api ",[536,2638,2062],{"class":650},[536,2640,2641],{"class":650}," new",[536,2643,948],{"class":642},[536,2645,2646],{"class":646},"(transport",[536,2648,815],{"class":650},[536,2650,2651],{"class":646}," clientOptions)",[536,2653,724],{"class":650},[499,2655,2656,2659,2660,2663,2664,2667,2668,2671,2672,2674],{},[503,2657,2658],{},"useRequestURL()"," gives an absolute origin on both server and client — a plain ",[503,2661,2662],{},"fetch()"," can't resolve a\nrelative URL during SSR the way a browser resolves one against the page location. ",[503,2665,2666],{},"useRequestHeaders"," returns\n",[503,2669,2670],{},"{}"," on the client, so the cookie forwarding is a no-op there — the browser's own ",[503,2673,2662],{}," already carries\ncookies for a same-origin request.",[499,2676,2677,2683,2684,2686,2687,2689,2690,661],{},[612,2678,2679,2680,996],{},"SSR-aware, with ",[503,2681,2682],{},"useAsyncData"," Nuxt's own data-fetching composable accepts any async function, not only\n",[503,2685,2034],{},", so it carries the typed call's result through the SSR payload exactly like the previous section's\n",[503,2688,2030],{}," — but typed end-to-end through ",[503,2691,1306],{},[526,2693,2695],{"className":626,"code":2694,"language":628,"meta":532,"style":532},"const { data: ssrProfile, refresh: refreshSsrProfile } = await useAsyncData(\"greeting-profile-typed\", () =>\n  api.client.profile(),\n);\n",[503,2696,2697,2745,2763],{"__ignoreMap":532},[536,2698,2699,2701,2703,2705,2707,2710,2712,2714,2716,2719,2721,2723,2725,2728,2730,2732,2735,2737,2739,2742],{"class":538,"line":539},[536,2700,2134],{"class":944},[536,2702,737],{"class":650},[536,2704,2178],{"class":657},[536,2706,661],{"class":650},[536,2708,2709],{"class":646}," ssrProfile",[536,2711,815],{"class":650},[536,2713,2313],{"class":657},[536,2715,661],{"class":650},[536,2717,2718],{"class":646}," refreshSsrProfile ",[536,2720,718],{"class":650},[536,2722,1390],{"class":650},[536,2724,1393],{"class":635},[536,2726,2727],{"class":642}," useAsyncData",[536,2729,647],{"class":646},[536,2731,670],{"class":650},[536,2733,2734],{"class":545},"greeting-profile-typed",[536,2736,670],{"class":650},[536,2738,815],{"class":650},[536,2740,2741],{"class":650}," ()",[536,2743,2744],{"class":944}," =>\n",[536,2746,2747,2750,2752,2755,2757,2759,2761],{"class":538,"line":654},[536,2748,2749],{"class":646},"  api",[536,2751,996],{"class":650},[536,2753,2754],{"class":646},"client",[536,2756,996],{"class":650},[536,2758,1609],{"class":642},[536,2760,1409],{"class":646},[536,2762,673],{"class":650},[536,2764,2765,2767],{"class":538,"line":676},[536,2766,721],{"class":646},[536,2768,724],{"class":650},[499,2770,2771,2444,2777,2780,2781,2784,2785,2787],{},[612,2772,2773,2774,996],{},"Client-reactive, with ",[503,2775,2776],{},"@heximon\u002Fclient\u002Fvue-query",[503,2778,2779],{},"VueQuery.initClient"," builds one TanStack Vue Query\nbinding per contract route off the same contract instance — reusing ",[503,2782,2783],{},"api"," above keeps the whole page to one\n",[503,2786,1306],{}," instance:",[526,2789,2791],{"className":626,"code":2790,"language":628,"meta":532,"style":532},"const vueQuery = VueQuery.initClient(api);\nconst reactiveProfile = vueQuery.profile.useQuery([\"greeting\", \"profile\"]);\n\nconst signIn = vueQuery.signIn.useMutation({ onSuccess: refreshBothProfiles });\nconst signOut = vueQuery.signOut.useMutation({ onSuccess: refreshBothProfiles });\n",[503,2792,2793,2815,2857,2861,2899],{"__ignoreMap":532},[536,2794,2795,2797,2800,2802,2805,2807,2810,2813],{"class":538,"line":539},[536,2796,2134],{"class":944},[536,2798,2799],{"class":646}," vueQuery ",[536,2801,2062],{"class":650},[536,2803,2804],{"class":646}," VueQuery",[536,2806,996],{"class":650},[536,2808,2809],{"class":642},"initClient",[536,2811,2812],{"class":646},"(api)",[536,2814,724],{"class":650},[536,2816,2817,2819,2822,2824,2827,2829,2831,2833,2836,2838,2840,2843,2845,2847,2849,2851,2853,2855],{"class":538,"line":654},[536,2818,2134],{"class":944},[536,2820,2821],{"class":646}," reactiveProfile ",[536,2823,2062],{"class":650},[536,2825,2826],{"class":646}," vueQuery",[536,2828,996],{"class":650},[536,2830,1609],{"class":646},[536,2832,996],{"class":650},[536,2834,2835],{"class":642},"useQuery",[536,2837,2530],{"class":646},[536,2839,670],{"class":650},[536,2841,2842],{"class":545},"greeting",[536,2844,670],{"class":650},[536,2846,815],{"class":650},[536,2848,664],{"class":650},[536,2850,1609],{"class":545},[536,2852,670],{"class":650},[536,2854,2540],{"class":646},[536,2856,724],{"class":650},[536,2858,2859],{"class":538,"line":676},[536,2860,783],{"emptyLinePlaceholder":782},[536,2862,2863,2865,2868,2870,2872,2874,2876,2878,2881,2883,2885,2888,2890,2893,2895,2897],{"class":538,"line":693},[536,2864,2134],{"class":944},[536,2866,2867],{"class":646}," signIn ",[536,2869,2062],{"class":650},[536,2871,2826],{"class":646},[536,2873,996],{"class":650},[536,2875,1372],{"class":646},[536,2877,996],{"class":650},[536,2879,2880],{"class":642},"useMutation",[536,2882,647],{"class":646},[536,2884,1028],{"class":650},[536,2886,2887],{"class":657}," onSuccess",[536,2889,661],{"class":650},[536,2891,2892],{"class":646}," refreshBothProfiles ",[536,2894,718],{"class":650},[536,2896,721],{"class":646},[536,2898,724],{"class":650},[536,2900,2901,2903,2906,2908,2910,2912,2915,2917,2919,2921,2923,2925,2927,2929,2931,2933],{"class":538,"line":715},[536,2902,2134],{"class":944},[536,2904,2905],{"class":646}," signOut ",[536,2907,2062],{"class":650},[536,2909,2826],{"class":646},[536,2911,996],{"class":650},[536,2913,2914],{"class":646},"signOut",[536,2916,996],{"class":650},[536,2918,2880],{"class":642},[536,2920,647],{"class":646},[536,2922,1028],{"class":650},[536,2924,2887],{"class":657},[536,2926,661],{"class":650},[536,2928,2892],{"class":646},[536,2930,718],{"class":650},[536,2932,721],{"class":646},[536,2934,724],{"class":650},[499,2936,2937,2940,2941,2944,2945,2947,2948,2951,2952,2955,2956,2959,2960,2963,2964,2967,2968,2971,2972,2974],{},[503,2938,2939],{},"refreshBothProfiles"," is your own callback — it just calls ",[503,2942,2943],{},"reactiveProfile.refetch()"," and the\n",[503,2946,2682],{}," section's ",[503,2949,2950],{},"refreshSsrProfile()"," together, so a sign-in\u002Fsign-out mutation updates both sections\nof the page at once. ",[503,2953,2954],{},"app\u002Fplugins\u002Fvue-query.ts"," installs ",[503,2957,2958],{},"VueQueryPlugin"," the standard Nuxt way — one ",[503,2961,2962],{},"QueryClient",", dehydrated\ninto the Nuxt payload on ",[503,2965,2966],{},"app:rendered",", rehydrated on ",[503,2969,2970],{},"app:created"," — which is unrelated to Heximon itself\nand needed only so the bindings above have a ",[503,2973,2962],{}," to run against.",[2976,2977,2979,2980,2982,2983,2986,2987,2990,2991,2994,2995,1505,2997,2999],"callout",{"type":2978},"info","TanStack Vue Query's ",[503,2981,2835],{}," doesn't hook into Vue's SSR data-prefetch (",[503,2984,2985],{},"onServerPrefetch",") the way Nuxt's\nown composables do, so ",[503,2988,2989],{},"reactiveProfile"," above resolves ",[612,2992,2993],{},"after"," hydration, on the client. That's a real\ndifference, not a bug: reach for vue-query when you want client-managed cache, mutations, and invalidation\n(the sign-in\u002Fsign-out buttons here); reach for ",[503,2996,2030],{},[503,2998,2682],{}," — or the plain typed call earlier on\nthis page — when the data has to be in the very first SSR response.",[512,3001,3003],{"id":3002},"the-dev-loop","The dev loop",[499,3005,3006,3009],{},[503,3007,3008],{},"nuxt dev"," gives you the Heximon dev experience with no extra setup — the module wires it in automatically\n(and only in dev; production builds carry none of it):",[3011,3012,3013,3023,3029],"ul",{},[3014,3015,3016,3019,3020,3022],"li",{},[612,3017,3018],{},"Recompile on change."," Edit anything under ",[503,3021,509],{}," — add a route, change a module's providers — and the\ncompiler re-runs; the browser reloads itself once the rebuilt server is live, no restart and no manual\nrefresh.",[3014,3024,3025,3028],{},[612,3026,3027],{},"Plain build errors."," While a compile error stands, every request answers with the diagnostic — a\ncodeframe page in the browser, plain text for an API client — instead of a confident response from stale\nwiring. Fix the source and the app recovers on its own.",[3014,3030,3031,3034,3035,3037],{},[612,3032,3033],{},"JSON preview."," Navigate to an API route in the browser (",[503,3036,2210],{},") and the JSON renders as a\npretty-printed, auto-reloading preview page; API clients and the Vue pages are untouched.",[499,3039,3040,3041,3044,3045,3048],{},"Under the hood this is ",[503,3042,3043],{},"@heximon\u002Fnitro","'s dev plugin (the same one a plain Nitro app lists in its\n",[503,3046,3047],{},"vite.config.ts",") pushed into Nuxt's Vite dev server by the module — you never register it yourself.",[512,3050,3052],{"id":3051},"configure-the-compile","Configure the compile",[499,3054,3055,3057,3058,1505,3061,3064,3065,1662,3068,3071,3072,3075,3076,3078],{},[503,3056,609],{}," is the single source of truth for the compile — the same file ",[503,3059,3060],{},"vp dev",[503,3062,3063],{},"vp build",", ",[503,3066,3067],{},"vp test",[503,3069,3070],{},"createTestApp","), and every host (Vite, Nitro, Nuxt) read identically. There's no ",[503,3073,3074],{},"entry"," and no\ncompile script to point at — the Nuxt module loads it, compiles ",[503,3077,509],{},", and wires the mount itself.",[3080,3081,3082,3098],"table",{},[3083,3084,3085],"thead",{},[3086,3087,3088,3095],"tr",{},[3089,3090,3092,3094],"th",{"align":3091},"left",[503,3093,609],{}," option",[3089,3096,3097],{"align":3091},"Description",[3099,3100,3101],"tbody",{},[3086,3102,3103,3108],{},[3104,3105,3106],"td",{"align":3091},[503,3107,618],{},[3104,3109,3110,3111,3114],{"align":3091},"The compiler plugin set to honor (",[503,3112,3113],{},"[new HttpPlugin()]",", plus event\u002FCQRS\u002Fetc. plugins for those tiers)",[499,3116,3117,3118,3120,3121,3123,3124,3127,3128,3131,3132,3135,3136,3139,3140,3142,3143,3146,3147,3149],{},"Declare it once in ",[503,3119,609],{}," at the project root; ",[503,3122,505],{}," needs no Heximon-specific\noptions at all beyond listing the module. The generated ",[503,3125,3126],{},".heximon"," wiring is always written to the project root\n(",[503,3129,3130],{},"\u003CrootDir>\u002F.heximon",", gitignored) under Nuxt — outside Nuxt's ",[503,3133,3134],{},".nuxt"," build directory, which Nuxt cleans\nmid-build (that would otherwise wipe the emitted ",[503,3137,3138],{},"nitro-entry.js"," before Nitro resolves it). You never configure\nthis, and ",[503,3141,609],{},"'s ",[503,3144,3145],{},"debug"," option — which elsewhere toggles whether the wiring is written to disk —\nhas no effect here: the Nitro\u002FNuxt host always materializes it, ",[503,3148,3145],{}," or not.",[2976,3151,3152,3158,3159,3161,3162,3164,3165,3168,3169,3171],{"type":2978},[612,3153,3154,3155,3157],{},"The ",[503,3156,969],{}," prefix lives in your contract, not the host."," Because ",[503,3160,1306],{}," declares ",[503,3163,1166],{},"\nand the controller binds to it (",[503,3166,3167],{},"Controller\u003CGreetingApi>","), its routes mount under ",[503,3170,1170],{}," and leave the\nrest of the URL space to Nuxt's pages on the same Nitro server. Keep this in mind when choosing contract\nprefixes for a Nuxt app — pick one that won't collide with a Nuxt route.",[512,3173,3175],{"id":3174},"see-also","See also",[3011,3177,3178,3184,3189,3199,3207],{},[3014,3179,3180,3183],{},[1161,3181,3182],{"href":333},"Nitro host"," — the Node\u002FNitro host that does the compile-and-mount work the Nuxt\nmodule delegates to, useful when you're serving an API without Nuxt pages in front of it.",[3014,3185,3186,3188],{},[1161,3187,57],{"href":58}," — routes, validation, cookies, and the two controller modes in\ndepth.",[3014,3190,3191,3193,3194,2031,3196,3198],{},[1161,3192,72],{"href":73}," — the full ",[503,3195,2425],{},[503,3197,2429],{}," \u002F interceptor \u002F vue-query\nreference this page's typed-client section builds on.",[3014,3200,3201,3203,3204,3206],{},[1161,3202,289],{"href":290}," and ",[1161,3205,267],{"href":268}," — push the same\nmodules onto Cloudflare's stateful actors when you outgrow a single server.",[3014,3208,3209,3217,3218,3220],{},[1161,3210,3214],{"href":3211,"rel":3212},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fgap\u002Fnuxt",[3213],"nofollow",[612,3215,3216],{},"Nuxt module example"," — a\nVue page that calls a Heximon ",[503,3219,1170],{}," route during SSR with cookies forwarded automatically, a second page\nreading the same routes through the typed contract client + vue-query, and an in-process test that proves\nboth the cookie sign-in \u002F profile \u002F sign-out flow and the typed client's callers end-to-end.",[3222,3223,3224],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":532,"searchDepth":654,"depth":654,"links":3226},[3227,3228,3229,3230,3232,3233,3234,3235,3236,3237],{"id":514,"depth":654,"text":515},{"id":598,"depth":654,"text":599},{"id":851,"depth":654,"text":852},{"id":1174,"depth":654,"text":3231},"Write a controller under server\u002F",{"id":1771,"depth":654,"text":1772},{"id":2023,"depth":654,"text":2024},{"id":2343,"depth":654,"text":2344},{"id":3002,"depth":654,"text":3003},{"id":3051,"depth":654,"text":3052},{"id":3174,"depth":654,"text":3175},"Run a Heximon API inside a Nuxt 5 app on one Nitro server, with SSR cookie forwarding, a typed Contract client with TanStack Vue Query bindings, heximon.config.ts, HttpPlugin, and a server\u002F controller.","md",null,{},{"icon":340},{"title":337,"description":3238},"C6dK1FSiA25XB3ibjzfsaN452TL1xiMYmr6ha38VgYs",[3246,3248],{"title":332,"path":333,"stem":334,"description":3247,"icon":335,"children":-1},"Run a Heximon app inside Nitro v3 with heximonNitroModule, heximonNitroVitePlugin for the dev loop, heximon.config.ts, NitroFetchClient, and one server directory that deploys to Node, Cloudflare Workers, Deno, Bun, and AWS Lambda.",{"title":342,"path":343,"stem":344,"description":3249,"icon":236,"children":-1},"Place one app's controllers across edge and node runtimes in a single deploy — the compiler partitions the DI graph by runtime, proves each edge tier is edge-safe before deploy, and emits separate functions routed by prefix. Vercel Functions and Netlify Functions.",1783300759753]