@bluedynamics/cdk8s-plone 0.1.40 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.jsii +294 -28
  2. package/API.md +225 -10
  3. package/CLAUDE.md +1 -1
  4. package/README.md +4 -4
  5. package/docs/superpowers/plans/2026-06-12-configurable-service-spec.md +608 -0
  6. package/docs/superpowers/specs/2026-06-12-configurable-service-spec-design.md +192 -0
  7. package/documentation/sources/explanation/architecture.md +7 -6
  8. package/documentation/sources/explanation/features.md +9 -7
  9. package/documentation/sources/how-to/{deploy-classic-ui.md → deploy-blicca.md} +43 -39
  10. package/documentation/sources/how-to/deploy-production-volto.md +1 -1
  11. package/documentation/sources/how-to/index.md +1 -1
  12. package/documentation/sources/reference/api/index.md +1 -1
  13. package/documentation/sources/reference/configuration-options.md +55 -11
  14. package/documentation/sources/tutorials/01-quick-start.md +1 -1
  15. package/examples/{classic-ui → blicca}/README.md +24 -25
  16. package/examples/{classic-ui → blicca}/__snapshots__/main.test.ts.snap +3 -3
  17. package/examples/{classic-ui → blicca}/config/varnish.tpl.vcl +1 -1
  18. package/examples/{classic-ui → blicca}/main.test.ts +3 -3
  19. package/examples/{classic-ui → blicca}/main.ts +6 -6
  20. package/examples/{classic-ui → blicca}/package.json +2 -2
  21. package/lib/httpcache.js +1 -1
  22. package/lib/index.d.ts +1 -0
  23. package/lib/index.js +1 -1
  24. package/lib/plone.d.ts +23 -5
  25. package/lib/plone.js +22 -8
  26. package/lib/service.d.ts +81 -0
  27. package/lib/service.js +24 -6
  28. package/lib/vinylcache.js +1 -1
  29. package/package.json +1 -1
  30. /package/examples/{classic-ui → blicca}/.env.example +0 -0
  31. /package/examples/{classic-ui → blicca}/cdk8s.yaml +0 -0
  32. /package/examples/{classic-ui → blicca}/ingress.ts +0 -0
  33. /package/examples/{classic-ui → blicca}/jest.config.js +0 -0
  34. /package/examples/{classic-ui → blicca}/postgres.bitnami.ts +0 -0
  35. /package/examples/{classic-ui → blicca}/postgres.cloudnativepg.ts +0 -0
