[{"data":1,"prerenderedAt":2051},["ShallowReactive",2],{"navigation":3,"\u002Fdeployment\u002Fkubernetes":358,"\u002Fdeployment\u002Fkubernetes-surround":2046},[4,14,36,69,140,341],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fgetting-started","1.getting-started\u002F1.index",[9,10],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":15,"path":16,"stem":17,"children":18,"page":35},"Guides","\u002Fguides","2.guides",[19,23,27,31],{"title":20,"path":21,"stem":22},"Your First Layout","\u002Fguides\u002Fyour-first-layout","2.guides\u002F1.your-first-layout",{"title":24,"path":25,"stem":26},"Your First Page Template","\u002Fguides\u002Fyour-first-page-template","2.guides\u002F2.your-first-page-template",{"title":28,"path":29,"stem":30},"Your First Component","\u002Fguides\u002Fyour-first-component","2.guides\u002F3.your-first-component",{"title":32,"path":33,"stem":34},"Alternative UI Variants","\u002Fguides\u002Falternative-ui-variants","2.guides\u002F4.alternative-ui-variants",false,{"title":37,"path":38,"stem":39,"children":40,"page":35},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[41,45,49,53,57,61,65],{"title":42,"path":43,"stem":44},"How It All Works","\u002Fcore-concepts\u002Farchitecture","3.core-concepts\u002F1.architecture",{"title":46,"path":47,"stem":48},"The Data Model","\u002Fcore-concepts\u002Fthe-data-model","3.core-concepts\u002F2.the-data-model",{"title":50,"path":51,"stem":52},"Layouts & Pages","\u002Fcore-concepts\u002Flayouts-and-pages","3.core-concepts\u002F3.layouts-and-pages",{"title":54,"path":55,"stem":56},"Dynamic Pages","\u002Fcore-concepts\u002Fdynamic-pages","3.core-concepts\u002F4.dynamic-pages",{"title":58,"path":59,"stem":60},"Components","\u002Fcore-concepts\u002Fcomponents","3.core-concepts\u002F5.components",{"title":62,"path":63,"stem":64},"Draft & Publish Workflow","\u002Fcore-concepts\u002Fdraft-and-publish","3.core-concepts\u002F6.draft-and-publish",{"title":66,"path":67,"stem":68},"The Admin Panel","\u002Fcore-concepts\u002Fadmin-panel","3.core-concepts\u002F7.admin-panel",{"title":70,"path":71,"stem":72,"children":73,"page":35},"Api","\u002Fapi","4.api",[74,78,116,120,124,128,132,136],{"title":75,"path":76,"stem":77},"Bundle Setup","\u002Fapi\u002Fbundle-setup","4.api\u002F1.bundle-setup",{"title":58,"path":79,"stem":80,"children":81,"page":35},"\u002Fapi\u002Fcomponents","4.api\u002F2.components",[82,86,103],{"title":83,"path":84,"stem":85},"Creating Components","\u002Fapi\u002Fcomponents\u002Fcreating-components","4.api\u002F2.components\u002F1.creating-components",{"title":87,"path":88,"stem":89,"children":90,"page":35},"Annotations","\u002Fapi\u002Fcomponents\u002Fannotations","4.api\u002F2.components\u002F2.annotations",[91,95,99],{"title":92,"path":93,"stem":94},"Publishable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fpublishable","4.api\u002F2.components\u002F2.annotations\u002F1.publishable",{"title":96,"path":97,"stem":98},"Uploadable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fuploadable","4.api\u002F2.components\u002F2.annotations\u002F2.uploadable",{"title":100,"path":101,"stem":102},"Timestamped","\u002Fapi\u002Fcomponents\u002Fannotations\u002Ftimestamped","4.api\u002F2.components\u002F2.annotations\u002F3.timestamped",{"title":104,"path":105,"stem":106,"children":107,"page":35},"Built Ins","\u002Fapi\u002Fcomponents\u002Fbuilt-ins","4.api\u002F2.components\u002F3.built-ins",[108,112],{"title":109,"path":110,"stem":111},"Collection Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fcollection-component","4.api\u002F2.components\u002F3.built-ins\u002F1.collection-component",{"title":113,"path":114,"stem":115},"Form Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fform-component","4.api\u002F2.components\u002F3.built-ins\u002F2.form-component",{"title":117,"path":118,"stem":119},"Dynamic & Nested Pages","\u002Fapi\u002Fdynamic-pages","4.api\u002F3.dynamic-pages",{"title":121,"path":122,"stem":123},"Users & Security","\u002Fapi\u002Fusers-and-security","4.api\u002F4.users-and-security",{"title":125,"path":126,"stem":127},"Data Fixtures","\u002Fapi\u002Fdata-fixtures","4.api\u002F5.data-fixtures",{"title":129,"path":130,"stem":131},"Configuration Reference","\u002Fapi\u002Fconfiguration","4.api\u002F6.configuration",{"title":133,"path":134,"stem":135},"Console Commands","\u002Fapi\u002Fconsole-commands","4.api\u002F7.console-commands",{"title":137,"path":138,"stem":139},"Debugging & Profiler","\u002Fapi\u002Fdebugging","4.api\u002F8.debugging",{"title":141,"path":142,"stem":143,"children":144,"page":35},"Nuxt Module","\u002Fnuxt-module","5.nuxt-module",[145,149,162,182,207,211,295,320,324],{"title":146,"path":147,"stem":148},"Module Setup","\u002Fnuxt-module\u002Fmodule-setup","5.nuxt-module\u002F1.module-setup",{"title":150,"path":151,"stem":152,"children":153,"page":35},"Configuration","\u002Fnuxt-module\u002Fconfiguration","5.nuxt-module\u002F2.configuration",[154,158],{"title":155,"path":156,"stem":157},"Nuxt Config","\u002Fnuxt-module\u002Fconfiguration\u002Fnuxt-config","5.nuxt-module\u002F2.configuration\u002F1.nuxt-config",{"title":159,"path":160,"stem":161},"Site Config & SEO","\u002Fnuxt-module\u002Fconfiguration\u002Fsite-config-and-seo","5.nuxt-module\u002F2.configuration\u002F2.site-config-and-seo",{"title":163,"path":164,"stem":165,"children":166,"page":35},"Building Your Ui","\u002Fnuxt-module\u002Fbuilding-your-ui","5.nuxt-module\u002F3.building-your-ui",[167,171,175,178],{"title":168,"path":169,"stem":170},"Layouts","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-layouts","5.nuxt-module\u002F3.building-your-ui\u002F1.creating-layouts",{"title":172,"path":173,"stem":174},"Page Templates","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-page-templates","5.nuxt-module\u002F3.building-your-ui\u002F2.creating-page-templates",{"title":83,"path":176,"stem":177},"\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-components","5.nuxt-module\u002F3.building-your-ui\u002F3.creating-components",{"title":179,"path":180,"stem":181},"CLI Generator","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcwa-cli","5.nuxt-module\u002F3.building-your-ui\u002F4.cwa-cli",{"title":183,"path":184,"stem":185,"children":186,"page":35},"Cwa Components","\u002Fnuxt-module\u002Fcwa-components","5.nuxt-module\u002F4.cwa-components",[187,191,195,199,203],{"title":188,"path":189,"stem":190},"\u003CCwaComponentGroup \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-component-group","5.nuxt-module\u002F4.cwa-components\u002F1.cwa-component-group",{"title":192,"path":193,"stem":194},"\u003CCwaPage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-page","5.nuxt-module\u002F4.cwa-components\u002F2.cwa-page",{"title":196,"path":197,"stem":198},"\u003CCwaLink \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-link","5.nuxt-module\u002F4.cwa-components\u002F3.cwa-link",{"title":200,"path":201,"stem":202},"\u003CCwaImage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-image","5.nuxt-module\u002F4.cwa-components\u002F4.cwa-image",{"title":204,"path":205,"stem":206},"\u003CCwaDefaultLayout \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-default-layout","5.nuxt-module\u002F4.cwa-components\u002F5.cwa-default-layout",{"title":208,"path":209,"stem":210},"The useCwa() API","\u002Fnuxt-module\u002Fcwa-api","5.nuxt-module\u002F5.cwa-api",{"title":212,"path":213,"stem":214,"children":215,"page":35},"Composables","\u002Fnuxt-module\u002Fcomposables","5.nuxt-module\u002F6.composables",[216,224,261,278],{"title":217,"path":218,"stem":219,"children":220,"page":35},"Layout","\u002Fnuxt-module\u002Fcomposables\u002Flayout","5.nuxt-module\u002F6.composables\u002F0.layout",[221],{"title":217,"path":222,"stem":223},"\u002Fnuxt-module\u002Fcomposables\u002Flayout\u002Fuse-cwa-layout","5.nuxt-module\u002F6.composables\u002F0.layout\u002F1.use-cwa-layout",{"title":225,"path":226,"stem":227,"children":228,"page":35},"Component","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent","5.nuxt-module\u002F6.composables\u002F1.component",[229,233,237,241,245,249,253,257],{"title":230,"path":231,"stem":232},"Component (recommended)","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-component","5.nuxt-module\u002F6.composables\u002F1.component\u002F0.use-cwa-component",{"title":234,"path":235,"stem":236},"Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F1.use-cwa-resource",{"title":238,"path":239,"stem":240},"Collection Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-collection-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F2.use-cwa-collection-resource",{"title":242,"path":243,"stem":244},"Image Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-image-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F3.use-cwa-image-resource",{"title":246,"path":247,"stem":248},"Form","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form","5.nuxt-module\u002F6.composables\u002F1.component\u002F4.use-cwa-form",{"title":250,"path":251,"stem":252},"Form Input","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-input","5.nuxt-module\u002F6.composables\u002F1.component\u002F5.use-cwa-form-input",{"title":254,"path":255,"stem":256},"Form Repeated","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-repeated","5.nuxt-module\u002F6.composables\u002F1.component\u002F6.use-cwa-form-repeated",{"title":258,"path":259,"stem":260},"Form Collection","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-collection","5.nuxt-module\u002F6.composables\u002F1.component\u002F7.use-cwa-form-collection",{"title":262,"path":263,"stem":264,"children":265,"page":35},"Admin Manager","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager","5.nuxt-module\u002F6.composables\u002F2.admin-manager",[266,270,274],{"title":267,"path":268,"stem":269},"Manager Tab","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-manager-tab","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F1.use-cwa-resource-manager-tab",{"title":271,"path":272,"stem":273},"Resource Model","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-model","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F2.use-cwa-resource-model",{"title":275,"path":276,"stem":277},"Resource Upload","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-upload","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F3.use-cwa-resource-upload",{"title":279,"path":280,"stem":281,"children":282,"page":35},"Utilities","\u002Fnuxt-module\u002Fcomposables\u002Futilities","5.nuxt-module\u002F6.composables\u002F3.utilities",[283,287,291],{"title":284,"path":285,"stem":286},"Resource Endpoint","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-endpoint","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F1.use-cwa-resource-endpoint",{"title":288,"path":289,"stem":290},"Query Model","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-query-bound-model","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F2.use-query-bound-model",{"title":292,"path":293,"stem":294},"Resource Route","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-route","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F3.use-cwa-resource-route",{"title":296,"path":297,"stem":298,"children":299,"page":35},"Component Helpers","\u002Fnuxt-module\u002Fcomponent-helpers","5.nuxt-module\u002F7.component-helpers",[300,304,308,312,316],{"title":301,"path":302,"stem":303},"Images & Media","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fimages-and-uploads","5.nuxt-module\u002F7.component-helpers\u002F1.images-and-uploads",{"title":305,"path":306,"stem":307},"Collections & Pagination","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fcollections-and-pagination","5.nuxt-module\u002F7.component-helpers\u002F2.collections-and-pagination",{"title":309,"path":310,"stem":311},"HTML Content","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fhtml-content","5.nuxt-module\u002F7.component-helpers\u002F3.html-content",{"title":313,"path":314,"stem":315},"Real-Time Updates","\u002Fnuxt-module\u002Fcomponent-helpers\u002Freal-time-updates","5.nuxt-module\u002F7.component-helpers\u002F4.real-time-updates",{"title":317,"path":318,"stem":319},"Forms","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fforms","5.nuxt-module\u002F7.component-helpers\u002F5.forms",{"title":321,"path":322,"stem":323},"Authentication","\u002Fnuxt-module\u002Fauthentication","5.nuxt-module\u002F8.authentication",{"title":325,"path":326,"stem":327,"children":328,"page":35},"Cwa Layer","\u002Fnuxt-module\u002Fcwa-layer","5.nuxt-module\u002F9.cwa-layer",[329,333,337],{"title":330,"path":331,"stem":332},"Overview","\u002Fnuxt-module\u002Fcwa-layer\u002Foverview","5.nuxt-module\u002F9.cwa-layer\u002F1.overview",{"title":334,"path":335,"stem":336},"Auth Pages","\u002Fnuxt-module\u002Fcwa-layer\u002Fauth-pages","5.nuxt-module\u002F9.cwa-layer\u002F2.auth-pages",{"title":338,"path":339,"stem":340},"Admin Panel","\u002Fnuxt-module\u002Fcwa-layer\u002Fadmin-panel","5.nuxt-module\u002F9.cwa-layer\u002F3.admin-panel",{"title":342,"path":343,"stem":344,"children":345,"page":35},"Deployment","\u002Fdeployment","6.deployment",[346,350,354],{"title":347,"path":348,"stem":349},"Docker","\u002Fdeployment\u002Fdocker","6.deployment\u002F1.docker",{"title":351,"path":352,"stem":353},"Kubernetes & Helm","\u002Fdeployment\u002Fkubernetes","6.deployment\u002F2.kubernetes",{"title":355,"path":356,"stem":357},"CI\u002FCD","\u002Fdeployment\u002Fci-cd","6.deployment\u002F3.ci-cd",{"id":359,"title":351,"badge":360,"body":363,"description":2040,"extension":2041,"links":2042,"meta":2043,"navigation":633,"path":352,"seo":2044,"stem":353,"__hash__":2045},"docs\u002F6.deployment\u002F2.kubernetes.md",{"label":361,"color":362},"Draft","amber",{"type":364,"value":365,"toc":2028},"minimark",[366,370,386,391,482,485,489,878,882,889,953,956,960,963,995,1000,1082,1086,1089,1322,1325,1329,1591,1595,1710,1713,1717,1724,1739,1919,1923,1930,1979,1983,1986,2021,2024],[367,368,369],"p",{},"CWA runs well on Kubernetes. Each service maps cleanly to a Deployment, and the stateless PHP and Nuxt containers make rolling updates straightforward.",[367,371,372,373,377,378,385],{},"The Helm chart lives in the template repository at ",[374,375,376],"code",{},"helm\u002Fcwa\u002F"," — it is included when you generate a project from the ",[379,380,384],"a",{"href":381,"rel":382},"https:\u002F\u002Fgithub.com\u002Fcomponents-web-app\u002Fcomponents-web-app",[383],"nofollow","components-web-app template",". There is no separate Helm registry; you own the chart and modify it as needed.",[387,388,390],"h2",{"id":389},"what-the-helm-chart-deploys","What the Helm Chart Deploys",[392,393,394,409],"table",{},[395,396,397],"thead",{},[398,399,400,403,406],"tr",{},[401,402,234],"th",{},[401,404,405],{},"Type",[401,407,408],{},"Description",[410,411,412,425,437,449,466],"tbody",{},[398,413,414,420,422],{},[415,416,417],"td",{},[374,418,419],{},"php",[415,421,342],{},[415,423,424],{},"FrankenPHP serving the Symfony API",[398,426,427,432,434],{},[415,428,429],{},[374,430,431],{},"nuxt",[415,433,342],{},[415,435,436],{},"Node SSR server",[398,438,439,444,446],{},[415,440,441],{},[374,442,443],{},"mercure",[415,445,342],{},[415,447,448],{},"Caddy + Mercure hub",[398,450,451,460,463],{},[415,452,453,455,456,455,458],{},[374,454,419],{},", ",[374,457,431],{},[374,459,443],{},[415,461,462],{},"Service",[415,464,465],{},"Internal cluster services",[398,467,468,476,479],{},[415,469,470,455,472,455,474],{},[374,471,419],{},[374,473,431],{},[374,475,443],{},[415,477,478],{},"Ingress",[415,480,481],{},"External routing with TLS",[367,483,484],{},"Database is typically a managed external service (Cloud SQL, RDS, etc.) rather than an in-cluster StatefulSet for production.",[387,486,488],{"id":487},"minimum-valuesyaml","Minimum values.yaml",[490,491,496],"pre",{"className":492,"code":493,"language":494,"meta":495,"style":495},"language-yaml shiki shiki-themes github-light github-dark material-theme-palenight","php:\n    image:\n        repository: ghcr.io\u002Fyour-org\u002Fapp-php\n        tag: latest\n    env:\n        DATABASE_URL: \"postgresql:\u002F\u002Fuser:pass@cloud-sql\u002Fapp\"\n        MERCURE_URL: \"http:\u002F\u002Fmercure\u002F.well-known\u002Fmercure\"\n        MERCURE_PUBLIC_URL: \"https:\u002F\u002Fmercure.example.com\u002F.well-known\u002Fmercure\"\n    envFrom:\n        - secretRef:\n            name: cwa-secrets\n\nnuxt:\n    image:\n        repository: ghcr.io\u002Fyour-org\u002Fapp-nuxt\n        tag: latest\n    env:\n        NUXT_PUBLIC_CWA_API_URL: \"http:\u002F\u002Fphp-service\"\n        NUXT_PUBLIC_CWA_API_URL_BROWSER: \"https:\u002F\u002Fapi.example.com\"\n    envFrom:\n        - secretRef:\n            name: cwa-secrets\n\nmercure:\n    image:\n        repository: dunglas\u002Fmercure\n        tag: latest\n    envFrom:\n        - secretRef:\n            name: cwa-secrets\n\ningress:\n    enabled: true\n    annotations:\n        cert-manager.io\u002Fcluster-issuer: letsencrypt\n    hosts:\n        api: api.example.com\n        www: www.example.com\n        mercure: mercure.example.com\n","yaml","",[374,497,498,510,518,531,542,550,568,583,598,606,617,628,635,642,649,659,668,675,690,705,712,721,730,735,742,749,759,768,775,784,793,798,806,818,826,837,845,856,867],{"__ignoreMap":495},[499,500,503,506],"span",{"class":501,"line":502},"line",1,[499,504,419],{"class":505},"s-h7I",[499,507,509],{"class":508},"sOvfz",":\n",[499,511,513,516],{"class":501,"line":512},2,[499,514,515],{"class":505},"    image",[499,517,509],{"class":508},[499,519,521,524,527],{"class":501,"line":520},3,[499,522,523],{"class":505},"        repository",[499,525,526],{"class":508},":",[499,528,530],{"class":529},"sLL54"," ghcr.io\u002Fyour-org\u002Fapp-php\n",[499,532,534,537,539],{"class":501,"line":533},4,[499,535,536],{"class":505},"        tag",[499,538,526],{"class":508},[499,540,541],{"class":529}," latest\n",[499,543,545,548],{"class":501,"line":544},5,[499,546,547],{"class":505},"    env",[499,549,509],{"class":508},[499,551,553,556,558,562,565],{"class":501,"line":552},6,[499,554,555],{"class":505},"        DATABASE_URL",[499,557,526],{"class":508},[499,559,561],{"class":560},"seSrl"," \"",[499,563,564],{"class":529},"postgresql:\u002F\u002Fuser:pass@cloud-sql\u002Fapp",[499,566,567],{"class":560},"\"\n",[499,569,571,574,576,578,581],{"class":501,"line":570},7,[499,572,573],{"class":505},"        MERCURE_URL",[499,575,526],{"class":508},[499,577,561],{"class":560},[499,579,580],{"class":529},"http:\u002F\u002Fmercure\u002F.well-known\u002Fmercure",[499,582,567],{"class":560},[499,584,586,589,591,593,596],{"class":501,"line":585},8,[499,587,588],{"class":505},"        MERCURE_PUBLIC_URL",[499,590,526],{"class":508},[499,592,561],{"class":560},[499,594,595],{"class":529},"https:\u002F\u002Fmercure.example.com\u002F.well-known\u002Fmercure",[499,597,567],{"class":560},[499,599,601,604],{"class":501,"line":600},9,[499,602,603],{"class":505},"    envFrom",[499,605,509],{"class":508},[499,607,609,612,615],{"class":501,"line":608},10,[499,610,611],{"class":508},"        -",[499,613,614],{"class":505}," secretRef",[499,616,509],{"class":508},[499,618,620,623,625],{"class":501,"line":619},11,[499,621,622],{"class":505},"            name",[499,624,526],{"class":508},[499,626,627],{"class":529}," cwa-secrets\n",[499,629,631],{"class":501,"line":630},12,[499,632,634],{"emptyLinePlaceholder":633},true,"\n",[499,636,638,640],{"class":501,"line":637},13,[499,639,431],{"class":505},[499,641,509],{"class":508},[499,643,645,647],{"class":501,"line":644},14,[499,646,515],{"class":505},[499,648,509],{"class":508},[499,650,652,654,656],{"class":501,"line":651},15,[499,653,523],{"class":505},[499,655,526],{"class":508},[499,657,658],{"class":529}," ghcr.io\u002Fyour-org\u002Fapp-nuxt\n",[499,660,662,664,666],{"class":501,"line":661},16,[499,663,536],{"class":505},[499,665,526],{"class":508},[499,667,541],{"class":529},[499,669,671,673],{"class":501,"line":670},17,[499,672,547],{"class":505},[499,674,509],{"class":508},[499,676,678,681,683,685,688],{"class":501,"line":677},18,[499,679,680],{"class":505},"        NUXT_PUBLIC_CWA_API_URL",[499,682,526],{"class":508},[499,684,561],{"class":560},[499,686,687],{"class":529},"http:\u002F\u002Fphp-service",[499,689,567],{"class":560},[499,691,693,696,698,700,703],{"class":501,"line":692},19,[499,694,695],{"class":505},"        NUXT_PUBLIC_CWA_API_URL_BROWSER",[499,697,526],{"class":508},[499,699,561],{"class":560},[499,701,702],{"class":529},"https:\u002F\u002Fapi.example.com",[499,704,567],{"class":560},[499,706,708,710],{"class":501,"line":707},20,[499,709,603],{"class":505},[499,711,509],{"class":508},[499,713,715,717,719],{"class":501,"line":714},21,[499,716,611],{"class":508},[499,718,614],{"class":505},[499,720,509],{"class":508},[499,722,724,726,728],{"class":501,"line":723},22,[499,725,622],{"class":505},[499,727,526],{"class":508},[499,729,627],{"class":529},[499,731,733],{"class":501,"line":732},23,[499,734,634],{"emptyLinePlaceholder":633},[499,736,738,740],{"class":501,"line":737},24,[499,739,443],{"class":505},[499,741,509],{"class":508},[499,743,745,747],{"class":501,"line":744},25,[499,746,515],{"class":505},[499,748,509],{"class":508},[499,750,752,754,756],{"class":501,"line":751},26,[499,753,523],{"class":505},[499,755,526],{"class":508},[499,757,758],{"class":529}," dunglas\u002Fmercure\n",[499,760,762,764,766],{"class":501,"line":761},27,[499,763,536],{"class":505},[499,765,526],{"class":508},[499,767,541],{"class":529},[499,769,771,773],{"class":501,"line":770},28,[499,772,603],{"class":505},[499,774,509],{"class":508},[499,776,778,780,782],{"class":501,"line":777},29,[499,779,611],{"class":508},[499,781,614],{"class":505},[499,783,509],{"class":508},[499,785,787,789,791],{"class":501,"line":786},30,[499,788,622],{"class":505},[499,790,526],{"class":508},[499,792,627],{"class":529},[499,794,796],{"class":501,"line":795},31,[499,797,634],{"emptyLinePlaceholder":633},[499,799,801,804],{"class":501,"line":800},32,[499,802,803],{"class":505},"ingress",[499,805,509],{"class":508},[499,807,809,812,814],{"class":501,"line":808},33,[499,810,811],{"class":505},"    enabled",[499,813,526],{"class":508},[499,815,817],{"class":816},"swWMF"," true\n",[499,819,821,824],{"class":501,"line":820},34,[499,822,823],{"class":505},"    annotations",[499,825,509],{"class":508},[499,827,829,832,834],{"class":501,"line":828},35,[499,830,831],{"class":505},"        cert-manager.io\u002Fcluster-issuer",[499,833,526],{"class":508},[499,835,836],{"class":529}," letsencrypt\n",[499,838,840,843],{"class":501,"line":839},36,[499,841,842],{"class":505},"    hosts",[499,844,509],{"class":508},[499,846,848,851,853],{"class":501,"line":847},37,[499,849,850],{"class":505},"        api",[499,852,526],{"class":508},[499,854,855],{"class":529}," api.example.com\n",[499,857,859,862,864],{"class":501,"line":858},38,[499,860,861],{"class":505},"        www",[499,863,526],{"class":508},[499,865,866],{"class":529}," www.example.com\n",[499,868,870,873,875],{"class":501,"line":869},39,[499,871,872],{"class":505},"        mercure",[499,874,526],{"class":508},[499,876,877],{"class":529}," mercure.example.com\n",[387,879,881],{"id":880},"managing-secrets","Managing Secrets",[367,883,884,885,888],{},"Never hardcode secrets in ",[374,886,887],{},"values.yaml",". Create a Kubernetes Secret:",[490,890,894],{"className":891,"code":892,"language":893,"meta":495,"style":495},"language-bash shiki shiki-themes github-light github-dark material-theme-palenight","kubectl create secret generic cwa-secrets \\\n    --from-literal=JWT_PASSPHRASE=your_jwt_passphrase \\\n    --from-literal=MERCURE_JWT_SECRET=your_mercure_secret \\\n    --from-literal=DATABASE_URL=\"postgresql:\u002F\u002F...\" \\\n    --from-literal=APP_SECRET=your_app_secret\n","bash",[374,895,896,918,926,933,948],{"__ignoreMap":495},[499,897,898,902,905,908,911,914],{"class":501,"line":502},[499,899,901],{"class":900},"sRCss","kubectl",[499,903,904],{"class":529}," create",[499,906,907],{"class":529}," secret",[499,909,910],{"class":529}," generic",[499,912,913],{"class":529}," cwa-secrets",[499,915,917],{"class":916},"sc2zw"," \\\n",[499,919,920,924],{"class":501,"line":512},[499,921,923],{"class":922},"szhYu","    --from-literal=JWT_PASSPHRASE=your_jwt_passphrase",[499,925,917],{"class":916},[499,927,928,931],{"class":501,"line":520},[499,929,930],{"class":922},"    --from-literal=MERCURE_JWT_SECRET=your_mercure_secret",[499,932,917],{"class":916},[499,934,935,938,941,944,946],{"class":501,"line":533},[499,936,937],{"class":922},"    --from-literal=DATABASE_URL=",[499,939,940],{"class":560},"\"",[499,942,943],{"class":529},"postgresql:\u002F\u002F...",[499,945,940],{"class":560},[499,947,917],{"class":916},[499,949,950],{"class":501,"line":544},[499,951,952],{"class":922},"    --from-literal=APP_SECRET=your_app_secret\n",[367,954,955],{},"For production use External Secrets Operator to sync from AWS Secrets Manager, GCP Secret Manager, or HashiCorp Vault.",[387,957,959],{"id":958},"jwt-keys-as-kubernetes-secrets","JWT Keys as Kubernetes Secrets",[367,961,962],{},"Generate JWT keys locally, then create a Secret:",[490,964,966],{"className":891,"code":965,"language":893,"meta":495,"style":495},"kubectl create secret generic jwt-keys \\\n    --from-file=private.pem=config\u002Fjwt\u002Fprivate.pem \\\n    --from-file=public.pem=config\u002Fjwt\u002Fpublic.pem\n",[374,967,968,983,990],{"__ignoreMap":495},[499,969,970,972,974,976,978,981],{"class":501,"line":502},[499,971,901],{"class":900},[499,973,904],{"class":529},[499,975,907],{"class":529},[499,977,910],{"class":529},[499,979,980],{"class":529}," jwt-keys",[499,982,917],{"class":916},[499,984,985,988],{"class":501,"line":512},[499,986,987],{"class":922},"    --from-file=private.pem=config\u002Fjwt\u002Fprivate.pem",[499,989,917],{"class":916},[499,991,992],{"class":501,"line":520},[499,993,994],{"class":922},"    --from-file=public.pem=config\u002Fjwt\u002Fpublic.pem\n",[367,996,997,998,526],{},"Mount into the PHP pod as a volume in ",[374,999,887],{},[490,1001,1003],{"className":492,"code":1002,"language":494,"meta":495,"style":495},"php:\n    volumes:\n        - name: jwt-keys\n          secret:\n            secretName: jwt-keys\n    volumeMounts:\n        - name: jwt-keys\n          mountPath: \u002Fvar\u002Fwww\u002Fhtml\u002Fconfig\u002Fjwt\n          readOnly: true\n",[374,1004,1005,1011,1018,1030,1037,1046,1053,1063,1073],{"__ignoreMap":495},[499,1006,1007,1009],{"class":501,"line":502},[499,1008,419],{"class":505},[499,1010,509],{"class":508},[499,1012,1013,1016],{"class":501,"line":512},[499,1014,1015],{"class":505},"    volumes",[499,1017,509],{"class":508},[499,1019,1020,1022,1025,1027],{"class":501,"line":520},[499,1021,611],{"class":508},[499,1023,1024],{"class":505}," name",[499,1026,526],{"class":508},[499,1028,1029],{"class":529}," jwt-keys\n",[499,1031,1032,1035],{"class":501,"line":533},[499,1033,1034],{"class":505},"          secret",[499,1036,509],{"class":508},[499,1038,1039,1042,1044],{"class":501,"line":544},[499,1040,1041],{"class":505},"            secretName",[499,1043,526],{"class":508},[499,1045,1029],{"class":529},[499,1047,1048,1051],{"class":501,"line":552},[499,1049,1050],{"class":505},"    volumeMounts",[499,1052,509],{"class":508},[499,1054,1055,1057,1059,1061],{"class":501,"line":570},[499,1056,611],{"class":508},[499,1058,1024],{"class":505},[499,1060,526],{"class":508},[499,1062,1029],{"class":529},[499,1064,1065,1068,1070],{"class":501,"line":585},[499,1066,1067],{"class":505},"          mountPath",[499,1069,526],{"class":508},[499,1071,1072],{"class":529}," \u002Fvar\u002Fwww\u002Fhtml\u002Fconfig\u002Fjwt\n",[499,1074,1075,1078,1080],{"class":501,"line":600},[499,1076,1077],{"class":505},"          readOnly",[499,1079,526],{"class":508},[499,1081,817],{"class":816},[387,1083,1085],{"id":1084},"running-migrations","Running Migrations",[367,1087,1088],{},"Run migrations as a Kubernetes Job before updating the PHP Deployment. Use a Helm pre-upgrade hook:",[490,1090,1092],{"className":492,"code":1091,"language":494,"meta":495,"style":495},"# templates\u002Fmigration-job.yaml\napiVersion: batch\u002Fv1\nkind: Job\nmetadata:\n    name: \"{{ .Release.Name }}-migrations-{{ .Release.Revision }}\"\n    annotations:\n        \"helm.sh\u002Fhook\": pre-upgrade,pre-install\n        \"helm.sh\u002Fhook-weight\": \"-1\"\n        \"helm.sh\u002Fhook-delete-policy\": before-hook-creation\nspec:\n    template:\n        spec:\n            restartPolicy: Never\n            containers:\n                - name: migrations\n                  image: \"{{ .Values.php.image.repository }}:{{ .Values.php.image.tag }}\"\n                  command: [\"bin\u002Fconsole\", \"doctrine:migrations:migrate\", \"--no-interaction\"]\n                  envFrom:\n                      - secretRef:\n                          name: cwa-secrets\n",[374,1093,1094,1100,1110,1120,1127,1141,1147,1162,1180,1194,1201,1208,1215,1225,1232,1244,1258,1297,1304,1313],{"__ignoreMap":495},[499,1095,1096],{"class":501,"line":502},[499,1097,1099],{"class":1098},"sTBSN","# templates\u002Fmigration-job.yaml\n",[499,1101,1102,1105,1107],{"class":501,"line":512},[499,1103,1104],{"class":505},"apiVersion",[499,1106,526],{"class":508},[499,1108,1109],{"class":529}," batch\u002Fv1\n",[499,1111,1112,1115,1117],{"class":501,"line":520},[499,1113,1114],{"class":505},"kind",[499,1116,526],{"class":508},[499,1118,1119],{"class":529}," Job\n",[499,1121,1122,1125],{"class":501,"line":533},[499,1123,1124],{"class":505},"metadata",[499,1126,509],{"class":508},[499,1128,1129,1132,1134,1136,1139],{"class":501,"line":544},[499,1130,1131],{"class":505},"    name",[499,1133,526],{"class":508},[499,1135,561],{"class":560},[499,1137,1138],{"class":529},"{{ .Release.Name }}-migrations-{{ .Release.Revision }}",[499,1140,567],{"class":560},[499,1142,1143,1145],{"class":501,"line":552},[499,1144,823],{"class":505},[499,1146,509],{"class":508},[499,1148,1149,1152,1155,1157,1159],{"class":501,"line":570},[499,1150,1151],{"class":560},"        \"",[499,1153,1154],{"class":529},"helm.sh\u002Fhook",[499,1156,940],{"class":560},[499,1158,526],{"class":508},[499,1160,1161],{"class":529}," pre-upgrade,pre-install\n",[499,1163,1164,1166,1169,1171,1173,1175,1178],{"class":501,"line":585},[499,1165,1151],{"class":560},[499,1167,1168],{"class":529},"helm.sh\u002Fhook-weight",[499,1170,940],{"class":560},[499,1172,526],{"class":508},[499,1174,561],{"class":560},[499,1176,1177],{"class":529},"-1",[499,1179,567],{"class":560},[499,1181,1182,1184,1187,1189,1191],{"class":501,"line":600},[499,1183,1151],{"class":560},[499,1185,1186],{"class":529},"helm.sh\u002Fhook-delete-policy",[499,1188,940],{"class":560},[499,1190,526],{"class":508},[499,1192,1193],{"class":529}," before-hook-creation\n",[499,1195,1196,1199],{"class":501,"line":608},[499,1197,1198],{"class":505},"spec",[499,1200,509],{"class":508},[499,1202,1203,1206],{"class":501,"line":619},[499,1204,1205],{"class":505},"    template",[499,1207,509],{"class":508},[499,1209,1210,1213],{"class":501,"line":630},[499,1211,1212],{"class":505},"        spec",[499,1214,509],{"class":508},[499,1216,1217,1220,1222],{"class":501,"line":637},[499,1218,1219],{"class":505},"            restartPolicy",[499,1221,526],{"class":508},[499,1223,1224],{"class":529}," Never\n",[499,1226,1227,1230],{"class":501,"line":644},[499,1228,1229],{"class":505},"            containers",[499,1231,509],{"class":508},[499,1233,1234,1237,1239,1241],{"class":501,"line":651},[499,1235,1236],{"class":508},"                -",[499,1238,1024],{"class":505},[499,1240,526],{"class":508},[499,1242,1243],{"class":529}," migrations\n",[499,1245,1246,1249,1251,1253,1256],{"class":501,"line":661},[499,1247,1248],{"class":505},"                  image",[499,1250,526],{"class":508},[499,1252,561],{"class":560},[499,1254,1255],{"class":529},"{{ .Values.php.image.repository }}:{{ .Values.php.image.tag }}",[499,1257,567],{"class":560},[499,1259,1260,1263,1265,1268,1270,1273,1275,1278,1280,1283,1285,1287,1289,1292,1294],{"class":501,"line":670},[499,1261,1262],{"class":505},"                  command",[499,1264,526],{"class":508},[499,1266,1267],{"class":508}," [",[499,1269,940],{"class":560},[499,1271,1272],{"class":529},"bin\u002Fconsole",[499,1274,940],{"class":560},[499,1276,1277],{"class":508},",",[499,1279,561],{"class":560},[499,1281,1282],{"class":529},"doctrine:migrations:migrate",[499,1284,940],{"class":560},[499,1286,1277],{"class":508},[499,1288,561],{"class":560},[499,1290,1291],{"class":529},"--no-interaction",[499,1293,940],{"class":560},[499,1295,1296],{"class":508},"]\n",[499,1298,1299,1302],{"class":501,"line":677},[499,1300,1301],{"class":505},"                  envFrom",[499,1303,509],{"class":508},[499,1305,1306,1309,1311],{"class":501,"line":692},[499,1307,1308],{"class":508},"                      -",[499,1310,614],{"class":505},[499,1312,509],{"class":508},[499,1314,1315,1318,1320],{"class":501,"line":707},[499,1316,1317],{"class":505},"                          name",[499,1319,526],{"class":508},[499,1321,627],{"class":529},[367,1323,1324],{},"This ensures migrations complete before any new pod receives traffic — no race conditions from parallel pod starts.",[387,1326,1328],{"id":1327},"ingress-with-tls","Ingress with TLS",[490,1330,1332],{"className":492,"code":1331,"language":494,"meta":495,"style":495},"apiVersion: networking.k8s.io\u002Fv1\nkind: Ingress\nmetadata:\n    annotations:\n        cert-manager.io\u002Fcluster-issuer: letsencrypt-prod\nspec:\n    tls:\n        - hosts: [api.example.com]\n          secretName: api-tls\n        - hosts: [www.example.com]\n          secretName: www-tls\n    rules:\n        - host: api.example.com\n          http:\n              paths:\n                  - path: \u002F\n                    backend:\n                        service:\n                            name: php-service\n                            port:\n                                number: 80\n        - host: www.example.com\n          http:\n              paths:\n                  - path: \u002F\n                    backend:\n                        service:\n                            name: nuxt-service\n                            port:\n                                number: 3000\n",[374,1333,1334,1343,1352,1358,1364,1373,1379,1386,1402,1412,1427,1436,1443,1454,1461,1468,1481,1488,1495,1505,1512,1523,1533,1539,1545,1555,1561,1567,1576,1582],{"__ignoreMap":495},[499,1335,1336,1338,1340],{"class":501,"line":502},[499,1337,1104],{"class":505},[499,1339,526],{"class":508},[499,1341,1342],{"class":529}," networking.k8s.io\u002Fv1\n",[499,1344,1345,1347,1349],{"class":501,"line":512},[499,1346,1114],{"class":505},[499,1348,526],{"class":508},[499,1350,1351],{"class":529}," Ingress\n",[499,1353,1354,1356],{"class":501,"line":520},[499,1355,1124],{"class":505},[499,1357,509],{"class":508},[499,1359,1360,1362],{"class":501,"line":533},[499,1361,823],{"class":505},[499,1363,509],{"class":508},[499,1365,1366,1368,1370],{"class":501,"line":544},[499,1367,831],{"class":505},[499,1369,526],{"class":508},[499,1371,1372],{"class":529}," letsencrypt-prod\n",[499,1374,1375,1377],{"class":501,"line":552},[499,1376,1198],{"class":505},[499,1378,509],{"class":508},[499,1380,1381,1384],{"class":501,"line":570},[499,1382,1383],{"class":505},"    tls",[499,1385,509],{"class":508},[499,1387,1388,1390,1393,1395,1397,1400],{"class":501,"line":585},[499,1389,611],{"class":508},[499,1391,1392],{"class":505}," hosts",[499,1394,526],{"class":508},[499,1396,1267],{"class":508},[499,1398,1399],{"class":529},"api.example.com",[499,1401,1296],{"class":508},[499,1403,1404,1407,1409],{"class":501,"line":600},[499,1405,1406],{"class":505},"          secretName",[499,1408,526],{"class":508},[499,1410,1411],{"class":529}," api-tls\n",[499,1413,1414,1416,1418,1420,1422,1425],{"class":501,"line":608},[499,1415,611],{"class":508},[499,1417,1392],{"class":505},[499,1419,526],{"class":508},[499,1421,1267],{"class":508},[499,1423,1424],{"class":529},"www.example.com",[499,1426,1296],{"class":508},[499,1428,1429,1431,1433],{"class":501,"line":619},[499,1430,1406],{"class":505},[499,1432,526],{"class":508},[499,1434,1435],{"class":529}," www-tls\n",[499,1437,1438,1441],{"class":501,"line":630},[499,1439,1440],{"class":505},"    rules",[499,1442,509],{"class":508},[499,1444,1445,1447,1450,1452],{"class":501,"line":637},[499,1446,611],{"class":508},[499,1448,1449],{"class":505}," host",[499,1451,526],{"class":508},[499,1453,855],{"class":529},[499,1455,1456,1459],{"class":501,"line":644},[499,1457,1458],{"class":505},"          http",[499,1460,509],{"class":508},[499,1462,1463,1466],{"class":501,"line":651},[499,1464,1465],{"class":505},"              paths",[499,1467,509],{"class":508},[499,1469,1470,1473,1476,1478],{"class":501,"line":661},[499,1471,1472],{"class":508},"                  -",[499,1474,1475],{"class":505}," path",[499,1477,526],{"class":508},[499,1479,1480],{"class":529}," \u002F\n",[499,1482,1483,1486],{"class":501,"line":670},[499,1484,1485],{"class":505},"                    backend",[499,1487,509],{"class":508},[499,1489,1490,1493],{"class":501,"line":677},[499,1491,1492],{"class":505},"                        service",[499,1494,509],{"class":508},[499,1496,1497,1500,1502],{"class":501,"line":692},[499,1498,1499],{"class":505},"                            name",[499,1501,526],{"class":508},[499,1503,1504],{"class":529}," php-service\n",[499,1506,1507,1510],{"class":501,"line":707},[499,1508,1509],{"class":505},"                            port",[499,1511,509],{"class":508},[499,1513,1514,1517,1519],{"class":501,"line":714},[499,1515,1516],{"class":505},"                                number",[499,1518,526],{"class":508},[499,1520,1522],{"class":1521},"scSvc"," 80\n",[499,1524,1525,1527,1529,1531],{"class":501,"line":723},[499,1526,611],{"class":508},[499,1528,1449],{"class":505},[499,1530,526],{"class":508},[499,1532,866],{"class":529},[499,1534,1535,1537],{"class":501,"line":732},[499,1536,1458],{"class":505},[499,1538,509],{"class":508},[499,1540,1541,1543],{"class":501,"line":737},[499,1542,1465],{"class":505},[499,1544,509],{"class":508},[499,1546,1547,1549,1551,1553],{"class":501,"line":744},[499,1548,1472],{"class":508},[499,1550,1475],{"class":505},[499,1552,526],{"class":508},[499,1554,1480],{"class":529},[499,1556,1557,1559],{"class":501,"line":751},[499,1558,1485],{"class":505},[499,1560,509],{"class":508},[499,1562,1563,1565],{"class":501,"line":761},[499,1564,1492],{"class":505},[499,1566,509],{"class":508},[499,1568,1569,1571,1573],{"class":501,"line":770},[499,1570,1499],{"class":505},[499,1572,526],{"class":508},[499,1574,1575],{"class":529}," nuxt-service\n",[499,1577,1578,1580],{"class":501,"line":777},[499,1579,1509],{"class":505},[499,1581,509],{"class":508},[499,1583,1584,1586,1588],{"class":501,"line":786},[499,1585,1516],{"class":505},[499,1587,526],{"class":508},[499,1589,1590],{"class":1521}," 3000\n",[387,1592,1594],{"id":1593},"resource-requests-and-limits-starting-point","Resource Requests and Limits (Starting Point)",[490,1596,1598],{"className":492,"code":1597,"language":494,"meta":495,"style":495},"php:\n    resources:\n        requests:\n            cpu: 100m\n            memory: 256Mi\n        limits:\n            memory: 512Mi\n\nnuxt:\n    resources:\n        requests:\n            cpu: 50m\n            memory: 128Mi\n        limits:\n            memory: 256Mi\n",[374,1599,1600,1606,1613,1620,1630,1640,1647,1656,1660,1666,1672,1678,1687,1696,1702],{"__ignoreMap":495},[499,1601,1602,1604],{"class":501,"line":502},[499,1603,419],{"class":505},[499,1605,509],{"class":508},[499,1607,1608,1611],{"class":501,"line":512},[499,1609,1610],{"class":505},"    resources",[499,1612,509],{"class":508},[499,1614,1615,1618],{"class":501,"line":520},[499,1616,1617],{"class":505},"        requests",[499,1619,509],{"class":508},[499,1621,1622,1625,1627],{"class":501,"line":533},[499,1623,1624],{"class":505},"            cpu",[499,1626,526],{"class":508},[499,1628,1629],{"class":529}," 100m\n",[499,1631,1632,1635,1637],{"class":501,"line":544},[499,1633,1634],{"class":505},"            memory",[499,1636,526],{"class":508},[499,1638,1639],{"class":529}," 256Mi\n",[499,1641,1642,1645],{"class":501,"line":552},[499,1643,1644],{"class":505},"        limits",[499,1646,509],{"class":508},[499,1648,1649,1651,1653],{"class":501,"line":570},[499,1650,1634],{"class":505},[499,1652,526],{"class":508},[499,1654,1655],{"class":529}," 512Mi\n",[499,1657,1658],{"class":501,"line":585},[499,1659,634],{"emptyLinePlaceholder":633},[499,1661,1662,1664],{"class":501,"line":600},[499,1663,431],{"class":505},[499,1665,509],{"class":508},[499,1667,1668,1670],{"class":501,"line":608},[499,1669,1610],{"class":505},[499,1671,509],{"class":508},[499,1673,1674,1676],{"class":501,"line":619},[499,1675,1617],{"class":505},[499,1677,509],{"class":508},[499,1679,1680,1682,1684],{"class":501,"line":630},[499,1681,1624],{"class":505},[499,1683,526],{"class":508},[499,1685,1686],{"class":529}," 50m\n",[499,1688,1689,1691,1693],{"class":501,"line":637},[499,1690,1634],{"class":505},[499,1692,526],{"class":508},[499,1694,1695],{"class":529}," 128Mi\n",[499,1697,1698,1700],{"class":501,"line":644},[499,1699,1644],{"class":505},[499,1701,509],{"class":508},[499,1703,1704,1706,1708],{"class":501,"line":651},[499,1705,1634],{"class":505},[499,1707,526],{"class":508},[499,1709,1639],{"class":529},[367,1711,1712],{},"Tune based on your traffic profile. FrankenPHP is efficient; Nuxt SSR memory usage grows with concurrent requests.",[387,1714,1716],{"id":1715},"health-checks","Health Checks",[367,1718,1719,1720,1723],{},"The PHP (FrankenPHP) pod uses a TCP socket for liveness — it just checks the port is listening — and ",[374,1721,1722],{},"\u002F_api\u002F_\u002Fsite_config_parameters.jsonld"," for readiness, which confirms Symfony is fully booted and the database is reachable.",[367,1725,1726,1727,1730,1731,1734,1735,1738],{},"The Nuxt pod uses ",[374,1728,1729],{},"\u002F_cwa\u002Fhealthcheck"," for readiness. This endpoint is a server route provided by the ",[374,1732,1733],{},"@cwa\u002Fnuxt"," module (",[374,1736,1737],{},"server\u002Froutes\u002F_cwa\u002Fcwa-healthcheck.get.ts",") — it returns 200 when the Nuxt server is running.",[490,1740,1742],{"className":492,"code":1741,"language":494,"meta":495,"style":495},"php:\n    startupProbe:\n        tcpSocket:\n            port: 80\n        failureThreshold: 30\n        periodSeconds: 10\n    livenessProbe:\n        tcpSocket:\n            port: 80\n        initialDelaySeconds: 5\n        periodSeconds: 5\n    readinessProbe:\n        httpGet:\n            path: \u002F_api\u002F_\u002Fsite_config_parameters.jsonld\n            port: 80\n        initialDelaySeconds: 5\n        periodSeconds: 10\n\nnuxt:\n    readinessProbe:\n        httpGet:\n            path: \u002F_cwa\u002Fhealthcheck\n            port: 3000\n",[374,1743,1744,1750,1757,1764,1773,1783,1793,1800,1806,1814,1824,1832,1839,1846,1856,1864,1872,1880,1884,1890,1896,1902,1911],{"__ignoreMap":495},[499,1745,1746,1748],{"class":501,"line":502},[499,1747,419],{"class":505},[499,1749,509],{"class":508},[499,1751,1752,1755],{"class":501,"line":512},[499,1753,1754],{"class":505},"    startupProbe",[499,1756,509],{"class":508},[499,1758,1759,1762],{"class":501,"line":520},[499,1760,1761],{"class":505},"        tcpSocket",[499,1763,509],{"class":508},[499,1765,1766,1769,1771],{"class":501,"line":533},[499,1767,1768],{"class":505},"            port",[499,1770,526],{"class":508},[499,1772,1522],{"class":1521},[499,1774,1775,1778,1780],{"class":501,"line":544},[499,1776,1777],{"class":505},"        failureThreshold",[499,1779,526],{"class":508},[499,1781,1782],{"class":1521}," 30\n",[499,1784,1785,1788,1790],{"class":501,"line":552},[499,1786,1787],{"class":505},"        periodSeconds",[499,1789,526],{"class":508},[499,1791,1792],{"class":1521}," 10\n",[499,1794,1795,1798],{"class":501,"line":570},[499,1796,1797],{"class":505},"    livenessProbe",[499,1799,509],{"class":508},[499,1801,1802,1804],{"class":501,"line":585},[499,1803,1761],{"class":505},[499,1805,509],{"class":508},[499,1807,1808,1810,1812],{"class":501,"line":600},[499,1809,1768],{"class":505},[499,1811,526],{"class":508},[499,1813,1522],{"class":1521},[499,1815,1816,1819,1821],{"class":501,"line":608},[499,1817,1818],{"class":505},"        initialDelaySeconds",[499,1820,526],{"class":508},[499,1822,1823],{"class":1521}," 5\n",[499,1825,1826,1828,1830],{"class":501,"line":619},[499,1827,1787],{"class":505},[499,1829,526],{"class":508},[499,1831,1823],{"class":1521},[499,1833,1834,1837],{"class":501,"line":630},[499,1835,1836],{"class":505},"    readinessProbe",[499,1838,509],{"class":508},[499,1840,1841,1844],{"class":501,"line":637},[499,1842,1843],{"class":505},"        httpGet",[499,1845,509],{"class":508},[499,1847,1848,1851,1853],{"class":501,"line":644},[499,1849,1850],{"class":505},"            path",[499,1852,526],{"class":508},[499,1854,1855],{"class":529}," \u002F_api\u002F_\u002Fsite_config_parameters.jsonld\n",[499,1857,1858,1860,1862],{"class":501,"line":651},[499,1859,1768],{"class":505},[499,1861,526],{"class":508},[499,1863,1522],{"class":1521},[499,1865,1866,1868,1870],{"class":501,"line":661},[499,1867,1818],{"class":505},[499,1869,526],{"class":508},[499,1871,1823],{"class":1521},[499,1873,1874,1876,1878],{"class":501,"line":670},[499,1875,1787],{"class":505},[499,1877,526],{"class":508},[499,1879,1792],{"class":1521},[499,1881,1882],{"class":501,"line":677},[499,1883,634],{"emptyLinePlaceholder":633},[499,1885,1886,1888],{"class":501,"line":692},[499,1887,431],{"class":505},[499,1889,509],{"class":508},[499,1891,1892,1894],{"class":501,"line":707},[499,1893,1836],{"class":505},[499,1895,509],{"class":508},[499,1897,1898,1900],{"class":501,"line":714},[499,1899,1843],{"class":505},[499,1901,509],{"class":508},[499,1903,1904,1906,1908],{"class":501,"line":723},[499,1905,1850],{"class":505},[499,1907,526],{"class":508},[499,1909,1910],{"class":529}," \u002F_cwa\u002Fhealthcheck\n",[499,1912,1913,1915,1917],{"class":501,"line":732},[499,1914,1768],{"class":505},[499,1916,526],{"class":508},[499,1918,1590],{"class":1521},[387,1920,1922],{"id":1921},"rolling-updates","Rolling Updates",[367,1924,1925,1926,1929],{},"Both PHP and Nuxt use ",[374,1927,1928],{},"RollingUpdate"," strategy. Old pods continue serving until new pods pass their readiness probe, ensuring zero downtime.",[490,1931,1933],{"className":492,"code":1932,"language":494,"meta":495,"style":495},"strategy:\n    type: RollingUpdate\n    rollingUpdate:\n        maxSurge: 1\n        maxUnavailable: 0\n",[374,1934,1935,1942,1952,1959,1969],{"__ignoreMap":495},[499,1936,1937,1940],{"class":501,"line":502},[499,1938,1939],{"class":505},"strategy",[499,1941,509],{"class":508},[499,1943,1944,1947,1949],{"class":501,"line":512},[499,1945,1946],{"class":505},"    type",[499,1948,526],{"class":508},[499,1950,1951],{"class":529}," RollingUpdate\n",[499,1953,1954,1957],{"class":501,"line":520},[499,1955,1956],{"class":505},"    rollingUpdate",[499,1958,509],{"class":508},[499,1960,1961,1964,1966],{"class":501,"line":533},[499,1962,1963],{"class":505},"        maxSurge",[499,1965,526],{"class":508},[499,1967,1968],{"class":1521}," 1\n",[499,1970,1971,1974,1976],{"class":501,"line":544},[499,1972,1973],{"class":505},"        maxUnavailable",[499,1975,526],{"class":508},[499,1977,1978],{"class":1521}," 0\n",[387,1980,1982],{"id":1981},"rollback","Rollback",[367,1984,1985],{},"If a deploy fails:",[490,1987,1989],{"className":891,"code":1988,"language":893,"meta":495,"style":495},"helm rollback cwa        # revert to previous Helm release\nkubectl get pods -w      # watch the rollback progress\n",[374,1990,1991,2005],{"__ignoreMap":495},[499,1992,1993,1996,1999,2002],{"class":501,"line":502},[499,1994,1995],{"class":900},"helm",[499,1997,1998],{"class":529}," rollback",[499,2000,2001],{"class":529}," cwa",[499,2003,2004],{"class":1098},"        # revert to previous Helm release\n",[499,2006,2007,2009,2012,2015,2018],{"class":501,"line":512},[499,2008,901],{"class":900},[499,2010,2011],{"class":529}," get",[499,2013,2014],{"class":529}," pods",[499,2016,2017],{"class":922}," -w",[499,2019,2020],{"class":1098},"      # watch the rollback progress\n",[367,2022,2023],{},"Helm tracks release history. The migration Job won't re-run on rollback (it only runs on install\u002Fupgrade), so a database rollback requires a separate migration reversal if needed.",[2025,2026,2027],"style",{},"html pre.shiki code .s-h7I, html code.shiki .s-h7I{--shiki-light:#22863A;--shiki-default:#85E89D;--shiki-dark:#F07178}html pre.shiki code .sOvfz, html code.shiki .sOvfz{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#89DDFF}html pre.shiki code .sLL54, html code.shiki .sLL54{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#C3E88D}html pre.shiki code .seSrl, html code.shiki .seSrl{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#89DDFF}html pre.shiki code .swWMF, html code.shiki .swWMF{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#FF9CAC}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 .sRCss, html code.shiki .sRCss{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#FFCB6B}html pre.shiki code .sc2zw, html code.shiki .sc2zw{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#BABED8}html pre.shiki code .szhYu, html code.shiki .szhYu{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#C3E88D}html pre.shiki code .sTBSN, html code.shiki .sTBSN{--shiki-light:#6A737D;--shiki-light-font-style:inherit;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .scSvc, html code.shiki .scSvc{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#F78C6C}",{"title":495,"searchDepth":512,"depth":512,"links":2029},[2030,2031,2032,2033,2034,2035,2036,2037,2038,2039],{"id":389,"depth":512,"text":390},{"id":487,"depth":512,"text":488},{"id":880,"depth":512,"text":881},{"id":958,"depth":512,"text":959},{"id":1084,"depth":512,"text":1085},{"id":1327,"depth":512,"text":1328},{"id":1593,"depth":512,"text":1594},{"id":1715,"depth":512,"text":1716},{"id":1921,"depth":512,"text":1922},{"id":1981,"depth":512,"text":1982},"Deploying the CWA stack to Kubernetes using Helm — values configuration, secrets management, migration Jobs, and rolling updates.","md",null,{},{"title":351,"description":2040},"6vZ3jc8oSh2ubYxvhHsz5qcOnDgqQ9g4nBzcHenMnZU",[2047,2049],{"title":347,"path":348,"stem":349,"description":2048,"children":-1},"The Docker Compose setup for local development and production — services, environment variables, volumes, and build workflow.",{"title":355,"path":356,"stem":357,"description":2050,"children":-1},"The template ships full CI\u002FCD for both GitLab CI and GitHub Actions — Docker Buildx builds, tests, per-branch review apps, and staged Kubernetes deployments via Helm.",1782512903667]