@intlayer/docs 9.0.0-canary.10 → 9.0.0-canary.11

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 (63) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +20 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +20 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/intlayer_CMS.md +16 -1
  8. package/docs/ar/releases/v9.md +58 -1
  9. package/docs/ar/self_hosting.md +349 -0
  10. package/docs/bn/intlayer_CMS.md +570 -0
  11. package/docs/bn/releases/v9.md +358 -0
  12. package/docs/cs/releases/v9.md +358 -0
  13. package/docs/de/intlayer_CMS.md +117 -1
  14. package/docs/de/releases/v9.md +61 -1
  15. package/docs/de/self_hosting.md +349 -0
  16. package/docs/en/intlayer_CMS.md +171 -1
  17. package/docs/en/releases/v9.md +45 -2
  18. package/docs/en/self_hosting.md +349 -0
  19. package/docs/en-GB/intlayer_CMS.md +16 -1
  20. package/docs/en-GB/releases/v9.md +47 -2
  21. package/docs/en-GB/self_hosting.md +349 -0
  22. package/docs/es/intlayer_CMS.md +117 -1
  23. package/docs/es/releases/v9.md +61 -1
  24. package/docs/es/self_hosting.md +349 -0
  25. package/docs/fr/intlayer_CMS.md +117 -1
  26. package/docs/fr/releases/v9.md +61 -1
  27. package/docs/fr/self_hosting.md +349 -0
  28. package/docs/hi/intlayer_CMS.md +16 -1
  29. package/docs/hi/releases/v9.md +59 -1
  30. package/docs/hi/self_hosting.md +349 -0
  31. package/docs/id/releases/v9.md +31 -1
  32. package/docs/id/self_hosting.md +349 -0
  33. package/docs/it/intlayer_CMS.md +117 -1
  34. package/docs/it/releases/v9.md +61 -1
  35. package/docs/it/self_hosting.md +349 -0
  36. package/docs/ja/intlayer_CMS.md +191 -10
  37. package/docs/ja/releases/v9.md +31 -1
  38. package/docs/ja/self_hosting.md +349 -0
  39. package/docs/ko/intlayer_CMS.md +189 -6
  40. package/docs/ko/releases/v9.md +30 -1
  41. package/docs/ko/self_hosting.md +349 -0
  42. package/docs/nl/releases/v9.md +358 -0
  43. package/docs/pl/intlayer_CMS.md +16 -1
  44. package/docs/pl/releases/v9.md +58 -1
  45. package/docs/pl/self_hosting.md +349 -0
  46. package/docs/pt/intlayer_CMS.md +117 -1
  47. package/docs/pt/releases/v9.md +61 -1
  48. package/docs/pt/self_hosting.md +349 -0
  49. package/docs/ru/intlayer_CMS.md +196 -15
  50. package/docs/ru/releases/v9.md +59 -1
  51. package/docs/ru/self_hosting.md +349 -0
  52. package/docs/tr/intlayer_CMS.md +16 -1
  53. package/docs/tr/releases/v9.md +46 -1
  54. package/docs/tr/self_hosting.md +349 -0
  55. package/docs/uk/intlayer_CMS.md +16 -1
  56. package/docs/uk/releases/v9.md +58 -1
  57. package/docs/uk/self_hosting.md +349 -0
  58. package/docs/vi/releases/v9.md +31 -1
  59. package/docs/vi/self_hosting.md +349 -0
  60. package/docs/zh/releases/v9.md +31 -1
  61. package/docs/zh/self_hosting.md +349 -0
  62. package/package.json +6 -6
  63. package/src/generated/docs.entry.ts +20 -0