@@ -0,0 +1,192 @@
1
+ # Design: Generisch steuerbare Service-Resourcen
2
+
3
+ **Datum:** 2026-06-12
4
+ **Branch:** `feat/configurable-service-spec`
5
+ **Status:** Approved (Design)
6
+
7
+ ## Problem
8
+
9
+ Die von cdk8s-plone generierten Kubernetes-`Service`-Resourcen sind schlecht
10
+ steuerbar. Konkreter Anlass: Es soll `spec.trafficDistribution` gesetzt werden
11
+ können — das geht aktuell nicht. Generell ist die `Service`-Spec faktisch
12
+ hartcodiert: In [`src/service.ts`](../../../src/service.ts) baut `PloneService`
13
+ über das rohe `k8s.KubeService` nur `spec.ports` + `spec.selector`. Alle anderen
14
+ Felder (`type`, `sessionAffinity`, `externalTrafficPolicy`,
15
+ `internalTrafficPolicy`, `publishNotReadyAddresses`, `loadBalancerClass`,
16
+ `trafficDistribution`, …) sind nicht durchgereicht.
17
+
18
+ Zusätzlich ist das Plumbing nicht wartbar: Nach oben (in
19
+ [`src/plone.ts`](../../../src/plone.ts)) wird pro Feld einzeln geplumbt — aktuell
20
+ nur `serviceAnnotations`. Jedes neue Feld bräuchte Änderungen an mehreren Stellen.
21
+
22
+ ## Ziel
23
+
24
+ Service-Spec-Felder konfigurierbar machen — möglichst generisch, mit wenig
25
+ Pflegeaufwand pro Feld, JSII-/Python-kompatibel, ohne Breaking Change.
26
+
27
+ ## Designentscheidungen (bestätigt)
28
+
29
+ - **Hybrid-Ansatz:** Kuratierte typisierte Props für die häufigen Felder PLUS
30
+ ein generischer Escape-Hatch für alles Übrige.
31
+ - **Gruppiertes Plumbing:** Ein einziges `service`-Objekt in `PloneBaseOptions`
32
+ statt flacher Einzel-Props. Neue Felder ändern nur den Config-Typ.
33
+ - **`overrides`-Präzedenz:** `overrides` darf *alles* überschreiben (auch
34
+ `ports`/`selector`) — volle Kontrolle für Power-User, dokumentiert.
35
+
36
+ ## Lösung
37
+
38
+ ### 1. Neuer Config-Typ `PloneServiceSpec` (in `src/service.ts`)
39
+
40
+ ```typescript
41
+ export interface PloneServiceSpec {
42
+ // Kuratierte, häufig gebrauchte Felder (alle optional, typisiert, dokumentiert):
43
+ readonly type?: string; // ClusterIP | NodePort | LoadBalancer | ExternalName
44
+ readonly trafficDistribution?: string; // z.B. 'PreferClose'
45
+ readonly sessionAffinity?: string; // 'ClientIP' | 'None'
46
+ readonly externalTrafficPolicy?: string; // 'Cluster' | 'Local'
47
+ readonly internalTrafficPolicy?: string; // 'Cluster' | 'Local'
48
+ readonly publishNotReadyAddresses?: boolean;
49
+ readonly loadBalancerClass?: string;
50
+ readonly loadBalancerSourceRanges?: string[];
51
+ readonly annotations?: { [name: string]: string }; // ersetzt serviceAnnotations
52
+ readonly labels?: { [name: string]: string };
53
+
54
+ // Escape-Hatch für alles Übrige (ipFamilyPolicy, clusterIP, ...):
55
+ readonly overrides?: { [key: string]: any };
56
+ }
57
+ ```
58
+
59
+ Der `overrides`-Typ ist ein freiform-Record `{ [key: string]: any }` — deckt
60
+ jedes aktuelle und künftige k8s-Service-Feld ab, ohne dass Code angefasst werden
61
+ muss.
62
+
63
+ > **JSII-Constraint (entdeckt bei der Umsetzung):** Ursprünglich war
64
+ > `overrides?: k8s.ServiceSpec` geplant. JSII lehnt das ab
65
+ > (`JSII3000: Exported APIs cannot use un-exported type`), weil die generierten
66
+ > Typen aus `src/imports/k8s.ts` nicht Teil der JSII-Assembly sind. Den gesamten
67
+ > k8s-Import zu re-exportieren würde die öffentliche API mit der kompletten
68
+ > Kubernetes-API zumüllen. Ein freiform-Record ist die idiomatische, voll
69
+ > JSII-/Python-fähige (Python: `dict`) Lösung für einen generischen Escape-Hatch
70
+ > und bleibt „für alles" offen. Die kuratierten Felder bleiben typisiert.
71
+
72
+ ### 2. `PloneServiceOptions` erweitern
73
+
74
+ `PloneServiceOptions` (das interne Interface von `PloneService`) bekommt ein
75
+ optionales `spec?: PloneServiceSpec`. Die bestehenden Pflichtfelder
76
+ (`targetPort`, `selectorLabel`, `portName`) bleiben unverändert. Das bestehende
77
+ `annotations` und `labels` auf `PloneServiceOptions` bleiben erhalten
78
+ (construct-managed Defaults), werden aber mit den Werten aus `spec` zusammen-
79
+ geführt (siehe Merge-Regeln).
80
+
81
+ ### 3. Merge-Reihenfolge in `PloneService`
82
+
83
+ Vorhersagbar, shallow (ServiceSpec-Felder sind weitgehend flach):
84
+
85
+ ```
86
+ finalSpec = { ...generatedBase, ...curatedFields, ...overrides }
87
+ ```
88
+
89
+ Präzedenz steigend:
90
+
91
+ 1. **Construct-Basis:** `ports`, `selector` (aus `targetPort`/`portName`/`selectorLabel`).
92
+ 2. **Kuratierte Felder:** alle gesetzten Felder aus `spec` (außer `annotations`,
93
+ `labels`, `overrides`).
94
+ 3. **`overrides`:** `k8s.ServiceSpec`-Partial — höchste Präzedenz, überschreibt
95
+ auch `ports`/`selector`. Dokumentiert als „at your own risk".
96
+
97
+ `annotations` und `labels` aus `spec` fließen in `metadata` (nicht in `spec`):
98
+ - `metadata.labels = { ...spec.labels, ...constructManagedLabels }`
99
+ (construct-managed `part-of`/`managed-by` gewinnen — wie bisher).
100
+ - `metadata.annotations = { ...serviceAnnotations (deprecated), ...spec.annotations }`
101
+ (neue `spec.annotations` gewinnen bei Konflikt).
102
+
103
+ ### 4. Plumbing: ein Punkt in `PloneBaseOptions` (`src/plone.ts`)
104
+
105
+ ```typescript
106
+ /**
107
+ * Service configuration (type, trafficDistribution, sessionAffinity,
108
+ * annotations, raw spec overrides, ...). Applies to the component's Service.
109
+ */
110
+ readonly service?: PloneServiceSpec;
111
+
112
+ /**
113
+ * @deprecated use `service.annotations` instead
114
+ */
115
+ readonly serviceAnnotations?: { [name: string]: string };
116
+ ```
117
+
118
+ `backend`/`frontend` erben beide aus `PloneBaseOptions`, daher gilt die
119
+ `service`-Config automatisch für beide Services an genau einer Stelle.
120
+
121
+ In `plone.ts` (Backend-Service ~Z. 468, Frontend-Service ~Z. 570) wird
122
+ `spec` durchgereicht und die deprecated `serviceAnnotations` weiter unterstützt:
123
+
124
+ ```typescript
125
+ new PloneService(backendDeployment, 'service', {
126
+ // ... unverändert: labels, targetPort, selectorLabel, portName ...
127
+ spec: {
128
+ ...backend.service,
129
+ annotations: { ...backend.serviceAnnotations, ...backend.service?.annotations },
130
+ },
131
+ });
132
+ ```
133
+
134
+ ### 5. Backward-Compatibility
135
+
136
+ `serviceAnnotations` bleibt funktionsfähig, wird als `@deprecated` markiert und
137
+ mit `service.annotations` zusammengeführt (neue Variante gewinnt). Kein Breaking
138
+ Change. Bestehende Snapshots ohne `service` bleiben unverändert (alle neuen
139
+ Felder sind optional, ungesetzt → keine Spec-Änderung).
140
+
141
+ ### 6. Tests (`test/service.test.ts`)
142
+
143
+ Neue Snapshot-/Assertion-Fälle:
144
+
145
+ - `trafficDistribution: 'PreferClose'` → erscheint in `spec`.
146
+ - `type: 'LoadBalancer'` + `loadBalancerSourceRanges` → erscheinen in `spec`.
147
+ - `sessionAffinity` / `externalTrafficPolicy` gesetzt.
148
+ - `overrides` (z.B. `ipFamilyPolicy`) → erscheint in `spec`.
149
+ - Präzedenz: `overrides` schlägt kuratiertes Feld (z.B. beide setzen `type`,
150
+ `overrides` gewinnt).
151
+ - Backward-Compat: nur `serviceAnnotations` gesetzt → unverändertes Verhalten;
152
+ `serviceAnnotations` + `service.annotations` → korrekt gemergt.
153
+
154
+ Snapshots aktualisieren via `npx projen test -- -u`.
155
+
156
+ ### 7. Dokumentation
157
+
158
+ Beim Schreiben/Editieren der Doku den Skill **`plone-doc-style:author`**
159
+ verwenden (Diataxis-Quadranten-Zuordnung, MyST-Markup, Style-Enforcement),
160
+ soweit es sinnvoll ist — d.h. für die handgeschriebenen Seiten unter
161
+ `documentation/sources/` (Reference + How-to). Nicht für auto-generierte
162
+ Artefakte (`API.md`).
163
+
164
+ - **`API.md`** ist auto-generiert (`npx projen docgen`) — kein manuelles Edit,
165
+ aber nach Implementierung neu generieren.
166
+ - **`documentation/sources/reference/configuration-options.md`:** Den Abschnitt
167
+ „Annotations" (~Z. 200) zu einem Abschnitt „Service" erweitern bzw. einen
168
+ neuen Abschnitt für `PloneServiceSpec` ergänzen: Tabelle der kuratierten
169
+ Felder + `overrides`, mit Beispiel (`trafficDistribution`, `LoadBalancer`).
170
+ `serviceAnnotations` als deprecated kennzeichnen und auf `service.annotations`
171
+ verweisen.
172
+ - **`documentation/sources/how-to/`:** In `deploy-production-volto.md` ein
173
+ kurzes Beispiel ergänzen (z.B. `trafficDistribution: 'PreferClose'` für
174
+ topologie-nahes Routing), falls thematisch passend.
175
+ - Doku-Build prüfen: `cd documentation && make docs`.
176
+
177
+ ## Betroffene Dateien
178
+
179
+ - `src/service.ts` — neuer `PloneServiceSpec`-Typ, erweiterte `PloneServiceOptions`, Merge-Logik.
180
+ - `src/plone.ts` — `service`-Prop in `PloneBaseOptions`, Plumbing in Backend/Frontend, `serviceAnnotations` deprecaten.
181
+ - `test/service.test.ts` (+ Snapshots) — neue Testfälle.
182
+ - `documentation/sources/reference/configuration-options.md` — Service-Config dokumentieren.
183
+ - `documentation/sources/how-to/deploy-production-volto.md` — optionales Beispiel.
184
+ - `API.md` — regenerieren via `npx projen docgen`.
185
+
186
+ ## Nicht im Scope (YAGNI)
187
+
188
+ - Multi-Port-Services (mehrere `ports`-Einträge) — über `overrides` möglich,
189
+ aber kein kuratiertes Feature.
190
+ - Eigene Validierung der Enum-Strings (`type`, `sessionAffinity`, …) — k8s
191
+ validiert serverseitig; wir bilden die Strings 1:1 ab.
192
+ - Separate Service-Configs pro Service jenseits von backend/frontend.
@@ -21,19 +21,20 @@ cdk8s-plone provides CDK8S constructs for deploying Plone CMS on Kubernetes. The
21
21
 
