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