Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ Repository-wide baseline. Child files add local constraints; the nearest child f
- Implementations consume local package tarballs from `pkgs/` after `pnpm build:pkgs` plus the
implementation install step.

## Reference implementations

- Treat `implementations/**` as first-class product artifacts: maintained SDK integration contracts,
customer-facing evidence, and required validation targets for the SDK surfaces they exercise.
- Treat broken, stale, incomplete, or needlessly reduced reference implementations as SDK-suite
quality issues unless evidence shows the affected behavior is no longer supported.
- Do not treat reference implementations as optional demos, disposable samples, or places to reduce
behavior for convenience. When public SDK behavior changes, identify affected reference
implementations before concluding validation.

## Code discipline

- Treat [`eslint.config.ts`](./eslint.config.ts) as an upfront design constraint.
Expand Down
18 changes: 9 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ pnpm version:pnpm

## Repository map

| Path | Purpose |
| -------------------- | ----------------------------------------------------------------------------------- |
| `lib/` | Internal shared tooling and mock services, such as `build-tools` and `mocks` |
| `packages/` | Workspace packages, including the published SDKs and framework layers |
| `implementations/` | Reference applications used for integration testing, local demos, and E2E coverage |
| `pkgs/` | Generated tarballs created by `pnpm build:pkgs`; implementations install from these |
| `docs/` | Generated TypeDoc output |
| `dist/`, `coverage/` | Generated build and test artifacts inside individual workspaces |
| Path | Purpose |
| -------------------- | ------------------------------------------------------------------------------------------ |
| `lib/` | Internal shared tooling and mock services, such as `build-tools` and `mocks` |
| `packages/` | Workspace packages, including the published SDKs and framework layers |
| `implementations/` | Reference applications used for integration testing, validation evidence, and E2E coverage |
| `pkgs/` | Generated tarballs created by `pnpm build:pkgs`; implementations install from these |
| `docs/` | Generated TypeDoc output |
| `dist/`, `coverage/` | Generated build and test artifacts inside individual workspaces |

The most important repository-specific mechanic is this:

Expand Down Expand Up @@ -335,7 +335,7 @@ category:
caveats, and links to guides, reference implementations, and generated API reference.
- Lower-level package READMEs explain the package's role in the SDK stack, who uses it directly,
common setup options where useful, and where exhaustive API details live.
- Reference implementation READMEs stay procedural: what the implementation demonstrates,
- Reference implementation READMEs stay procedural: what the implementation validates,
prerequisites, setup, run/test commands, environment notes, and related package links.
- Internal and placeholder READMEs stay short, explicit, and status-oriented.

Expand Down
4 changes: 4 additions & 0 deletions STYLE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ Use the repository-standard product names and terms from `AGENTS.md`, including:
- reference implementation
- exact package names, such as `@contentful/optimization-web`

When referring to in-repo apps under `implementations/`, use `reference implementation` or
`reference app`. Do not use `demo`, `sample`, or `example` to describe their status; reserve
`example` for code snippets or package-local harnesses when accurate.

Use Contentful product terms consistently when they apply:

- `app` - An HTML5 application that extends the functionality of the Contentful web app or
Expand Down
3 changes: 3 additions & 0 deletions documentation/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Applies to authored documentation under `documentation/`.
- In guides, do not place concept links in the opening before quick-start material unless the
concept is required for safe action. Put deeper mechanics links after the relevant step or in a
`## Learn more` section.
- Treat reference implementations as maintained validation evidence and comparison targets for
supported integration paths. Do not frame them as optional examples, disposable samples, or
lower-stakes app code.
- Guides, concepts, and product documents may link to docs, package READMEs, implementation READMEs,
and generated reference docs, but not directly to source code, tests, generated outputs, or source
line numbers.
Expand Down
5 changes: 3 additions & 2 deletions documentation/concepts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ they are not the first stop for installation or setup commands.
explains how SDK consent state, event allow-lists, blocked-event diagnostics, persistence, and
application-owned CMP policy work together to support consent-aware integrations.
- [Entry optimization and variant resolution](./entry-personalization-and-variant-resolution.md) -
explains how the SDK resolves a Contentful baseline entry to the selected entry variant, including
data model expectations, fallback behavior, resolution paths, and preview overrides.
explains how the SDK resolves a manual `baselineEntry` or SDK-managed Contentful fetch with
`contentful: { client }` to the selected entry variant, including single-locale CDA shape
expectations, fallback behavior, framework `entryId` paths, and preview overrides.
- [Locale handling in the Optimization SDK Suite](./locale-handling-in-the-optimization-sdk-suite.md) -
explains how application-owned Contentful locales differ from SDK Experience/event locales.
- [Interaction tracking in Web SDKs](./interaction-tracking-in-web-sdks.md) - explains how
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ Account for these constraints before wiring lifecycle details:
- **Storage availability** - Platform storage is a durability layer, not the live source of truth.
If browser storage, AsyncStorage, UserDefaults, or SharedPreferences is unavailable or blocked,
design the application to continue from runtime state.
- **Managed entry fetching** - SDK-managed entry fetching still uses the application-configured
`contentful.js` client and does not change consent ownership. Apply the same CMP, routing, locale,
and cache policy before choosing manual `baselineEntry` resolution or managed
`fetchOptimizedEntry()`.
- **Offline queue purge** - Withdrawing event consent with `consent(false)` purges queued SDK
Experience and Insights events. Blocked events are not replayed when consent later becomes true.
- **Preview mode** - Preview panels and preview overrides change live-update and preview behavior;
Expand Down
35 changes: 27 additions & 8 deletions documentation/concepts/core-state-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ Swift or Kotlin published state in native runtimes, and request objects in Node/
### Key state definitions