22
22
  cdk8s-plone supports two deployment variants:
23
23
 
24
- **Volto (Modern)**
24
+ **Volto (React single-page frontend)**
25
25
  - React-based frontend (Volto)
26
26
  - REST API backend (Plone)
27
27
  - Separate services for frontend and backend
28
- - Modern user experience
29
28
  - Headless CMS architecture
30
29
 
31
- **Classic UI (Traditional)**
32
- - Server-side rendered Plone
30
+ **Blicca (server-side rendered)**
31
+ - The Plone backend renders the UI and serves HTML directly
33
32
  - Single integrated service
34
- - Traditional Plone experience
35
33
  - Simpler deployment model
36
34
 
35
+ Blicca is the new name for the variant Plone formerly called "Classic UI".
36
+ Both approaches are equally current; they differ in where rendering happens, not in how modern they are.
37
+
37
38
  ### High availability
38
39
 
39
40
  **Replica Management**
@@ -251,7 +252,7 @@ For a typical Volto deployment, cdk8s-plone creates:
251
252
  - Better resource utilization
252
253
  - Clear separation of concerns
253
254
 
254
- **When to use Classic UI:**
255
+ **When to use Blicca:**
255
256
  - Simpler deployment model
256
257
  - Lower resource requirements
257
258
  - Legacy integrations
