dotCMS / dotCMS/core

@dotcms/experiments 1.0.0: Next.js 15 App Router integration crashes in UVE editor, spurious /api/v1/experiments/DEFAULT 404, and stale npm docs

Open
#36,225 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS : Experiments OKR : Customer Support stale Team : Maintenance Type : Defect
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Problem Statement

A customer integrating A/B testing with @dotcms/experiments@1.0.0 in a Next.js 15 (App Router) app (with @dotcms/react, @dotcms/uve, Analytics enabled) hit several issues. Investigation of core-web/libs/sdk/experiments/src/ confirms the SDK behavior and points to concrete defects on our side.

Confirmed findings (from source):

  1. Stale npm/docs vs. actual API. The npm docs reference import { DotExperimentsProvider } from "@dotcms/experiments", but core-web/libs/sdk/experiments/src/index.ts only exports withExperiments. DotExperimentsProvider is internal. The customer's use of withExperiments is the correct, supported pattern.

  2. UVE/editor crash ("A client-side exception has occurred"). The SDK does implement editor detection (getUVEState()?.mode in DotExperimentsProvider.tsx and useExperiments.ts; UVE_MODE.EDIT in useExperimentVariant.ts). Two root-cause candidates:

    • withExperiments is itself a hook (calls useMemoizedObject + useCallback, with /* eslint-disable react-hooks/rules-of-hooks */ in withExperiments.tsx). The README's recommended conditional pattern apiKey ? withExperiments(...) : DotCMSLayoutBody calls a hook conditionally — a rules-of-hooks violation that can crash, and differs between editor/published render paths.
    • If the UVE integration layer is not mounted, getUVEState() returns undefined, the if (!insideEditor) guard passes, and the SDK initializes inside the editor without a try/catch safety net.
  3. GET /api/v1/experiments/DEFAULT → 404. The SDK only ever calls api/v1/experiments/isUserIncluded (API_EXPERIMENTS_URL in constants.ts). The /DEFAULT request comes from the Angular backoffice: DotExperimentsService.getById() in core-web/libs/data-access/src/lib/dot-experiments/dot-experiments.service.ts issues GET /api/v1/experiments/${experimentId}. When the default variant name "DEFAULT" (EXPERIMENT_DEFAULT_VARIANT_NAME) is passed as an experiment ID, the call 404s.

  4. "No experiments assigned to the client." Expected when the experiment is not in Running status or no analytics session exists yet — needs confirmation against the customer's experiment state.

  5. No working Next.js 15 reference. examples/nextjs declares @dotcms/experiments in package.json but never uses withExperiments and does not document the integration, so there is no canonical example to point customers to.

Impact: Blocks a business-critical A/B test on the Lennox Commercial homepage. Priority/severity High.

Environment: Next.js 15 (App Router), @dotcms/experiments@1.0.0, @dotcms/react, @dotcms/uve, dotCMS QA (Current Release / dotEvergreen). Browser: Chrome.

Steps to Reproduce

  1. Build a Next.js 15 (App Router) app using @dotcms/react + @dotcms/uve.
  2. Wrap DotCMSLayoutBody with withExperiments using the conditional pattern from the README: apiKey ? withExperiments(DotCMSLayoutBody, { apiKey, server, redirectFn }) : DotCMSLayoutBody.
  3. Configure an experiment on a page (variant name e.g. HomeNew) with DEFAULT + custom variants.
  4. Open the page inside the dotCMS UVE/backoffice editor → page fails to load: "A client-side exception has occurred."
  5. Observe the browser console: GET /api/v1/experiments/DEFAULT 404 (Not Found) and No experiments assigned to the client.

Acceptance Criteria

  • @dotcms/experiments README, npm docs, and the DotExperimentsProvider.tsx JSDoc accurately state that withExperiments is the only public export; remove/replace DotExperimentsProvider usage examples.
  • The recommended integration pattern does not violate the rules of hooks. withExperiments (or the documented usage) handles the "no apiKey" case without conditionally calling a hook, so toggling experiments on/off cannot crash.
  • Opening a page inside the UVE editor never crashes due to experiments, including when getUVEState() returns undefined/null. Experiment initialization is skipped in editor mode and any init error is caught and logged rather than thrown.
  • Root cause of GET /api/v1/experiments/DEFAULT 404 is identified and fixed: DotExperimentsService.getById() (and its caller) no longer requests an experiment using the default variant name "DEFAULT" as an ID; invalid/empty IDs short-circuit instead of hitting the API.
  • examples/nextjs includes a complete, working withExperiments integration (wrapping DotCMSLayoutBody in src/views/Page.js with the safe pattern) and the README documents the Next.js 15 App Router setup.
  • Documentation clarifies the server config must point directly to the dotCMS origin (not Azure Front Door/CDN), since experiment API responses are session-specific and must not be cached.
  • Existing SDK specs (DotExperimentsProvider.spec.tsx, useExperimentVariant.spec.tsx) pass and cover the editor-mode no-crash path.

dotCMS Version

Current Release / dotEvergreen (QA). @dotcms/experiments@1.0.0, Next.js 15 (App Router), @dotcms/react, @dotcms/uve.

Severity

High - Major functionality broken

Links

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with core-web/libs/sdk/experiments/src/withExperiments.tsx, DotExperimentsProvider.tsx, useExperiments.ts, useExperimentVariant.ts, and constants.ts, then inspect DotExperimentsService in core-web/libs/data-access/src/lib/dot-experiments/dot-experiments.service.ts. Review examples/nextjs/src/views/Page.js and its README for the integration pattern. Done means the documented integration is safe in UVE, the DEFAULT request is avoided, docs are accurate, and DotExperimentsProvider.spec.tsx and useExperimentVariant.spec.tsx cover the editor path.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, next.js, react, typescript
Domain
api, documentation, frontend, testing, web-dev
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.