@@ -0,0 +1,349 @@
1
+ ---
2
+ createdAt: 2026-06-30
3
+ updatedAt: 2026-06-30
4
+ title: "Intlayer selbst hosten"
5
+ description: "Betreiben Sie eine komplette Intlayer-Instanz auf Ihrer eigenen Infrastruktur mit einem einzigen Befehl. Kein Intlayer Cloud-Konto erforderlich."
6
+ keywords:
7
+ - Selbst-Hosting
8
+ - Docker
9
+ - Docker Compose
10
+ - Intlayer
11
+ - CMS
12
+ - Installation
13
+ - Infrastruktur
14
+ slugs:
15
+ - doc
16
+ - self-hosting
17
+ author: aymericzip
18
+ ---
19
+
20
+ # Intlayer selbst hosten
21
+
22
+ Intlayer kann vollständig auf Ihrer eigenen Infrastruktur ausgeführt werden – kein Intlayer Cloud-Konto erforderlich. Ein einziger Befehl startet einen produktionsbereiten Stack:
23
+
24
+ ```sh
25
+ curl -fsSL https://intlayer.org/install.sh | sh
26
+ ```
27
+
28
+ Der Installer lädt eine `docker-compose.yml` und eine `.env` herunter, generiert automatisch die erforderlichen Secrets und startet alle Container mit `docker compose up -d`.
29
+
30
+ ## Inhaltsverzeichnis
31
+
32
+ <TOC/>
33
+
34
+ ---
35
+
36
+ ## Architektur
37
+
38
+ ```
39
+ ┌─────────────────────────────┐
40
+ browser ──────▶ │ app (TanStack Start) :3000│ ──┐
41
+ └─────────────────────────────┘ │ VITE_BACKEND_URL
42
+ ┌─────────────────────────────┐ │
43
+ │ backend (Fastify/Bun) :3100│ ◀─┘
44
+ └──────────────┬──────────────┘
45
+ ┌──────────┬─────────┼──────────┬───────────┐
46
+ ▼ ▼ ▼ ▼ ▼
47
+ mongo:27017 redis:6379 minio:9000 mailpit:1025 Chromium
48
+ (1-node RS) (S3 API) (SMTP) (in-image)
49
+ minio:9001 mailpit:8025
50
+ (console) (web UI)
51
+ ```
52
+
53
+ Chromium (wird für die Erzeugung von Puppeteer-Screenshots verwendet) ist im Backend-Image gebündelt – es wird kein separater Container benötigt.
54
+
55
+ ---
56
+
57
+ ## Voraussetzungen
58
+
59
+ - **Docker** ≥ 24 und **Docker Compose** ≥ v2. Fehlt eines davon, gibt der Installer den Installationslink aus und beendet sich.
60
+ - Ports `3000`, `3100`, `8025`, `9000` und `9001` auf dem Host verfügbar.
61
+ - Ein Linux- oder macOS-Host (oder WSL2 unter Windows).
62
+
63
+ ---
64
+
65
+ ## Schnellstart
66
+
67
+ ```sh
68
+ curl -fsSL https://intlayer.org/install.sh | sh
69
+ ```
70
+
71
+ Was der Installer tut:
72
+
73
+ 1. Überprüft, ob `docker` und `docker compose` vorhanden sind.
74
+ 2. Lädt `docker-compose.yml` und `.env.example` in `./intlayer/` herunter.
75
+ 3. Falls keine `.env` existiert, kopiert er das Beispiel und generiert zufällige Secrets für `BETTER_AUTH_SECRET`, `S3_ACCESS_KEY_ID` und `S3_SECRET_ACCESS_KEY` mittels `openssl rand`.
76
+ 4. Führt `docker compose pull` + `docker compose up -d` aus.
77
+ 5. Gibt die URLs aus: Dashboard `:3000`, API `:3100`, E-Mail-UI `:8025`, MinIO-Konsole `:9001`.
78
+
79
+ Nachdem der Stack gestartet ist, öffnen Sie **http://localhost:3000** und erstellen Sie Ihr erstes Konto.
80
+
81
+ ---
82
+
83
+ ## Dienste
84
+
85
+ | Service | Image | Host port(s) | Zweck |
86
+ | :---------- | :----------------------------------- | :--------------------------------------------- | :-------------------------------------------------------- |
87
+ | **app** | built from `apps/app/Dockerfile` | `3000` | TanStack Start Dashboard (CMS-Benutzeroberfläche) |
88
+ | **backend** | built from `apps/backend/Dockerfile` | `3100` | Fastify REST API (`/health` Endpunkt) |
89
+ | **mongo** | `mongo:7` | intern | Einzelknoten-Replica Set (`rs0`) |
90
+ | **redis** | `redis:7-alpine` | intern | Job-Warteschlangen (BullMQ) und Caching (ioredis) |
91
+ | **minio** | `minio/minio` | `9000` (S3), `9001` (Konsole) | S3-kompatibler Objektspeicher für Avatare und Screenshots |
92
+ | **mailpit** | `axllent/mailpit` | `1025` (SMTP), `8025` (Web-Benutzeroberfläche) | Lokale Transaktions-E-Mail-Senke |
93
+
94
+ Interne Ports (mongo, redis) werden standardmäßig nicht zum Host exponiert.
95
+
96
+ > MinIO-Port `9000` muss vom Browser erreichbar sein, da hochgeladene Assets (Avatare, Screenshots) direkt von `S3_PUBLIC_URL=http://localhost:9000/intlayer` geladen werden.
97
+
98
+ ---
99
+
100
+ ## Umgebungsvariablen
101
+
102
+ Der Installer generiert eine gebrauchsfertige `.env`. Die folgende Tabelle beschreibt jede Variable.
103
+
104
+ ### Erforderlich (automatisch generiert oder abgefragt)
105
+
106
+ | Variable | Beispiel | Beschreibung |
107
+ | :--------------------- | :---------------------------------------------- | :--------------------------------------------------------------- |
108
+ | `NODE_ENV` | `production` | Laufzeitumgebung |
109
+ | `PORT` | `3100` | Backend-Listenport |
110
+ | `BACKEND_URL` | `http://localhost:3100` | Öffentliche URL der Backend-API |
111
+ | `APP_URL` | `http://localhost:3000` | Öffentliche URL des Dashboards |
112
+ | `DOMAIN` | `localhost` | Cookie-Domain |
113
+ | `MONGODB_URI` | `mongodb://mongo:27017/intlayer?replicaSet=rs0` | Vollständige MongoDB-Verbindungs-URI |
114
+ | `REDIS_URL` | `redis://redis:6379` | Redis-Verbindungs-URL |
115
+ | `BETTER_AUTH_SECRET` | _(generiert)_ | 32-Byte-Secret für die Session-Signierung |
116
+ | `MAIL_PROVIDER` | `smtp` | Mail-Transport: `smtp` oder `resend` |
117
+ | `MAIL_SMTP_HOST` | `mailpit` | SMTP-Hostname (Mailpit Container-Name) |
118
+ | `MAIL_SMTP_PORT` | `1025` | SMTP-Port |
119
+ | `MAIL_FROM` | `Intlayer <no-reply@localhost>` | Absenderadresse |
120
+ | `S3_ENDPOINT` | `http://minio:9000` | S3-kompatibler Endpunkt |
121
+ | `S3_PUBLIC_URL` | `http://localhost:9000/intlayer` | Öffentliche URL für das Laden von Browser-Assets |
122
+ | `S3_BUCKET_NAME` | `intlayer` | Bucket-Name |
123
+ | `S3_ACCESS_KEY_ID` | _(generiert)_ | MinIO-Zugangsschlüssel |
124
+ | `S3_SECRET_ACCESS_KEY` | _(generiert)_ | MinIO-Geheimschlüssel |
125
+ | `VITE_BACKEND_URL` | `http://localhost:3100` | Backend-URL, die zur Build-Zeit in das Dashboard integriert wird |
126
+ | `VITE_DOMAIN` | `localhost` | Domain, die zur Build-Zeit in das Dashboard integriert wird |
127
+
128
+ ### Optional (Funktionen funktionieren bei Abwesenheit eingeschränkt)
129
+
130
+ | Variable | Funktion |
131
+ | :------------------------------------------------------- | :------------------------------------------------------------------- |
132
+ | `OPENAI_API_KEY` | KI-gestützte Übersetzung und Inhaltsprüfung |
133
+ | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_*` | Abrechnung und Abonnementverwaltung |
134
+ | `RESEND_API_KEY` | Transaktions-E-Mail über Resend (überschreibt Mailpit, wenn gesetzt) |
135
+ | `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` | GitHub OAuth-Login |
136
+ | `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | Google OAuth-Login |
137
+ | `GITLAB_CLIENT_ID`, `GITLAB_CLIENT_SECRET` | GitLab OAuth-Login |
138
+ | `MICROSOFT_CLIENT_ID`, `MICROSOFT_CLIENT_SECRET` | Microsoft OAuth-Login |
139
+ | `LINKEDIN_CLIENT_ID`, `LINKEDIN_CLIENT_SECRET` | LinkedIn OAuth-Login |
140
+ | `ATLASSIAN_CLIENT_ID`, `ATLASSIAN_CLIENT_SECRET` | Atlassian OAuth-Login |
141
+
142
+ ---
143
+
144
+ ## Ihr Intlayer-Projekt verbinden
145
+
146
+ Sobald der Stack läuft, verweisen Sie Ihr Projekt auf das selbst gehostete Backend und Dashboard anstelle von `intlayer.org`.
147
+
148
+ ### Projektkonfiguration
149
+
150
+ ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
151
+ import type { IntlayerConfig } from "intlayer";
152
+
153
+ const config: IntlayerConfig = {
154
+ editor: {
155
+ clientId: process.env.INTLAYER_CLIENT_ID,
156
+ clientSecret: process.env.INTLAYER_CLIENT_SECRET,
157
+
158
+ /**
159
+ * URL des selbst gehosteten CMS-Dashboards.
160
+ * Standard: https://app.intlayer.org
161
+ */
162
+ cmsURL: process.env.INTLAYER_CMS_URL, // e.g. http://localhost:3000
163
+
164
+ /**
165
+ * URL der selbst gehosteten Backend-API.
166
+ * Standard: https://back.intlayer.org
167
+ */
168
+ backendURL: process.env.INTLAYER_BACKEND_URL, // e.g. http://localhost:3100
169
+ },
170
+ };
171
+
172
+ export default config;
173
+ ```
174
+
175
+ Setzen Sie die Umgebungsvariablen in der `.env` Ihres Projekts:
176
+
177
+ ```sh
178
+ INTLAYER_CMS_URL=http://localhost:3000
179
+ INTLAYER_BACKEND_URL=http://localhost:3100
180
+ INTLAYER_CLIENT_ID=<your-client-id>
181
+ INTLAYER_CLIENT_SECRET=<your-client-secret>
182
+ ```
183
+
184
+ Erstellen Sie Zugangsdaten in Ihrem selbst gehosteten Dashboard unter **Projects → Access keys** unter `http://localhost:3000/projects`.
185
+
186
+ ### `@intlayer/api` SDK
187
+
188
+ Wenn Sie das `@intlayer/api` SDK programmatisch verwenden, übergeben Sie `backendURL` explizit:
189
+
190
+ ```typescript fileName="cms.ts" codeFormat="typescript"
191
+ import { createIntlayerCMS } from "@intlayer/api";
192
+ import { dictionaryEndpoint } from "@intlayer/api/dictionary";
193
+
194
+ const cms = createIntlayerCMS({
195
+ editor: {
196
+ clientId: process.env.INTLAYER_CLIENT_ID,
197
+ clientSecret: process.env.INTLAYER_CLIENT_SECRET,
198
+ backendURL: process.env.INTLAYER_BACKEND_URL, // http://localhost:3100
199
+ },
200
+ });
201
+
202
+ const { data: dictionaries } = await dictionaryEndpoint(cms).getDictionaries();
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Upgrade
208
+
209
+ Ein erneutes Ausführen des Installers auf einer bestehenden Bereitstellung führt ein Rolling-Upgrade durch:
210
+
211
+ ```sh
212
+ curl -fsSL https://intlayer.org/install.sh | sh
213
+ ```
214
+
215
+ Dies zieht die neuesten Images und startet Container neu mit `docker compose pull && docker compose up -d`. Bestehende Volumes (`mongo-data`, `redis-data`, `minio-data`) bleiben erhalten – kein Datenverlust.
216
+
217
+ Um manuell aus dem `./intlayer/`-Verzeichnis ein Upgrade durchzuführen:
218
+
219
+ ```sh
220
+ docker compose pull
221
+ docker compose up -d
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Backup und Wiederherstellung
227
+
228
+ Alle persistenten Daten befinden sich in drei benannten Docker-Volumes.
229
+
230
+ ### Backup
231
+
232
+ ```sh
233
+ docker run --rm \
234
+ -v intlayer_mongo-data:/data \
235
+ -v "$(pwd)":/backup \
236
+ busybox tar czf /backup/mongo-data.tar.gz /data
237
+
238
+ docker run --rm \
239
+ -v intlayer_redis-data:/data \
240
+ -v "$(pwd)":/backup \
241
+ busybox tar czf /backup/redis-data.tar.gz /data
242
+
243
+ docker run --rm \
244
+ -v intlayer_minio-data:/data \
245
+ -v "$(pwd)":/backup \
246
+ busybox tar czf /backup/minio-data.tar.gz /data
247
+ ```
248
+
249
+ ### Wiederherstellung
250
+
251
+ ```sh
252
+ docker run --rm \
253
+ -v intlayer_mongo-data:/data \
254
+ -v "$(pwd)":/backup \
255
+ busybox tar xzf /backup/mongo-data.tar.gz -C /
256
+
257
+ # Wiederholen Sie dies für redis-data und minio-data
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Verwendung eines Reverse-Proxys (Nginx / Caddy)
263
+
264
+ Für Produktionsbereitstellungen platzieren Sie einen Reverse-Proxy vor den App- und Backend-Containern, anstatt sie direkt zu exponieren.
265
+
266
+ ### Nginx-Beispiel
267
+
268
+ ```nginx
269
+ server {
270
+ listen 80;
271
+ server_name cms.example.com;
272
+
273
+ location / {
274
+ proxy_pass http://localhost:3000;
275
+ proxy_set_header Host $host;
276
+ proxy_set_header X-Real-IP $remote_addr;
277
+ }
278
+ }
279
+
280
+ server {
281
+ listen 80;
282
+ server_name api.example.com;
283
+
284
+ location / {
285
+ proxy_pass http://localhost:3100;
286
+ proxy_set_header Host $host;
287
+ proxy_set_header X-Real-IP $remote_addr;
288
+ }
289
+ }
290
+ ```
291
+
292
+ Aktualisieren Sie die folgenden `.env`-Variablen, um sie an Ihre öffentlichen Domains anzupassen:
293
+
294
+ ```sh
295
+ BACKEND_URL=https://api.example.com
296
+ APP_URL=https://cms.example.com
297
+ DOMAIN=example.com
298
+ VITE_BACKEND_URL=https://api.example.com
299
+ VITE_DOMAIN=example.com
300
+ ```
301
+
302
+ > `VITE_*`-Variablen werden zur Build-Zeit in das Dashboard-Image integriert. Wenn Sie diese nach dem Bau des Images ändern, müssen Sie das `app`-Image neu erstellen (`docker compose build app`) oder die Laufzeitkonfigurationsinjektion verwenden.
303
+
304
+ ---
305
+
306
+ ## Fehlerbehebung
307
+
308
+ ### Backend-Absturzschleifen beim ersten Start
309
+
310
+ MongoDB und Redis müssen fehlerfrei sein, bevor das Backend startet. Die Compose-Datei verwendet `depends_on` mit `condition: service_healthy`. Wenn Sie wiederholte Backend-Neustarts sehen, überprüfen Sie, ob die `mongo`- und `redis`-Healthchecks erfolgreich sind:
311
+
312
+ ```sh
313
+ docker compose ps
314
+ docker compose logs mongo
315
+ docker compose logs redis
316
+ ```
317
+
318
+ ### Dashboard kann die API nicht erreichen
319
+
320
+ Stellen Sie sicher, dass `VITE_BACKEND_URL` der URL entspricht, unter der das Backend vom **Browser** (nicht vom Docker-Netzwerk) aus erreichbar ist. Wenn Sie den Backend-Port geändert oder einen Reverse-Proxy hinzugefügt haben, erstellen Sie das Dashboard-Image neu:
321
+
322
+ ```sh
323
+ docker compose build app
324
+ docker compose up -d app
325
+ ```
326
+
327
+ ### E-Mail wird nicht gesendet
328
+
329
+ Standardmäßig werden alle ausgehenden E-Mails von Mailpit abgefangen. Öffnen Sie `http://localhost:8025`, um gesendete Nachrichten anzuzeigen. Um echte E-Mails zu senden, setzen Sie `MAIL_PROVIDER=resend` und `RESEND_API_KEY=<Ihr-Schlüssel>` in `.env` und starten Sie dann das Backend neu:
330
+
331
+ ```sh
332
+ docker compose restart backend
333
+ ```
334
+
335
+ ### MinIO-Bucket fehlt
336
+
337
+ Wenn der `minio-init`-One-Shot-Service nicht ausgeführt wurde (oder vor der Bereitschaft von MinIO lief), erstellen Sie den Bucket manuell:
338
+
339
+ ```sh
340
+ docker compose run --rm minio-init
341
+ ```
342
+
343
+ ---
344
+
345
+ ## Nützliche Links
346
+
347
+ - [Intlayer CMS-Dokumentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_CMS.md)
348
+ - [Konfigurationsreferenz](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/configuration.md)
349
+ - [CMS SDK — `@intlayer/api`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_CMS.md#programmatic-access-with-the-intlayerapi-sdk)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-08-23
3
- updatedAt: 2025-08-23
3
+ updatedAt: 2026-06-29
4
4
  title: Intlayer CMS | Externalize your content into the Intlayer CMS
5
5
  description: Externalize your content into the Intlayer CMS to delegate the management of your content to your team.
6
6
  keywords:
@@ -18,6 +18,12 @@ slugs:
18
18
  - cms
19
19
  youtubeVideo: https://www.youtube.com/watch?v=UDDTnirwi_4
20
20
  history:
21
+ - version: 9.0.0
22
+ date: 2026-06-30
23
+ changes: "Add Self-Hosting section: Docker Compose bootstrap, service inventory, SDK configuration, optional features, and upgrade notes"
24
+ - version: 9.0.0
25
+ date: 2026-06-29
26
+ changes: "Add @intlayer/api SDK (createIntlayerCMS) section for programmatic CMS access"
21
27
  - version: 6.0.1
22
28
  date: 2025-09-22
23
29
  changes: "Add live sync documentation"
@@ -241,6 +247,158 @@ This command uploads your initial content dictionaries, making them available fo
241
247
 
242
248
  Then you will be able to see and manage your dictionary in the [Intlayer CMS](https://app.intlayer.org/content).
243
249
 
250
+ ## Programmatic access with the `@intlayer/api` SDK
251
+
252
+ Beyond the CLI and the visual editor, Intlayer ships a typed SDK in the [`@intlayer/api`](https://www.npmjs.com/package/@intlayer/api) package. It lets you treat the CMS as a **headless content database**: you can fetch projects, fetch dictionaries, and push or update them directly from your own application, scripts, or CI pipeline.
253
+
254
+ The SDK handles authentication for you. As long as your `clientId` and `clientSecret` are available (in your Intlayer configuration or environment), it obtains and refreshes an OAuth2 access token automatically and signs every request.
255
+
256
+ ### Installation
257
+
258
+ ```bash packageManager="npm"
259
+ npm install @intlayer/api
260
+ ```
261
+
262
+ ```bash packageManager="yarn"
263
+ yarn add @intlayer/api
264
+ ```
265
+
266
+ ```bash packageManager="pnpm"
267
+ pnpm add @intlayer/api
268
+ ```
269
+
270
+ ```bash packageManager="bun"
271
+ bun add @intlayer/api
272
+ ```
273
+
274
+ ### How it works: authenticator + endpoints
275
+
276
+ The SDK is split into **two separate imports** on purpose, to keep your bundle small:
277
+
278
+ 1. `createIntlayerCMS` — creates a lightweight **authenticator**. It only carries the credentials and the managed access token; it knows nothing about any specific domain.
279
+ 2. `dictionaryEndpoint`, `projectEndpoint`, … — per-domain **endpoint binders**, each imported from its own subpath (`@intlayer/api/dictionary`, `@intlayer/api/project`, …). You pass the authenticator to the endpoint you need.
280
+
281
+ Because each endpoint is imported separately, your bundle includes only the domains you actually use — importing `dictionaryEndpoint` never pulls in the project, AI, or any other domain client.
282
+
283
+ ```typescript fileName="cms.ts" codeFormat="typescript"
284
+ import { createIntlayerCMS } from "@intlayer/api";
285
+
286
+ // The configuration is optional: when omitted, the credentials are read from
287
+ // `@intlayer/config/built`, which resolves the INTLAYER_CLIENT_ID and
288
+ // INTLAYER_CLIENT_SECRET environment variables.
289
+ export const cmsAuthenticator = createIntlayerCMS();
290
+ ```
291
+
292
+ > [!WARNING]
293
+ > The CMS credentials (`clientId` / `clientSecret`) grant **write access** to your content. Only ever create the authenticator on the **server side** (server actions, route handlers, scripts, CI). Never import it into client-side code or expose your credentials to the browser.
294
+
295
+ If you prefer not to rely on the build-time configuration, pass the credentials explicitly:
296
+
297
+ ```typescript fileName="cms.ts" codeFormat="typescript"
298
+ import { createIntlayerCMS } from "@intlayer/api";
299
+
300
+ export const cmsAuthenticator = createIntlayerCMS({
301
+ editor: {
302
+ clientId: process.env.INTLAYER_CLIENT_ID,
303
+ clientSecret: process.env.INTLAYER_CLIENT_SECRET,
304
+ // Optional, for self-hosted backends:
305
+ // backendURL: process.env.INTLAYER_BACKEND_URL,
306
+ },
307
+ });
308
+ ```
309
+
310
+ > Get your credentials by creating a new access key in the [Intlayer Dashboard - Projects](https://app.intlayer.org/projects).
311
+
312
+ ### Fetch projects
313
+
314
+ ```typescript fileName="projects.ts" codeFormat="typescript"
315
+ import { createIntlayerCMS } from "@intlayer/api";
316
+ import { projectEndpoint } from "@intlayer/api/project";
317
+
318
+ const cmsAuthenticator = createIntlayerCMS();
319
+
320
+ // List the projects accessible with your credentials
321
+ const { data: projects } =
322
+ await projectEndpoint(cmsAuthenticator).getProjects();
323
+
324
+ // Read aggregated localization insights of the selected project
325
+ const { data: insights } =
326
+ await projectEndpoint(cmsAuthenticator).getProjectInsights();
327
+ ```
328
+
329
+ ### Fetch dictionaries
330
+
331
+ ```typescript fileName="read-dictionaries.ts" codeFormat="typescript"
332
+ import { createIntlayerCMS } from "@intlayer/api";
333
+ import { dictionaryEndpoint } from "@intlayer/api/dictionary";
334
+
335
+ const cmsAuthenticator = createIntlayerCMS();
336
+
337
+ // List every remote dictionary of the project
338
+ const { data: dictionaries } =
339
+ await dictionaryEndpoint(cmsAuthenticator).getDictionaries();
340
+
341
+ // Or get a single dictionary by key
342
+ const { data: dictionary } = await dictionaryEndpoint(
343
+ cmsAuthenticator
344
+ ).getDictionary("my-first-dictionary-key");
345
+ ```
346
+
347
+ ### Push and update dictionaries
348
+
349
+ Use the CMS as a database to write content back:
350
+
351
+ ```typescript fileName="write-dictionaries.ts" codeFormat="typescript"
352
+ import { createIntlayerCMS } from "@intlayer/api";
353
+ import { dictionaryEndpoint } from "@intlayer/api/dictionary";
354
+
355
+ const cmsAuthenticator = createIntlayerCMS();
356
+
357
+ // Create a new dictionary
358
+ await dictionaryEndpoint(cmsAuthenticator).addDictionary({
359
+ key: "my-first-dictionary-key",
360
+ content: { title: "Hello world" },
361
+ });
362
+
363
+ // Upsert a batch of dictionaries (create or update them in one call)
364
+ await dictionaryEndpoint(cmsAuthenticator).pushDictionaries([
365
+ { key: "home", content: { title: "Home" } },
366
+ { key: "about", content: { title: "About" } },
367
+ ]);
368
+
369
+ // Update an existing dictionary
370
+ await dictionaryEndpoint(cmsAuthenticator).updateDictionary({
371
+ id: "<dictionary-id>",
372
+ key: "home",
373
+ content: { title: "Updated title" },
374
+ });
375
+ ```
376
+
377
+ > Tip: reuse the bound endpoint to avoid repeating yourself:
378
+ >
379
+ > ```typescript codeFormat="typescript"
380
+ > const dictionary = dictionaryEndpoint(cmsAuthenticator);
381
+ > await dictionary.pushDictionaries([myDictionary]);
382
+ > const { data } = await dictionary.getDictionaries();
383
+ > ```
384
+
385
+ ### Extracting a single method
386
+
387
+ Every endpoint method is already authenticated and standalone (it carries its own token handling), so you can extract one and pass it around — for example to inject it as a dependency:
388
+
389
+ ```typescript fileName="push.ts" codeFormat="typescript"
390
+ import { createIntlayerCMS } from "@intlayer/api";
391
+ import { dictionaryEndpoint } from "@intlayer/api/dictionary";
392
+
393
+ const dictionary = dictionaryEndpoint(createIntlayerCMS());
394
+
395
+ // Already authenticated — refreshes the token automatically on each call
396
+ export const pushDictionaries = dictionary.pushDictionaries;
397
+
398
+ // Usage
399
+ await pushDictionaries([{ key: "home", content: { title: "Home" } }]);
400
+ ```
401
+
244
402
  ## Live sync
245
403
 
246
404
  Live Sync lets your app reflect CMS content changes at runtime. No rebuild or redeploy required. When enabled, updates are streamed to a Live Sync server that refreshes the dictionaries your application reads.
@@ -384,6 +542,18 @@ Notes and constraints:
384
542
  - The `live` flag is evaluated for each dictionary at build time. If remote content wasn't flagged `live=true` during build, you must rebuild to enable Live Sync for that dictionary.
385
543
  - The live sync server must be able to write to `.intlayer`. In containers, ensure write access to `/.intlayer`.
386
544
 
545
+ ## Self-Hosting
546
+
547
+ Intlayer can run entirely on your own infrastructure. A one-liner bootstraps the full stack (dashboard, API, database, object storage, and email) with Docker Compose:
548
+
549
+ ```sh
550
+ curl -fsSL https://intlayer.org/install.sh | sh
551
+ ```
552
+
553
+ For the complete setup guide, environment variable reference, upgrade instructions, and backup/restore procedures, see the [Self-Hosting Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/self_hosting.md).
554
+
555
+ ---
556
+
387
557
  ## Debug
388
558
 
389
559
  If you encounter any issues with the CMS, check the following:
@@ -1,14 +1,17 @@
1
1
  ---
2
2
  createdAt: 2026-06-14
3
- updatedAt: 2026-06-26
3
+ updatedAt: 2026-06-29
4
4
  title: New Intlayer v9 - What's new?
5
- description: Discover what's new in Intlayer v9. Introducing drop-in compatibility packages for popular i18n libraries and support for Collections and Variants.
5
+ description: Discover what's new in Intlayer v9. Introducing drop-in compatibility packages for popular i18n libraries, support for Collections and Variants, and self-hosting via Docker Compose.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - Compatibility
9
9
  - Migration
10
10
  - Collections
11
11
  - Variants
12
+ - CMS SDK
13
+ - Self-Hosting
14
+ - Docker
12
15
  - i18next
13
16
  - next-intl
14
17
  - vue-i18n
@@ -295,6 +298,44 @@ npm install intlayer react-native-intlayer
295
298
 
296
299
  ---
297
300
 
301
+ ## CMS SDK: use Intlayer as a headless content database
302
+
303
+ Intlayer v9 ships a clean, auto-authenticating SDK in `@intlayer/api` to interact with the CMS programmatically — fetch projects, fetch dictionaries, and push or update them from your own server, scripts, or CI. Authentication (OAuth2 `client_credentials`) is handled and refreshed for you.
304
+
305
+ The SDK is split into **two separate imports** so your bundle includes only the domains you actually use:
306
+
307
+ 1. `createIntlayerCMS` — a lightweight **authenticator** holding the credentials and the managed token (no domain client bundled).
308
+ 2. `dictionaryEndpoint`, `projectEndpoint`, … — per-domain **endpoint binders**, each imported from its own subpath.
309
+
310
+ ```ts fileName="cms.ts"
311
+ import { createIntlayerCMS } from "@intlayer/api";
312
+ import { dictionaryEndpoint } from "@intlayer/api/dictionary";
313
+
314
+ const cms = createIntlayerCMS();
315
+
316
+ // Read
317
+ const { data: dictionaries } = await dictionaryEndpoint(cms).getDictionaries();
318
+
319
+ // Write — use the CMS like a database
320
+ await dictionaryEndpoint(cms).pushDictionaries([myDictionary]);
321
+ ```
322
+
323
+ > Security: the CMS credentials grant write access to your content. Only ever create the authenticator on the **server side** — never ship `clientId` / `clientSecret` to the browser.
324
+
325
+ ---
326
+
327
+ ## Self-Hosting
328
+
329
+ Intlayer v9 ships first-class support for running your own Intlayer instance with a single command — no Intlayer Cloud account required.
330
+
331
+ ```sh
332
+ curl -fsSL https://intlayer.org/install.sh | sh
333
+ ```
334
+
335
+ The installer downloads a `docker-compose.yml` and a `.env`, auto-generates the required secrets, and runs `docker compose up -d`. Everything — the dashboard, the API, the database, object storage, and transactional email — runs locally in containers.
336
+
337
+ ---
338
+
298
339
  ## Migration notes from v8
299
340
 
300
341
  If you are upgrading from v8, note that the v9 does not include breaking changes. But here are the key changes:
@@ -313,3 +354,5 @@ If you are upgrading from v8, note that the v9 does not include breaking changes
313
354
  - [Dynamic Dictionaries - Collections & Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/index.md)
314
355
  - [Configuration Reference](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md)
315
356
  - [React Native & Expo Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_react_native+expo.md)
357
+ - [CMS SDK - Programmatic access with @intlayer/api](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
358
+ - [Self-Hosting Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/self_hosting.md)