@@ -19,17 +19,19 @@ Complete overview of cdk8s-plone features and capabilities.
19
19
 
20
20
  cdk8s-plone supports two deployment modes to match your requirements:
21
21
 
22
- **Volto (Modern React Frontend)**
23
- - Modern React-based user interface
22
+ **Volto (React single-page frontend)**
23
+ - React-based user interface
24
24
  - Headless CMS architecture
25
25
  - Separate frontend and backend services
26
- - Best for: New projects, modern UX requirements, API-first architectures
26
+ - Best for: API-first architectures, SPA frontends
27
27
 
28
- **Classic UI (Traditional Plone)**
29
- - Server-side rendered interface
28
+ **Blicca (server-side rendered Plone)**
29
+ - The Plone backend renders the UI and serves HTML directly
30
30
  - Integrated single-service deployment
31
- - Traditional Plone experience
32
- - Best for: Legacy migrations, existing add-ons, simpler deployments
31
+ - Best for: single-service setups, legacy migrations, existing add-ons
32
+
33
+ Blicca is the new name for the variant Plone formerly called "Classic UI".
34
+ Both are equally current; they differ in their rendering approach.
33
35
 
34
36
  See {doc}`architecture` for a deeper architectural comparison of the two variants.
35
37
 
@@ -1,37 +1,40 @@
1
1
  ---
2
2
  myst:
3
3
  html_meta:
4
- "description": "Deploy the Classic UI example: server-side rendered Plone with PostgreSQL, Varnish caching, and ingress with TLS."
5
- "property=og:description": "Deploy the Classic UI example: server-side rendered Plone with PostgreSQL, Varnish caching, and ingress with TLS."
6
- "property=og:title": "Deploy Classic UI example"
7
- "keywords": "Plone, cdk8s, Kubernetes, Classic UI, PostgreSQL, Varnish, ingress"
4
+ "description": "Deploy the Blicca example: server-side rendered Plone with PostgreSQL, Varnish caching, and ingress with TLS."
5
+ "property=og:description": "Deploy the Blicca example: server-side rendered Plone with PostgreSQL, Varnish caching, and ingress with TLS."
6
+ "property=og:title": "Deploy Blicca example"
7
+ "keywords": "Plone, cdk8s, Kubernetes, Blicca, Classic UI, PostgreSQL, Varnish, ingress"
8
8
  ---
9
9
 
10
- # Deploy Classic UI example
10
+ # Deploy Blicca example
11
11
 
12
- This guide shows you how to deploy the Classic UI example to your Kubernetes cluster.
12
+ This guide shows you how to deploy the Blicca example to your Kubernetes cluster.
13
+
14
+ Blicca is the new name for what Plone formerly called "Classic UI".
13
15
 
14
16
  ## What you'll deploy
15
17
 
