@intlayer/docs 9.0.0-canary.15 → 9.0.0-canary.16

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 (107) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +40 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +40 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +2 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/cli/index.md +1 -1
  8. package/docs/ar/configuration.md +42 -1
  9. package/docs/ar/intlayer_CMS.md +5 -128
  10. package/docs/ar/live-sync.md +174 -0
  11. package/docs/ar/releases/v9.md +45 -1
  12. package/docs/bn/cli/index.md +1 -1
  13. package/docs/bn/configuration.md +45 -1
  14. package/docs/cs/cli/index.md +1 -1
  15. package/docs/cs/configuration.md +45 -1
  16. package/docs/de/cli/index.md +1 -1
  17. package/docs/de/configuration.md +42 -1
  18. package/docs/de/intlayer_CMS.md +5 -135
  19. package/docs/de/live-sync.md +174 -0
  20. package/docs/de/releases/v9.md +45 -1
  21. package/docs/en/analytics.md +222 -0
  22. package/docs/en/cli/index.md +1 -1
  23. package/docs/en/configuration.md +42 -1
  24. package/docs/en/intlayer_CMS.md +6 -140
  25. package/docs/en/live-sync.md +184 -0
  26. package/docs/en/releases/v9.md +53 -3
  27. package/docs/en-GB/cli/index.md +1 -1
  28. package/docs/en-GB/configuration.md +42 -1
  29. package/docs/en-GB/intlayer_CMS.md +5 -128
  30. package/docs/en-GB/live-sync.md +173 -0
  31. package/docs/en-GB/releases/v9.md +45 -1
  32. package/docs/es/cli/index.md +1 -1
  33. package/docs/es/configuration.md +42 -1
  34. package/docs/es/intlayer_CMS.md +5 -140
  35. package/docs/es/live-sync.md +176 -0
  36. package/docs/es/releases/v9.md +45 -1
  37. package/docs/fr/cli/index.md +1 -1
  38. package/docs/fr/configuration.md +42 -1
  39. package/docs/fr/intlayer_CMS.md +5 -135
  40. package/docs/fr/live-sync.md +174 -0
  41. package/docs/fr/releases/v9.md +45 -1
  42. package/docs/hi/cli/index.md +1 -1
  43. package/docs/hi/configuration.md +42 -1
  44. package/docs/hi/intlayer_CMS.md +5 -128
  45. package/docs/hi/live-sync.md +174 -0
  46. package/docs/hi/releases/v9.md +45 -1
  47. package/docs/id/cli/index.md +1 -1
  48. package/docs/id/configuration.md +42 -1
  49. package/docs/id/intlayer_CMS.md +5 -139
  50. package/docs/id/live-sync.md +185 -0
  51. package/docs/id/releases/v9.md +45 -1
  52. package/docs/it/cli/index.md +1 -1
  53. package/docs/it/configuration.md +42 -1
  54. package/docs/it/intlayer_CMS.md +5 -128
  55. package/docs/it/live-sync.md +174 -0
  56. package/docs/it/releases/v9.md +45 -1
  57. package/docs/ja/cli/index.md +1 -1
  58. package/docs/ja/configuration.md +42 -1
  59. package/docs/ja/intlayer_CMS.md +5 -139
  60. package/docs/ja/live-sync.md +185 -0
  61. package/docs/ja/releases/v9.md +45 -1
  62. package/docs/ko/cli/index.md +1 -1
  63. package/docs/ko/configuration.md +42 -1
  64. package/docs/ko/intlayer_CMS.md +5 -141
  65. package/docs/ko/live-sync.md +187 -0
  66. package/docs/ko/releases/v9.md +45 -1
  67. package/docs/nl/cli/index.md +1 -1
  68. package/docs/nl/configuration.md +45 -1
  69. package/docs/pl/cli/index.md +1 -1
  70. package/docs/pl/configuration.md +45 -1
  71. package/docs/pl/intlayer_CMS.md +5 -139
  72. package/docs/pl/live-sync.md +185 -0
  73. package/docs/pl/releases/v9.md +45 -1
  74. package/docs/pt/cli/index.md +1 -1
  75. package/docs/pt/configuration.md +45 -1
  76. package/docs/pt/intlayer_CMS.md +5 -143
  77. package/docs/pt/live-sync.md +174 -0
  78. package/docs/pt/releases/v9.md +45 -1
  79. package/docs/ru/cli/index.md +1 -1
  80. package/docs/ru/configuration.md +42 -1
  81. package/docs/ru/intlayer_CMS.md +5 -139
  82. package/docs/ru/live-sync.md +185 -0
  83. package/docs/ru/releases/v9.md +45 -1
  84. package/docs/tr/cli/index.md +1 -1
  85. package/docs/tr/configuration.md +42 -1
  86. package/docs/tr/intlayer_CMS.md +5 -127
  87. package/docs/tr/live-sync.md +173 -0
  88. package/docs/tr/releases/v9.md +45 -1
  89. package/docs/uk/cli/index.md +1 -1
  90. package/docs/uk/configuration.md +42 -1
  91. package/docs/uk/intlayer_CMS.md +5 -139
  92. package/docs/uk/live-sync.md +185 -0
  93. package/docs/uk/releases/v9.md +45 -1
  94. package/docs/ur/cli/index.md +1 -1
  95. package/docs/ur/configuration.md +45 -1
  96. package/docs/vi/cli/index.md +1 -1
  97. package/docs/vi/configuration.md +42 -1
  98. package/docs/vi/intlayer_CMS.md +5 -139
  99. package/docs/vi/live-sync.md +185 -0
  100. package/docs/vi/releases/v9.md +45 -1
  101. package/docs/zh/cli/index.md +1 -1
  102. package/docs/zh/configuration.md +42 -1
  103. package/docs/zh/intlayer_CMS.md +5 -129
  104. package/docs/zh/live-sync.md +175 -0
  105. package/docs/zh/releases/v9.md +45 -1
  106. package/package.json +7 -7
  107. package/src/generated/docs.entry.ts +40 -0