**Locale state** is the SDK Experience API and event locale. It is not a Contentful Delivery API
locale and it does not fetch localized entries for your application. In stateful JavaScript
runtimes, `locale` is available as `sdk.locale` and `sdk.states.locale`; `setLocale()` updates the
state signal, future Experience API requests, and default event context. React providers can update
provider-owned SDK instances from their `locale` prop. iOS and Android expose the same value as
native `locale` state from the bridge. Node and stateless runtimes bind locale per request with
`forRequest({ locale })`.
locale policy and changing it does not by itself refetch localized entries for your application. In
stateful JavaScript runtimes, `locale` is available as `sdk.locale` and `sdk.states.locale`;
`setLocale()` updates the state signal, future Experience API requests, and default event context.
JavaScript managed fetching can use this value only as a fallback `getEntry()` query locale when no
Contentful query locale is provided. Request-bound Node clients use `forRequest({ locale })` as that
fallback for managed Contentful entry fetching. React providers can update provider-owned SDK
instances from their `locale` prop. iOS and Android expose the same value as native `locale` state
from the bridge. Node and stateless runtimes bind locale per request with `forRequest({ locale })`.

**`experienceRequestState`** tells you what happened to the most recent Experience API request. It
starts as `{ status: 'idle' }`, changes to `{ status: 'pending' }` when a request starts, changes to
Expand All @@ -98,6 +100,11 @@ available. `states.optimizationPossible` can be `true` before `states.selectedOp
contains variants. Use `states.canOptimize` when you need to know whether variant selection data is
available for entry resolution.

**Selected optimization state** is the current Experience API selection array used by stateful entry
resolution. In stateful JavaScript runtimes, `resolveOptimizedEntry(entry)` uses
`states.selectedOptimizations.current` when explicit selections are omitted. In stateful Core and
Web runtimes, `fetchOptimizedEntry(entryId)` follows the same default.

### Signals and observables

`CoreStateful` stores runtime state in [Preact Signals](https://github.com/preactjs/signals), a
Expand Down Expand Up @@ -156,11 +163,14 @@ still current and has not already produced an accepted event.
The SDK locale affects default Experience API requests and event context. It does not modify your
Contentful client, router, native localization, or server i18n state. Fetch Contentful entries with
the application-owned CDA locale, and pass SDK locale separately when Experience API responses and
events need that locale.
events need that locale. JavaScript managed fetching can use SDK locale only as the fallback
Contentful `getEntry()` query locale when `contentful.defaultQuery` and the per-call query omit
`locale`.

`setLocale(locale)` validates and normalizes explicit locale values. Invalid explicit values throw
without changing locale state. In stateful SDKs, changing locale affects future requests and events;
it does not automatically refetch profile state or selected optimizations.
it does not automatically refetch profile state, selected optimizations, or localized Contentful
entries.

### Defaults, storage, offline, and preview state

Expand Down Expand Up @@ -275,6 +285,10 @@ instead of writing signal values directly. Think about state changes as a few fl
- **Experience-producing events** - `identify`, `page`, `screen`, `track`, and sticky `trackView`
send an Experience API request when consent or the allow-list permits it. A successful response
publishes profile, selected optimizations, changes, and request status in one state batch.
- **SDK-managed entry fetching** - `fetchContentfulEntry(entryId)` and
`fetchOptimizedEntry(entryId)` call the configured consumer-owned `contentful.js` client. They do
not publish profile, selected optimizations, changes, or diagnostics events. Resolution reads
current selected optimization state only when options omit explicit selections.
- **Insights and diagnostics events** - `trackView`, `trackClick`, `trackHover`, and `trackFlagView`
can update `eventStream` when the event is accepted. Sticky `trackView` also uses the Experience
path before sending its paired Insights event.
Expand All @@ -288,6 +302,11 @@ Flag reads only produce accepted flag-view delivery when event consent is `true`
`allowedEventTypes` permits `flag` or `component`, and an active Optimization profile ID exists.
Reads before either condition is true do not update the accepted flag-view dedupe signature.

The SDK-managed Contentful entry cache is separate from optimization state. It caches CDA entries
returned by the configured `contentful.js` client and does not store profile or selected
optimization data. Use `clearContentfulEntryCache()` when application locale, preview mode,
environment, or cache policy changes make those cached entries invalid.

The package also exports raw `signals` and `signalFns` references for SDK layers and first-party
preview tooling. Those exports are not application consumer APIs. Application code must treat them
as read-only implementation details and use the methods, observables, defaults, and interceptors
Expand Down
Loading
Loading