16
- The [Classic UI example](https://github.com/bluedynamics/cdk8s-plone/tree/main/examples/classic-ui) provides traditional Plone with server-side rendering:
18
+ The [Blicca example](https://github.com/bluedynamics/cdk8s-plone/tree/main/examples/blicca) provides Plone with server-side rendering:
17
19
 
18
- - **Plone 6.1 Classic UI** (traditional interface, no separate frontend)
20
+ - **Plone 6.1 Blicca** (backend renders the UI, no separate frontend)
19
21
  - **PostgreSQL** with RelStorage (CloudNativePG or Bitnami)
20
22
  - **Varnish HTTP caching** with kube-httpcache
21
23
  - **Ingress** with TLS (Traefik or Kong)
22
24
  - **Simpler architecture** (single backend service)
23
25
 
24
- ## Classic UI vs Volto
26
+ ## Blicca vs Volto
25
27
 
26
- | Feature | Classic UI | Volto |
28
+ | Feature | Blicca | Volto |
27
29
  |---------|-----------|-------|
28
30
  | **Architecture** | Single backend | Frontend + Backend |
29
31
  | **Rendering** | Server-side | Client-side (React) |
30
32
  | **Deployment** | Simpler | More complex |
31
- | **Best for** | Migrations, intranets | Modern projects |
33
+ | **Best for** | Single-service setups, migrations | API-first projects, SPA frontends |
32
34
 
33
35
  :::{tip}
34
- Choose Classic UI if you're migrating from older Plone versions or need specific Classic UI add-ons. For new projects, consider [Volto](deploy-production-volto.md).
36
+ Choose Blicca if you want a single backend service without a separate frontend, or if you need Blicca-specific add-ons.
37
+ For the React single-page frontend approach, consider [Volto](deploy-production-volto.md).
35
38
  :::
36
39
 
37
40
  ## Prerequisites
@@ -49,7 +52,7 @@ See [Setup Prerequisites](setup-prerequisites.md) for detailed instructions.
49
52
 
50
53
  ```shell
51
54
  git clone https://github.com/bluedynamics/cdk8s-plone.git
52
- cd cdk8s-plone/examples/classic-ui
55
+ cd cdk8s-plone/examples/blicca
53
56
  ```
54
57
 
55
58
  ## Step 2: Install dependencies
@@ -91,7 +94,8 @@ DATABASE=cloudnativepg
91
94
  ```
92
95
 
93
96
  :::{note}
94
- Classic UI only needs one image (backend). There's no frontend image configuration.
97
+ Blicca only needs one image (backend).
98
+ There's no frontend image configuration.
95
99
  :::
96
100
 
97
101
  ## Step 5: Generate manifests
@@ -100,28 +104,28 @@ Classic UI only needs one image (backend). There's no frontend image configurati
100
104
  npm run synth
101
105
  ```
102
106
 
103
- Creates `dist/plone-classic.k8s.yaml` (~27 KB, smaller than Volto's 32 KB).
107
+ Creates `dist/plone-blicca.k8s.yaml` (~27 KB, smaller than Volto's 32 KB).
104
108
 
105
109
  ## Step 6: Review manifests
106
110
 
107
111
  ```shell
108
112
  # Count resources
109
- grep "^kind:" dist/plone-classic.k8s.yaml | sort | uniq -c
113
+ grep "^kind:" dist/plone-blicca.k8s.yaml | sort | uniq -c
110
114
 
111
115
  # Dry run
112
- kubectl apply --dry-run=client -f dist/plone-classic.k8s.yaml
116
+ kubectl apply --dry-run=client -f dist/plone-blicca.k8s.yaml
113
117
  ```
114
118
 
115
119
  ## Step 7: Deploy
116
120
 
117
121
  ```shell
118
- kubectl apply -f dist/plone-classic.k8s.yaml
122
+ kubectl apply -f dist/plone-blicca.k8s.yaml
119
123
  ```
120
124
 
121
125
  Or to a specific namespace:
122
126
 
123
127
  ```shell
124
- kubectl apply -f dist/plone-classic.k8s.yaml -n plone
128
+ kubectl apply -f dist/plone-blicca.k8s.yaml -n plone
125
129
  ```
126
130
 
127
131
  ## Step 8: Monitor deployment
@@ -137,7 +141,7 @@ kubectl wait --for=condition=ready pod \
137
141
  ```
138
142
 
139
143
  :::{note}
140
- Classic UI deploys fewer pods than Volto (no frontend pods).
144
+ Blicca deploys fewer pods than Volto (no frontend pods).
141
145
  :::
142
146
 
143
147
  ## Step 9: Verify services
@@ -147,7 +151,7 @@ kubectl get svc -l app.kubernetes.io/part-of=plone
147
151
  ```
148
152
 
149
153
  You should see:
150
- - `plone-backend` (Classic UI service)
154
+ - `plone-backend` (Blicca service)
151
155
  - `plone-httpcache` (Varnish cache)
152
156
  - Database service
153
157
 
@@ -174,17 +178,17 @@ Once DNS and TLS are ready:
174
178
  - **Site ID**: `Plone`
175
179
  - **Title**: Your site name
176
180
  - **Language**: Select language
177
- - **Add-ons**: Choose Classic UI add-ons
181
+ - **Add-ons**: Choose Blicca add-ons
178
182
  4. Click "Create Plone Site"
179
183
 
180
184
  ## Key differences from Volto
181
185
 
182
186
  ### Architecture
183
187
 
184
- Classic UI routing is simpler - all traffic goes to the backend:
188
+ Blicca routing is simpler - all traffic goes to the backend:
185
189
 
186
190
  ```
187
- Traffic → Ingress → Varnish → Plone Backend (Classic UI)
191
+ Traffic → Ingress → Varnish → Plone Backend (Blicca)
188
192
  ```
189
193
 
190
194
  Compared to Volto:
@@ -195,7 +199,7 @@ Traffic → Ingress → {Varnish → Frontend, Backend}
195
199
 
196
200
  ### Ingress routes
197
201
 
198
- Classic UI uses virtual host rewriting for direct backend access:
202
+ Blicca uses virtual host rewriting for direct backend access:
199
203
 
200
204
  - **Cached**: Routes through Varnish to backend
201
205
  - **Uncached**: Direct to backend with VirtualHostBase rewrite
@@ -225,7 +229,7 @@ Common issues:
225
229
  - Memory limits too low
226
230
  - Image pull errors
227
231
 
228
- ### Classic UI interface not loading
232
+ ### Blicca interface not loading
229
233
 
230
234
  1. Check if backend pods are running:
231
235
  ```shell
@@ -244,14 +248,14 @@ Common issues:
244
248
 
245
249
  ### Add-on compatibility
246
250
 
247
- Some add-ons are Volto-specific. For Classic UI:
248
- - Use Classic UI themes (not Volto themes)
249
- - Check add-on compatibility with Plone 6 Classic UI
251
+ Some add-ons are Volto-specific. For Blicca:
252
+ - Use Blicca themes (not Volto themes)
253
+ - Check add-on compatibility with Plone 6 Blicca
250
254
  - Avoid Volto-specific frontend add-ons
251
255
 
252
256
  ## Migrating to Volto
253
257
 
254
- If you want to migrate from Classic UI to Volto later:
258
+ If you want to migrate from Blicca to Volto later:
255
259
 
256
260
  1. Keep your backend deployment (same configuration)
257
261
  2. Add Volto frontend from the [Volto example](deploy-production-volto.md)
@@ -268,7 +272,7 @@ Edit `main.ts` to customize:
268
272
 
269
273
  ```typescript
270
274
  const plone = new Plone(this, 'plone', {
271
- variant: PloneVariant.CLASSICUI,
275
+ variant: PloneVariant.BLICCA,
272
276
  backend: {
273
277
  image: 'plone/plone-backend:6.1.3',
274
278
  replicas: 2,
@@ -281,9 +285,9 @@ const plone = new Plone(this, 'plone', {
281
285
 
282
286
  ### Varnish caching
283
287
 
284
- Edit `config/varnish.tpl.vcl` for caching rules specific to Classic UI.
288
+ Edit `config/varnish.tpl.vcl` for caching rules specific to Blicca.
285
289
 
286
- Classic UI VCL is simpler than Volto's - all traffic routes to one backend.
290
+ Blicca VCL is simpler than Volto's - all traffic routes to one backend.
287
291
 
288
292
  ## Scaling
289
293
 
@@ -298,14 +302,14 @@ backend: {
298
302
  Then:
299
303
  ```shell
300
304
  npm run synth
301
- kubectl apply -f dist/plone-classic.k8s.yaml
305
+ kubectl apply -f dist/plone-blicca.k8s.yaml
302
306
  ```
303
307
 
304
308
  ## Performance
305
309
 
306
- Classic UI performance characteristics:
310
+ Blicca performance characteristics:
307
311
 
308
- - **Server-side rendering** can be slower than Volto's client-side
312
+ - **Server-side rendering** moves rendering work to the backend, so Varnish caching matters
309
313
  - **Varnish caching** is critical for performance
310
314
  - **Database** is the main bottleneck (use CloudNativePG for HA)
311
315
  - **Fewer HTTP requests** than Volto (no separate frontend API calls)
@@ -313,18 +317,18 @@ Classic UI performance characteristics:
313
317
  ## Cleanup
314
318
 
315
319
  ```shell
316
- kubectl delete -f dist/plone-classic.k8s.yaml
320
+ kubectl delete -f dist/plone-blicca.k8s.yaml
317
321
  ```
318
322
 
319
323
  ## Next steps
320
324
 
321
325
  - Follow {doc}`enable-prometheus-monitoring` to add Prometheus monitoring.
322
326
  - Configure [CloudNativePG backups](https://cloudnative-pg.io/documentation/).
323
- - Customize the Classic UI theme through [Plone 6 Classic UI documentation](https://6.docs.plone.org/classic-ui/).
327
+ - Customize the theme through the [Plone 6 Classic UI documentation](https://6.docs.plone.org/classic-ui/) (upstream docs; Blicca is the new name for Classic UI).
324
328
 
325
329
  ## See also
326
330
 
327
- - {doc}`deploy-production-volto` — For the modern React UI.
331
+ - {doc}`deploy-production-volto` — For the React single-page frontend.
328
332
  - {doc}`setup-prerequisites` — Cluster requirements.
329
333
  - {doc}`/reference/configuration-options` — API reference.
330
334
  - [Plone 6 Classic UI documentation](https://6.docs.plone.org/classic-ui/)
@@ -324,6 +324,6 @@ kubectl delete -f dist/plone-example.k8s.yaml
324
324
 
325
325
  ## See also
326
326
 
327
- - {doc}`deploy-classic-ui` — For the traditional Plone interface.
327
+ - {doc}`deploy-blicca` — For the server-side rendered Plone UI.
328
328
  - {doc}`setup-prerequisites` — Detailed cluster setup.
329
329
  - {doc}`/reference/configuration-options` — API reference.
@@ -40,7 +40,7 @@ maxdepth: 1
40
40
  titlesonly: true
41
41
  ---
42
42
  deploy-production-volto
43
- deploy-classic-ui
43
+ deploy-blicca
44
44
  deploy-with-vinyl-cache
45
45
  ```
46
46
 
@@ -15,7 +15,7 @@ Complete API reference for cdk8s-plone constructs, generated from TypeScript sou
15
15
 
16
16
  The cdk8s-plone library provides the following main constructs:
17
17
 
18
- - **Plone**: Main construct for deploying Plone CMS with support for both Volto (React frontend) and Classic UI variants
18
+ - **Plone**: Main construct for deploying Plone CMS with support for both Volto (React frontend) and Blicca (server-side rendered) variants
19
19
  - **PloneHttpcache**: HTTP caching layer using Varnish for improved performance
20
20
 
21
21
  ## Language support
@@ -16,13 +16,13 @@ Complete reference for all configuration options in cdk8s-plone.
16
16
  ### `Plone`
17
17
 
18
18
  Main construct for deploying Plone CMS. Supports two variants:
19
- - **VOLTO**: Modern React frontend with REST API backend (default)
20
- - **CLASSICUI**: Traditional server-side rendered Plone
19
+ - **VOLTO**: React single-page frontend talking to the REST API backend (default)
20
+ - **BLICCA**: the Plone backend renders the UI server-side and serves HTML directly
21
21
 
22
22
  **Properties:**
23
23
  - `backendServiceName` - Name of the backend Kubernetes service
24
24
  - `frontendServiceName` - Name of the frontend service (VOLTO only)
25
- - `variant` - Deployment variant (VOLTO or CLASSICUI)
25
+ - `variant` - Deployment variant (VOLTO or BLICCA)
26
26
  - `siteId` - Plone site ID in ZODB (default: 'Plone')
27
27
 
28
28
  **Example:**
@@ -75,7 +75,7 @@ Main configuration interface for the Plone construct.
75
75
  |----------|------|----------|---------|-------------|
76
76
  | `version` | `string` | No | - | Version of your project |
77
77
  | `siteId` | `string` | No | `'Plone'` | Plone site ID in ZODB |
78
- | `variant` | `PloneVariant` | No | `VOLTO` | Deployment variant (VOLTO or CLASSICUI) |
78
+ | `variant` | `PloneVariant` | No | `VOLTO` | Deployment variant (VOLTO or BLICCA) |
79
79
  | `backend` | `PloneBaseOptions` | Yes | - | Backend configuration |
80
80
  | `frontend` | `PloneBaseOptions` | Conditional | - | Frontend configuration (required for VOLTO) |
81
81
  | `imagePullSecrets` | `string[]` | No | - | Image pull secrets for private registries |
@@ -212,7 +212,7 @@ frontend: {
212
212
  |----------|------|-------------|
213
213
  | `annotations` | `Record<string, string>` | Deployment metadata annotations |
214
214
  | `podAnnotations` | `Record<string, string>` | Pod template annotations (e.g., for Prometheus) |
215
- | `serviceAnnotations` | `Record<string, string>` | Service annotations (e.g., for external-dns) |
215
+ | `serviceAnnotations` | `Record<string, string>` | **Deprecated.** Use `service.annotations` instead. Service annotations (e.g., for external-dns) |
216
216
 
217
217
  **Example:**
218
218
  ```typescript
@@ -228,6 +228,44 @@ backend: {
228
228
  }
229
229
  ```
230
230
 
231
+ #### Service
232
+
233
+ Configure the generated Kubernetes `Service` through the grouped `service` option.
234
+ The `service` option is available on both `backend` and `frontend`.
235
+ Curated fields cover the common cases.
236
+ The `overrides` field is an escape hatch for any other `ServiceSpec` field, and it has the highest precedence.
237
+
238
+ | Property | Type | Description |
239
+ |----------|------|-------------|
240
+ | `service.type` | `string` | Service type: `ClusterIP` (default), `NodePort`, `LoadBalancer`, or `ExternalName` |
241
+ | `service.trafficDistribution` | `string` | Traffic distribution preference, for example `PreferClose` |
242
+ | `service.sessionAffinity` | `string` | Session affinity: `ClientIP` or `None` |
243
+ | `service.externalTrafficPolicy` | `string` | External traffic policy: `Cluster` or `Local` |
244
+ | `service.internalTrafficPolicy` | `string` | Internal traffic policy: `Cluster` or `Local` |
245
+ | `service.publishNotReadyAddresses` | `boolean` | Publish not-ready addresses |
246
+ | `service.loadBalancerClass` | `string` | Load balancer implementation class |
247
+ | `service.loadBalancerSourceRanges` | `string[]` | Allowed source IP ranges for a `LoadBalancer` service |
248
+ | `service.annotations` | `Record<string, string>` | Service metadata annotations (replaces `serviceAnnotations`) |
249
+ | `service.labels` | `Record<string, string>` | Extra Service metadata labels |
250
+ | `service.overrides` | `Record<string, any>` | Raw `ServiceSpec` overrides as a free-form map, with the highest precedence |
251
+
252
+ **Example:**
253
+ ```typescript
254
+ backend: {
255
+ service: {
256
+ type: 'LoadBalancer',
257
+ trafficDistribution: 'PreferClose',
258
+ loadBalancerSourceRanges: ['10.0.0.0/8'],
259
+ annotations: {
260
+ 'external-dns.alpha.kubernetes.io/hostname': 'backend.example.com',
261
+ },
262
+ overrides: {
263
+ ipFamilyPolicy: 'PreferDualStack',
264
+ },
265
+ },
266
+ }
267
+ ```
268
+
231
269
  (monitoring)=
232
270
 
233
271
  #### Prometheus monitoring
@@ -543,18 +581,24 @@ Defines the deployment variant:
543
581
 
544
582
  | Value | Description |
545
583
  |-------|-------------|
546
- | `PloneVariant.VOLTO` | Modern React frontend with REST API backend (default) |
547
- | `PloneVariant.CLASSICUI` | Traditional server-side rendered Plone |
584
+ | `PloneVariant.VOLTO` | React single-page frontend talking to the REST API backend (default) |
585
+ | `PloneVariant.BLICCA` | The Plone backend renders the UI server-side and serves HTML directly |
586
+ | `PloneVariant.CLASSICUI` | Deprecated alias for `PloneVariant.BLICCA`, kept for backward compatibility |
587
+
588
+ `BLICCA` is the new name for the former `CLASSICUI` variant.
589
+ Both select the same backend-only deployment.
590
+ `CLASSICUI` keeps its legacy value (`'classicui'`), so existing configuration using `CLASSICUI` or that literal keeps working unchanged.
591
+ The `CLASSICUI` alias will be removed in a future major release.
548
592
 
549
593
  **Example:**
550
594
  ```typescript
551
595
  import { PloneVariant } from '@bluedynamics/cdk8s-plone';
552
596
 
553
- // Volto (modern)
597
+ // Volto (React single-page frontend)
554
598
  variant: PloneVariant.VOLTO
555
599
 
556
- // Classic UI
557
- variant: PloneVariant.CLASSICUI
600
+ // Blicca (server-side rendered)
601
+ variant: PloneVariant.BLICCA
558
602
  ```
559
603
 
560
604
  ---
@@ -625,7 +669,7 @@ app.synth();
625
669
 
626
670
  - {doc}`/tutorials/01-quick-start` — Get started guide
627
671
  - {doc}`/how-to/deploy-production-volto` — Production-ready Volto deployment
628
- - {doc}`/how-to/deploy-classic-ui` — Classic UI deployment
672
+ - {doc}`/how-to/deploy-blicca` — Blicca deployment
629
673
  - {doc}`/how-to/deploy-with-vinyl-cache` — `PloneVinylCache` walk-through
630
674
  - {doc}`/how-to/enable-prometheus-monitoring` — Wire up `ServiceMonitor`
631
675
  - {doc}`/how-to/configure-security-context` — Harden backend and frontend pods
@@ -147,7 +147,7 @@ Now that you have a basic Plone deployment:
147
147
 
148
148
  - **Configure resources**: See {doc}`/reference/configuration-options` for CPU and memory options.
149
149
  - **Add monitoring**: Follow {doc}`/how-to/enable-prometheus-monitoring`.
150
- - **Explore variants**: Read about Volto and Classic UI in {doc}`/explanation/features`.
150
+ - **Explore variants**: Read about Volto and Blicca in {doc}`/explanation/features`.
151
151
  - **Harden pods**: Apply {doc}`/how-to/configure-security-context`.
152
152
 
153
153
  ## Troubleshooting