@@ -0,0 +1,222 @@
1
+ ---
2
+ createdAt: 2026-07-08
3
+ updatedAt: 2026-07-08
4
+ title: Intlayer Analytics | Track content exposure and run A/B tests
5
+ description: Discover how @intlayer/analytics tracks page/locale views and content exposure, and how to use it to run A/B tests on your Intlayer content.
6
+ keywords:
7
+ - Analytics
8
+ - A/B Testing
9
+ - Audience
10
+ - Internationalization
11
+ - Documentation
12
+ - Intlayer
13
+ - Next.js
14
+ - JavaScript
15
+ - React
16
+ slugs:
17
+ - doc
18
+ - concept
19
+ - analytics
20
+ history:
21
+ - version: 9.0.0
22
+ date: 2026-07-08
23
+ changes: "Init doc — @intlayer/analytics package, provider/node-level tracking, A/B testing, dashboard"
24
+ author: aymericzip
25
+ ---
26
+
27
+ # Intlayer Analytics Documentation
28
+
29
+ `@intlayer/analytics` is an optional companion package that tells you **which content is actually shown** to your visitors — which page, in which locale, and which specific piece of translated content — so you can understand your audience and run **A/B tests on content**.
30
+
31
+ ## Table of Contents
32
+
33
+ <TOC/>
34
+
35
+ ---
36
+
37
+ ## What it tracks
38
+
39
+ `@intlayer/analytics` batches three kinds of anonymous events:
40
+
41
+ | Event | Captured where | What it tells you |
42
+ | ------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
43
+ | `page_view` | Provider level (`IntlayerProvider`) | Which page and locale a session viewed, on first load, route change, or locale switch. |
44
+ | `content_exposure` | Node level (`useIntlayer` / interpreter plugins) | Which dictionary key / key path was actually resolved and displayed — and, when part of an experiment, which **variant**. |
45
+ | `conversion` | Wherever you call `useConversion()` | A goal reached (signup, click, purchase…) attributed to the A/B variant the session was exposed to. |
46
+
47
+ Events are collected in memory and sent as a **single batched request roughly every 20 seconds** — never on every keystroke or render — so analytics never impacts first render time or adds a request per interaction.
48
+
49
+ ## How it powers A/B testing on content
50
+
51
+ Intlayer already lets you declare content [Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/index.md) (e.g. a `hero-banner` dictionary with a `control` and a `black_friday` variant). `@intlayer/analytics` closes the loop:
52
+
53
+ 1. `getVariant(experimentKey, variants)` deterministically assigns each anonymous session to a variant — a pure function of the session id and the experiment key, so the assignment is **stable across the session** and requires **no server round-trip** before first render (no flicker, no layout shift).
54
+ 2. Every `content_exposure` event carries the `variant` that was shown.
55
+ 3. `useConversion()` lets you attribute a goal (e.g. `"cta_click"`) to that variant.
56
+ 4. The dashboard's experiment results endpoint compares conversion rates per variant, including statistical significance (a z-test).
57
+
58
+ ## Installation
59
+
60
+ `@intlayer/analytics` is a **peer, optional** dependency — never installed automatically by a framework package. Add it alongside `intlayer`:
61
+
62
+ ```bash packageManager="npm"
63
+ npm install @intlayer/analytics
64
+ ```
65
+
66
+ ```bash packageManager="yarn"
67
+ yarn add @intlayer/analytics
68
+ ```
69
+
70
+ ```bash packageManager="pnpm"
71
+ pnpm add @intlayer/analytics
72
+ ```
73
+
74
+ ```bash packageManager="bun"
75
+ bun add @intlayer/analytics
76
+ ```
77
+
78
+ If you don't install it, every integration point resolves to a no-op — see [Zero-cost when not installed](#zero-cost-when-not-installed) below.
79
+
80
+ ## Configuration
81
+
82
+ Analytics **reuses the existing `editor` configuration block** — there is no separate `analytics` config schema to fill in:
83
+
84
+ ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
85
+ import type { IntlayerConfig } from "intlayer";
86
+
87
+ const config: IntlayerConfig = {
88
+ editor: {
89
+ backendURL: "https://back.intlayer.org", // Also used as the analytics ingestion endpoint
90
+ clientId: "your-client-id", // Also used as the analytics project key
91
+ clientSecret: "your-client-secret",
92
+ },
93
+ };
94
+
95
+ export default config;
96
+ ```
97
+
98
+ - `editor.backendURL` — the base URL analytics events are sent to (`POST {backendURL}/api/analytics/events`).
99
+ - `editor.clientId` — the public project key attributed to every ingested event. It also acts as the **enable switch**: analytics stays fully disabled (and tree-shaken, see below) until `clientId` is configured.
100
+
101
+ If you self-host Intlayer, analytics automatically points at your own instance since it shares `editor.backendURL`.
102
+
103
+ ## Framework support
104
+
105
+ Analytics is wired into the shared `IntlayerProvider` from `react-intlayer`, so it is available today anywhere that provider is used:
106
+
107
+ | Framework | Status |
108
+ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
109
+ | React | ✅ Available |
110
+ | Next.js (`next-intlayer`) | ✅ Available (via `react-intlayer`) |
111
+ | React Native / Expo (`react-native-intlayer`) | ✅ Available (via `react-intlayer`) |
112
+ | Vue, Svelte, Angular, Solid, Preact, Lit, Astro, Vanilla | 🚧 Planned — same client, provider-level bindings following the `@intlayer/editor` rollout pattern |
113
+
114
+ ## Usage
115
+
116
+ ### Automatic provider-level tracking
117
+
118
+ No code changes are required. Once `@intlayer/analytics` is installed and `editor.clientId` is configured, `IntlayerProvider` automatically:
119
+
120
+ - initializes the analytics client on mount,
121
+ - records a `page_view` on initial load,
122
+ - records a `page_view` on every locale change,
123
+ - starts the ~20s flush loop and flushes any remaining events on unmount / tab close (via `navigator.sendBeacon`, falling back to `fetch(..., { keepalive: true })`).
124
+
125
+ ### Automatic node-level tracking
126
+
127
+ Every time `useIntlayer` resolves a piece of content for display, the interpreter reports a `content_exposure` event for that exact `dictionaryKey` + key path + locale — again, no code changes required. Repeated exposures of the same node within a flush window are coalesced into a single event with a `count`, so a list re-rendering 50 times doesn't send 50 events.
128
+
129
+ ### Tracking conversions for A/B tests
130
+
131
+ Use `useConversion()` to attribute a goal to the variant a session saw:
132
+
133
+ ```tsx fileName="CTAButton.tsx" codeFormat="tsx"
134
+ import { useConversion } from "react-intlayer";
135
+
136
+ const CTAButton = () => {
137
+ const trackConversion = useConversion();
138
+
139
+ return (
140
+ <button
141
+ onClick={() =>
142
+ trackConversion({
143
+ experimentKey: "homepage-hero",
144
+ variant: "black_friday",
145
+ goal: "cta_click",
146
+ })
147
+ }
148
+ >
149
+ Get started
150
+ </button>
151
+ );
152
+ };
153
+ ```
154
+
155
+ ### Resolving a variant client-side
156
+
157
+ ```tsx fileName="useHeroVariant.ts" codeFormat="tsx"
158
+ import { getGlobalAnalyticsClient } from "@intlayer/analytics/client";
159
+
160
+ const client = getGlobalAnalyticsClient();
161
+ const variant = client?.getVariant("homepage-hero", [
162
+ "control",
163
+ "black_friday",
164
+ ]);
165
+ ```
166
+
167
+ ## Privacy & performance
168
+
169
+ - **Anonymous by design**: sessions are identified by a rotating id; the backend only ever stores a **SHA-256 hash** of that id — never the raw id, never an IP address.
170
+ - **Location is coarse**: only a country code, derived from CDN geolocation headers (`cf-ipcountry`, `x-vercel-ip-country`, …) — no IP is read or stored.
171
+ - **URLs exclude search params** by default, so query strings are never captured.
172
+ - **Sampling**: `sampleRate` lets you keep only a fraction of content-exposure events on high-traffic apps.
173
+ - **Batched**: one request roughly every 20 seconds (`flushInterval`), or earlier if the buffer fills up (`maxBufferSize`) — never one request per event.
174
+
175
+ ### Zero-cost when not installed
176
+
177
+ `@intlayer/analytics` follows the exact same optional-dependency pattern as `@intlayer/editor`:
178
+
179
+ - every integration point loads the package via a **dynamic `import()` wrapped in `try/catch`** — an app that never installs `@intlayer/analytics` never pays a bundle-size or runtime cost, and never sees an error;
180
+ - a compile-time env var (`INTLAYER_ANALYTICS_ENABLED`), automatically set to `'false'` by `@intlayer/config` whenever `editor.clientId` is not configured, lets bundlers **dead-code-eliminate** the whole integration;
181
+ - analytics is disabled inside the Intlayer editor/CMS preview iframe, so editor sessions are never counted as real traffic.
182
+
183
+ ## Dashboard: Analytics page
184
+
185
+ Once your project has collected events, the **Analytics** page in the [Intlayer dashboard](https://app.intlayer.org/analytics) (visible in the sidebar once a project is selected) shows:
186
+
187
+ - **Active users** — distinct visitors over the selected rolling window (7 / 30 / 90 days).
188
+ - **Users today** and **users over the last 7 days**.
189
+ - **Page views** over the selected window.
190
+ - An **evolution graph** of daily distinct visitors.
191
+ - **Locales** and **Location** breakdown tabs, ranking your audience by locale and by country.
192
+
193
+ ## Backend API reference
194
+
195
+ All read endpoints require authentication; ingestion is public and attributed by `clientId`.
196
+
197
+ | Method | Endpoint | Description |
198
+ | ------ | ------------------------------------------- | -------------------------------------------------------------------------------- |
199
+ | `POST` | `/api/analytics/events` | Ingest a batch of events (public, attributed by `clientId` in the body). |
200
+ | `GET` | `/api/analytics/overview` | Page/locale totals for the authenticated project. |
201
+ | `GET` | `/api/analytics/audience?days=30` | Distinct visitors, page views, daily series, locale + country breakdowns. |
202
+ | `GET` | `/api/analytics/content-stats` | Per-content exposure totals, grouped by dictionary key / key path / locale. |
203
+ | `GET` | `/api/analytics/experiments/:experimentKey` | Per-variant conversion rates and statistical significance for an A/B experiment. |
204
+
205
+ You can also call these programmatically with the [CMS SDK](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md):
206
+
207
+ ```ts fileName="analytics.ts"
208
+ import { createIntlayerCMS } from "@intlayer/api";
209
+ import { analyticsEndpoint } from "@intlayer/api/analytics";
210
+
211
+ const cms = createIntlayerCMS();
212
+
213
+ const { data: audience } = await analyticsEndpoint(cms).getAudience(30);
214
+ ```
215
+
216
+ ## Useful links
217
+
218
+ - [Dynamic Dictionaries - Collections & Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dynamic_dictionaries/index.md)
219
+ - [Intlayer CMS - CMS SDK](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
220
+ - [Intlayer Visual Editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md)
221
+ - [Configuration Reference](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md)
222
+ - [Self-Hosting Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/self_hosting.md)
@@ -125,7 +125,7 @@ To see how to configure available locales, or other parameters, refer to the [co
125
125
 
126
126
  ### Authentication
127
127
 
128
- - **[Login](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/login.md)** - Authenticate with the Intlayer CMS and get access credentials
128
+ - **[Login](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/login.md)** - Authenticate with the Intlayer CMS and get access credentials
129
129
 
130
130
  ### Core Commands
131
131
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2024-08-13
3
- updatedAt: 2026-06-23
3
+ updatedAt: 2026-07-11
4
4
  title: Configuration
5
5
  description: Learn how to configure Intlayer for your application. Understand the various settings and options available to customize Intlayer to your needs.
6
6
  keywords:
@@ -14,6 +14,9 @@ slugs:
14
14
  - concept
15
15
  - configuration
16
16
  history:
17
+ - version: 9.0.0
18
+ date: 2026-07-11
19
+ changes: "Add `analytics` configuration"
17
20
  - version: 9.0.0
18
21
  date: 2026-06-24
19
22
  changes: "Add `enableProxy` option to the routing configuration"
@@ -365,6 +368,30 @@ const config: IntlayerConfig = {
365
368
  liveSync: true,
366
369
  },
367
370
 
371
+ /**
372
+ * Analytics configuration.
373
+ */
374
+ analytics: {
375
+ /**
376
+ * Whether analytics collection is enabled (page views, content exposures, A/B events).
377
+ * Requires `editor.clientId` to be set for attribution.
378
+ * Default: false
379
+ */
380
+ enabled: true,
381
+
382
+ /**
383
+ * Milliseconds between automatic batched flushes to the backend.
384
+ * Default: 20000
385
+ */
386
+ flushInterval: 20000,
387
+
388
+ /**
389
+ * Fraction of sessions to record, from 0 (none) to 1 (all).
390
+ * Default: 1
391
+ */
392
+ sampleRate: 1,
393
+ },
394
+
368
395
  /**
369
396
  * AI-powered translation and generation settings.
370
397
  */
@@ -680,6 +707,20 @@ Defines settings related to the integrated editor, including server port and act
680
707
  | `liveSyncPort` | The port of the live sync server. | `number` | `4000` | `4000` | |
681
708
  | `liveSyncURL` | The URL of the live sync server. | `string` | `'http://localhost:{liveSyncPort}'` | `'https://example.com'` | Points to localhost by default; can be changed for a remote live sync server. |
682
709
 
710
+ ### Analytics Configuration
711
+
712
+ Defines settings related to Intlayer analytics: collecting which content is actually shown to users (page views, content exposures) and powering content A/B testing.
713
+
714
+ Analytics is strictly opt-in: nothing is collected unless `analytics.enabled` is explicitly set to `true` **and** a project key (`editor.clientId`) is configured for attribution. When disabled (the default), the whole analytics integration is dead-code-eliminated from your application bundle.
715
+
716
+ | Field | Description | Type | Default | Example | Note |
717
+ | --------------- | ------------------------------------------------------------------------- | --------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------- |
718
+ | `enabled` | Enables analytics collection (page views, content exposures, A/B events). | `boolean` | `false` | `true` | Requires `editor.clientId` to be set for attribution; otherwise analytics stays disabled even if `enabled` is `true`. |
719
+ | `flushInterval` | Milliseconds between automatic batched flushes to the backend. | `number` | `20000` | `10000` | |
720
+ | `sampleRate` | Fraction of sessions to record, from `0` (none) to `1` (all). | `number` | `1` | `0.5` | Sampling is deterministic per session, so a recorded session reports all of its events (no partial funnels). |
721
+
722
+ ---
723
+
683
724
  ### Routing Configuration
684
725
 
685
726
  Settings that control routing behavior, including URL structure, locale storage, and middleware handling.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-08-23
3
- updatedAt: 2026-06-29
3
+ updatedAt: 2026-07-08
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,9 @@ 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-07-08
23
+ changes: "Move Live Sync section to its own page (live-sync.md), keep a short intro + link here"
21
24
  - version: 9.0.0
22
25
  date: 2026-06-30
23
26
  changes: "Add Self-Hosting section: Docker Compose bootstrap, service inventory, SDK configuration, optional features, and upgrade notes"
@@ -401,146 +404,9 @@ await pushDictionaries([{ key: "home", content: { title: "Home" } }]);
401
404
 
402
405
  ## Live sync
403
406
 
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.
405
-
406
- Enable Live Sync by updating your Intlayer configuration:
407
-
408
- ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
409
- import type { IntlayerConfig } from "intlayer";
410
-
411
- const config: IntlayerConfig = {
412
- // ... other configuration settings
413
- editor: {
414
- /**
415
- * Enables hot reloading of locale configurations when changes are detected.
416
- * For example, when a dictionary is added or updated, the application updates
417
- * the content displayed on the page.
418
- *
419
- * Because hot reloading requires a continuous connection to the server, it is
420
- * only available for clients of the `enterprise` plan.
421
- *
422
- * Default: false
423
- */
424
- liveSync: true,
425
- },
426
- dictionary: {
427
- /**
428
- * Controls how dictionaries are imported:
429
- *
430
- * - "fetch": Dictionaries are fetched dynamically using the Live Sync API.
431
- * Replaces useIntlayer with useDictionaryDynamic.
432
- *
433
- * Note: Live mode uses the Live Sync API to fetch dictionaries. If the API call
434
- * fails, dictionaries are imported dynamically.
435
- * Note: Only dictionaries with remote content and "live" flags use live mode.
436
- * Others use dynamic mode for performance.
437
- */
438
- importMode: "fetch",
439
- },
440
- };
441
-
442
- export default config;
443
- ```
444
-
445
- Start the Live Sync server to wrap your application:
446
-
447
- Example using standalone server:
448
-
449
- ```json5 fileName="package.json"
450
- {
451
- "scripts": {
452
- // ... other scripts
453
- "live:start": "npx intlayer live",
454
- },
455
- }
456
- ```
457
-
458
- You can also use your application server in parallel using the `--process` argument.
459
-
460
- Example using Next.js:
461
-
462
- ```json5 fileName="package.json"
463
- {
464
- "scripts": {
465
- // ... other scripts
466
- "build": "next build",
467
- "dev": "next dev",
468
- "start": "npx intlayer live --with 'next start'",
469
- },
470
- }
471
- ```
472
-
473
- Example using Vite:
474
-
475
- ```json5 fileName="package.json"
476
- {
477
- "scripts": {
478
- // ... other scripts
479
- "build": "vite build",
480
- "dev": "vite dev",
481
- "start": "npx intlayer live --with 'vite start'",
482
- },
483
- }
484
- ```
485
-
486
- The Live Sync server wraps your application and automatically applies updated content as it arrives.
487
-
488
- To receive change notifications from the CMS, the Live Sync server maintains an SSE connection to the backend. When content changes in the CMS, the backend forwards the update to the Live Sync server, which writes the new dictionaries. Your application will reflect the update on the next navigation or browser reload, no rebuild required.
489
-
490
- Flow chart (CMS/Backend -> Live Sync Server -> Application Server -> Frontend):
491
-
492
- ![Live Sync Flow CMS/Backend/Live Sync Server/Application Server/Frontend Schema](https://github.com/aymericzip/intlayer/blob/main/docs/assets/live_sync_flow_scema.svg)
493
-
494
- How it works:
495
-
496
- ![Live Sync Logic Schema](https://github.com/aymericzip/intlayer/blob/main/docs/assets/live_sync_logic_schema.svg)
497
-
498
- ### Development workflow (local)
499
-
500
- - In development, all remote dictionaries are fetched when the application starts, so you can test updates quickly.
501
- - To test Live Sync locally with Next.js, wrap your dev server:
502
-
503
- ```json5 fileName="package.json"
504
- {
505
- "scripts": {
506
- // ... other scripts
507
- "dev": "npx intlayer live --with 'next dev'",
508
- // "dev": "npx intlayer live --with 'vite dev'", // For Vite
509
- },
510
- }
511
- ```
512
-
513
- Enable optimization so Intlayer applies the Live import transformations during development:
514
-
515
- ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
516
- import type { IntlayerConfig } from "intlayer";
517
-
518
- const config: IntlayerConfig = {
519
- editor: {
520
- applicationURL: "http://localhost:5173",
521
- liveSyncURL: "http://localhost:4000",
522
- liveSync: true,
523
- },
524
- dictionary: {
525
- importMode: "fetch",
526
- },
527
- build: {
528
- optimize: true, // default: process.env.NODE_ENV === 'production'
529
- },
530
- };
531
-
532
- export default config;
533
- ```
534
-
535
- This setup wraps your dev server with the Live Sync server, fetches remote dictionaries at startup, and streams updates from the CMS via SSE. Refresh the page to see changes.
536
-
537
- Notes and constraints:
407
+ 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.
538
408
 
539
- - Add the live sync origin to your site security policy (CSP). Ensure the live sync URL is allowed in `connect-src` (and `frame-ancestors` if relevant).
540
- - Live Sync does not work with static output. For Next.js, the page must be dynamic to receive updates at runtime (e.g., use `generateStaticParams`, `generateMetadata`, `getServerSideProps`, or `getStaticProps` appropriately to avoid full static-only constraints).
541
- - In the CMS, each dictionary has a `live` flag. Only dictionaries with `live=true` are fetched via the live sync API; others are imported dynamically and remain unchanged at runtime.
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.
543
- - The live sync server must be able to write to `.intlayer`. In containers, ensure write access to `/.intlayer`.
409
+ For the full setup guide (configuration, starting the Live Sync server, the local development workflow, and constraints), see the [Live Sync documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/live-sync.md).
544
410
 
545
411
  ## Self-Hosting
546
412
 
@@ -0,0 +1,184 @@
1
+ ---
2
+ createdAt: 2026-07-08
3
+ updatedAt: 2026-07-08
4
+ title: Live Sync | Reflect CMS content changes at runtime
5
+ description: Let your app reflect Intlayer CMS content changes at runtime, with no rebuild or redeploy required.
6
+ keywords:
7
+ - Live Sync
8
+ - CMS
9
+ - Visual Editor
10
+ - Internationalization
11
+ - Documentation
12
+ - Intlayer
13
+ - Next.js
14
+ - Vite
15
+ history:
16
+ - version: 9.0.0
17
+ date: 2026-07-08
18
+ changes: "Extracted from the Intlayer CMS documentation into its own page"
19
+ - version: 6.0.1
20
+ date: 2025-09-22
21
+ changes: "Add live sync documentation"
22
+ - version: 6.0.0
23
+ date: 2025-09-04
24
+ changes: "Replace `hotReload` field by `liveSync`"
25
+ author: aymericzip
26
+ ---
27
+
28
+ # Intlayer Live Sync
29
+
30
+ Live Sync lets your app reflect [Intlayer CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md) 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.
31
+
32
+ ## Table of Contents
33
+
34
+ <TOC/>
35
+
36
+ ---
37
+
38
+ ## Enabling Live Sync
39
+
40
+ Enable Live Sync by updating your Intlayer configuration:
41
+
42
+ ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
43
+ import type { IntlayerConfig } from "intlayer";
44
+
45
+ const config: IntlayerConfig = {
46
+ // ... other configuration settings
47
+ editor: {
48
+ /**
49
+ * Enables hot reloading of locale configurations when changes are detected.
50
+ * For example, when a dictionary is added or updated, the application updates
51
+ * the content displayed on the page.
52
+ *
53
+ * Because hot reloading requires a continuous connection to the server, it is
54
+ * only available for clients of the `enterprise` plan.
55
+ *
56
+ * Default: false
57
+ */
58
+ liveSync: true,
59
+ },
60
+ dictionary: {
61
+ /**
62
+ * Controls how dictionaries are imported:
63
+ *
64
+ * - "fetch": Dictionaries are fetched dynamically using the Live Sync API.
65
+ * Replaces useIntlayer with useDictionaryDynamic.
66
+ *
67
+ * Note: Live mode uses the Live Sync API to fetch dictionaries. If the API call
68
+ * fails, dictionaries are imported dynamically.
69
+ * Note: Only dictionaries with remote content and "live" flags use live mode.
70
+ * Others use dynamic mode for performance.
71
+ */
72
+ importMode: "fetch",
73
+ },
74
+ };
75
+
76
+ export default config;
77
+ ```
78
+
79
+ Start the Live Sync server to wrap your application:
80
+
81
+ Example using standalone server:
82
+
83
+ ```json5 fileName="package.json"
84
+ {
85
+ "scripts": {
86
+ // ... other scripts
87
+ "live:start": "npx intlayer live",
88
+ },
89
+ }
90
+ ```
91
+
92
+ You can also use your application server in parallel using the `--process` argument.
93
+
94
+ Example using Next.js:
95
+
96
+ ```json5 fileName="package.json"
97
+ {
98
+ "scripts": {
99
+ // ... other scripts
100
+ "build": "next build",
101
+ "dev": "next dev",
102
+ "start": "npx intlayer live --with 'next start'",
103
+ },
104
+ }
105
+ ```
106
+
107
+ Example using Vite:
108
+
109
+ ```json5 fileName="package.json"
110
+ {
111
+ "scripts": {
112
+ // ... other scripts
113
+ "build": "vite build",
114
+ "dev": "vite dev",
115
+ "start": "npx intlayer live --with 'vite start'",
116
+ },
117
+ }
118
+ ```
119
+
120
+ The Live Sync server wraps your application and automatically applies updated content as it arrives.
121
+
122
+ To receive change notifications from the CMS, the Live Sync server maintains an SSE connection to the backend. When content changes in the CMS, the backend forwards the update to the Live Sync server, which writes the new dictionaries. Your application will reflect the update on the next navigation or browser reload, no rebuild required.
123
+
124
+ Flow chart (CMS/Backend -> Live Sync Server -> Application Server -> Frontend):
125
+
126
+ ![Live Sync Flow CMS/Backend/Live Sync Server/Application Server/Frontend Schema](https://github.com/aymericzip/intlayer/blob/main/docs/assets/live_sync_flow_scema.svg)
127
+
128
+ How it works:
129
+
130
+ ![Live Sync Logic Schema](https://github.com/aymericzip/intlayer/blob/main/docs/assets/live_sync_logic_schema.svg)
131
+
132
+ ## Development workflow (local)
133
+
134
+ - In development, all remote dictionaries are fetched when the application starts, so you can test updates quickly.
135
+ - To test Live Sync locally with Next.js, wrap your dev server:
136
+
137
+ ```json5 fileName="package.json"
138
+ {
139
+ "scripts": {
140
+ // ... other scripts
141
+ "dev": "npx intlayer live --with 'next dev'",
142
+ // "dev": "npx intlayer live --with 'vite dev'", // For Vite
143
+ },
144
+ }
145
+ ```
146
+
147
+ Enable optimization so Intlayer applies the Live import transformations during development:
148
+
149
+ ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
150
+ import type { IntlayerConfig } from "intlayer";
151
+
152
+ const config: IntlayerConfig = {
153
+ editor: {
154
+ applicationURL: "http://localhost:5173",
155
+ liveSyncURL: "http://localhost:4000",
156
+ liveSync: true,
157
+ },
158
+ dictionary: {
159
+ importMode: "fetch",
160
+ },
161
+ build: {
162
+ optimize: true, // default: process.env.NODE_ENV === 'production'
163
+ },
164
+ };
165
+
166
+ export default config;
167
+ ```
168
+
169
+ This setup wraps your dev server with the Live Sync server, fetches remote dictionaries at startup, and streams updates from the CMS via SSE. Refresh the page to see changes.
170
+
171
+ ## Notes and constraints
172
+
173
+ - Add the live sync origin to your site security policy (CSP). Ensure the live sync URL is allowed in `connect-src` (and `frame-ancestors` if relevant).
174
+ - Live Sync does not work with static output. For Next.js, the page must be dynamic to receive updates at runtime (e.g., use `generateStaticParams`, `generateMetadata`, `getServerSideProps`, or `getStaticProps` appropriately to avoid full static-only constraints).
175
+ - In the CMS, each dictionary has a `live` flag. Only dictionaries with `live=true` are fetched via the live sync API; others are imported dynamically and remain unchanged at runtime.
176
+ - 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.
177
+ - The live sync server must be able to write to `.intlayer`. In containers, ensure write access to `/.intlayer`.
178
+
179
+ ## Useful links
180
+
181
+ - [Intlayer CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
182
+ - [Intlayer Visual Editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md)
183
+ - [Configuration Reference](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md)
184
+ - [Self-Hosting Guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/self_hosting.md)