Authoritative public contract for the first DnDGem Alpha.
This document defines what external consumers may rely on. It is not a v1 stability promise. Public Alpha publication itself remains the DND-2.5 gate; DND-2.2 prepares the contract and release mechanics only.
Related: overview.md, core-domain.md, dom-adapter.md, package-boundaries.md, release-strategy.md.
- Brand: DA62
- Product: DnDGem
- Attribution: DnDGem by DA62
- Category: Content-Aware Adaptive Layout Engine
- Distinction: geometrically fits ≠ content remains useful
- Canonical: https://dndgem.dev
- Support:
support@dndgem.dev - Security:
security@dndgem.dev
| Package | Role | Typical consumer | Publication |
|---|---|---|---|
@dndgem/core |
Domain, constraints, validity, scoring, deterministic solveLayout |
Headless / all layers | Published 0.1.0-alpha.4 / @alpha |
@dndgem/dom |
Measurement, resize, drag interaction, Vanilla createLayoutSession |
Vanilla DOM apps | Published 0.1.0-alpha.4 / @alpha |
@dndgem/react |
Thin React lifecycle adapter over the DOM session | React apps | Published 0.1.0-alpha.4 / @alpha |
@dndgem/vue |
Thin Vue 3 lifecycle adapter over the DOM session | Vue 3 apps | Published 0.1.0-alpha.4 / @alpha |
@dndgem/angular |
Thin Angular lifecycle adapter over the DOM session | Angular apps | Published 0.1.0-alpha.4 / @alpha |
@dndgem/svelte |
Thin Svelte 5 lifecycle adapter over the DOM session | Svelte 5 apps | Published 0.1.0-alpha.4 / @alpha |
No other @dndgem/* packages are currently part of published Alpha. Flutter is a separate track. Meta-framework environments (Next.js, Nuxt, SvelteKit) use the adapters above — there is no @dndgem/next, @dndgem/nuxt, or @dndgem/sveltekit. Workspace-only private packages @dndgem/intelligence and @dndgem/intelligence-openai exist for Phase 4 reference/experiment work — they are not npm install targets and are not part of this Alpha contract.
Each package is ESM-only. The only supported import path is the package root:
import { solveLayout } from '@dndgem/core';
import { createLayoutSession } from '@dndgem/dom';
import { DnDGemProvider } from '@dndgem/react';
import { DnDGemProvider as VueDnDGemProvider } from '@dndgem/vue';
import { DnDGemBoardDirective } from '@dndgem/angular';
import { DnDGemProvider as SvelteDnDGemProvider } from '@dndgem/svelte';Deep imports (@dndgem/core/solve, @dndgem/dom/src/..., @dndgem/react/dist/..., @dndgem/vue/dist/..., @dndgem/angular/dist/..., @dndgem/svelte/dist/...) are not part of the contract even if a file exists in the published tarball.
Module shape:
"type": "module"exports["."].import→./dist/index.jsexports["."].types→./dist/index.d.ts- No CommonJS
requireexport
| Area | Alpha statement |
|---|---|
| Node | >=20 for tooling and ESM import of published packages |
| Bundlers | Vite / modern bundlers with ESM are the expected app path |
| Browser | Chromium / Firefox / WebKit desktop engines SUPPORTED FOR ALPHA (Playwright). Mobile NOT VALIDATED. |
| DOM | @dndgem/dom and React rendering require a browser-like DOM at runtime |
| Pointer drag | Validated interaction path |
| Keyboard drag | DEFERRED — not a product-validated path |
| Accessibility | Baseline: Escape cancel + focus/ARIA preservation; no full WCAG / SR drag claim — see a11y guide |
| SSR / hydration | Module import is safe without window. Client session after mount. No server-side layout claim. See ADR-0017. |
| Next.js / Nuxt / SvelteKit | Validated compatibility environments (DND-FX.5). Not packages. Client-session integration only. See meta-frameworks.md. |
| React | Peer react@^18 || ^19. Client mount required for DnDGemProvider. Next.js App Router: 'use client' on the integration root. |
| Vue | Peer vue@^3.5.0. Client mount required. Nuxt is a validated compatibility environment (no @dndgem/nuxt). |
| Angular | Peer @angular/core@^20 || ^21 || ^22. Client mount required. Universal not validated. Zoneless-compatible. |
| Positioning | Container is a positioned containing block; items are absolutely positioned from resolved geometry |
Repository metadata repository.url points at https://github.com/DnDGem/dndgem. The GitHub repository is PUBLIC; those links identify the canonical open-source repository. Package homepage / public support point at https://dndgem.dev (see Public site & domain hosting).
Alpha versions are 0.x prereleases (expected first publish: 0.1.0-alpha.0, npm dist-tag alpha).
That means:
- The public surface below is intentional
- Breaking changes remain possible during 0.x
- Breaking changes require a changeset and changelog entry
- Silent breaking changes are not acceptable
- Consumer-facing removals or renames must be documented
- This is not SemVer 1.0 stability
Deprecation: Alpha will prefer a documented removal in the next prerelease over long overlapping dual APIs. There is no commitment to keep deprecated names for a fixed calendar period.
Public API hardening must not change Core previous semantics:
| Situation | Core previous |
|---|---|
| Explicit drag intent | omitted |
Explicit desiredPlacements |
omitted |
| Passive resize | may be supplied |
| Constraints-only continuation | may be supplied |
Runtime:
CORE_PACKAGE_NAME,CORE_PACKAGE_VERSION,getCorePackageInfoDomainErrorLAYOUT_SCHEMA_VERSIONVALIDITY_STATEScreatePoint,createRect,createSizecreateItemId,itemIdToString,itemIdsEqualcreateContentConstraintscreateLayoutItemcreateLayoutSpacecreateLayoutIntent,listLayoutIntentItemIdscreateResolvedLayoutSCORE_PREFERENCE_WEIGHT,SCORE_USEFULNESS_WEIGHT,VALIDITY_REASON_CODESevaluateConstraintsPlacement,evaluateItemPlacement,evaluateLayoutsolveLayoutcreateAutoLayoutProposal— opt-in Auto-Layout enricher (compose withsolveLayout; does not select/score/validate)
Types (non-exhaustive of type-only aliases re-exported with the values above):
Point,Rect,RectInput,SizeItemIdContentConstraints,ContentConstraintsInputLayoutItem,LayoutItemInputLayoutSpace,LayoutSpaceInputLayoutIntent,LayoutIntentInputResolvedLayout,ResolvedLayoutInputLayoutSchemaVersionValidityStateItemPlacementEvaluation,LayoutEvaluation,ScoreBreakdownValidityAxis,ValidityReason,ValidityReasonCode,ValidityReasonKindSolverCandidateSummary,SolverInput,SolverResult,SolverSelectionCode,SolverSelectionReason,SolverStrategyAutoLayoutProposal,AutoLayoutProposalInput,PlacementOrigin
Core remains framework-agnostic, renderer-agnostic, and deterministic.
const proposal = createAutoLayoutProposal({ intent, previous?, automaticItemOrder? });
const result = solveLayout({ intent: proposal.effectiveIntent, previous? });automaticItemOrder (optional, DND-4.2 — published in 0.1.0-alpha.4) — advisory processing order for automatic items only. When omitted, Stage B/C use declaration order (Phase 3 default). Core normalizes defensively; unknown, duplicate, and source ids are ignored. Ordering guidance only — Core remains authoritative for geometry, validity, scoring, and final resolution. Consumers do not need @dndgem/intelligence.
Auto-Layout is opt-in. Calling solveLayout alone is unchanged. Available on published npm @alpha (0.1.0-alpha.1). Alpha breaking-change policy above is unchanged.
Not exported from the package root, and not supported if reached via dist files:
- Candidate generation / ranking helpers (
generateCandidates,compareCandidates,packPlacements,SOLVER_STRATEGIES) - Auto-Layout sizing helpers and
maxProbeCountForOccupancy - Numeric assertion helpers (
numbers.ts) - Any file under
tests/orbenchmarks/
Typical Vanilla consumer: createLayoutSession plus Core types as needed.
Runtime:
DOM_PACKAGE_NAME,DOM_PACKAGE_VERSION,getDomPackageInfoDomAdapterErrormeasureLayoutobserveLayoutcreateDragInteractionapplyLayoutPlacements,layoutPlacementStyle,prepareLayoutContainercreateLayoutSession— optionalautoLayout?: boolean(default off / undefined = explicit-only path)
Types include measurement snapshots, session/interaction state, drag events, and the replaceable DragMechanicsAdapter seam.
createLayoutSession({ autoLayout?: boolean }) — when autoLayout: true:
desiredPlacementsmay be partial or absent (Source Intent); remaining items are proposed automaticallyLayoutSessionState.autoLayoutis{ enabled: true; proposalUnplacedItemIds: readonly string[] }(Auto-Layout proposal completeness only — not solver INVALID, and not “missing from ResolvedLayout”)- Accepted drag promotes only the active item to Source Intent (strong persistent intent — not a pin/lock)
Default / omitted autoLayout keeps the existing explicit-only seeding path. Available on published npm @alpha (0.1.0-alpha.1).
Default path unchanged when planner is omitted.
import {
createLayoutSession,
type LayoutSessionPlanner,
type LayoutSessionPlannerEvent,
} from '@dndgem/dom';
const planner: LayoutSessionPlanner = (snapshot, context) => {
// advisory automaticItemOrder only
return { automaticItemOrder: [/* … */] };
};
const session = createLayoutSession({
container,
items,
autoLayout: true,
planner,
onPlannerEvent: (event: LayoutSessionPlannerEvent) => {
// diagnostic only — not a second solver
},
});
await session.replan(); // Promise<void>; explicit onlyPublic types (from @dndgem/dom):
| Name | Role |
|---|---|
LayoutSessionPlanner |
(snapshot, context?) => proposal | Promise<proposal> |
LayoutSessionPlanningSnapshot |
intent, optional previous, optional prominence |
LayoutSessionPlannerContext |
requestId, optional signal?: AbortSignal |
LayoutSessionPlanningProposal |
{ automaticItemOrder: readonly string[] } |
LayoutSessionPlannerEvent |
diagnostic lifecycle (planning | applied | fallback | cancelled | stale | error) |
LayoutSession.replan |
() => Promise<void> |
Contract notes:
- Intelligence proposes; deterministic DnDGem validates and resolves
- Planner never blocks first paint; initial layout uses declaration-order Auto-Layout
- Invoked only via explicit
replan()— not interaction hot paths - Planner throw/reject → Phase 3 declaration-order Auto-Layout
- Does not depend on
@dndgem/intelligence(private reference package) - Consumer guide: Advisory Planner
measureLayout/observeLayout— composing a custom loop instead ofcreateLayoutSessioncreateDragInteraction— composing drag without the session orchestratorDragMechanicsAdapterand pointer callback types — tests and provider replacement (ADR-0004)ResizeObserverConstructorinjection — tests and environments without globalResizeObserver
Application code should prefer createLayoutSession. The mechanics seam must not carry @dnd-kit types.
dndKitMechanicsAdapterand@dnd-kit/domtypessnapshotsEqual,readClientBox, and other measurement internals- React
Runtime:
REACT_PACKAGE_NAME,REACT_PACKAGE_VERSION,getReactPackageInfoDnDGemProvideruseDnDGemuseDnDGemContaineruseDnDGemItem
Types:
DnDGemItemBinding,DnDGemItemConfig,DnDGemProviderProps,DnDGemStore- Re-exported DOM callback types:
DragCancelEvent,DragDropResult,DragProposal,LayoutSessionState
DnDGemRegistryContext,DnDGemStateContext,DnDGemRegistrycreateDragInteraction/createLayoutSession(consume via@dndgem/domif needed)@dnd-kit/*
DnDGemProvider accepts optional autoLayout?: boolean (default off; mirrors DOM session), plus optional mechanics and ResizeObserver for tests. Application consumers do not need the test seams. Available on published npm @alpha (0.1.0-alpha.1).
Optional planner parity (DND-4.3 — published in 0.1.0-alpha.4): planner?, onPlannerEvent? on provider props; useDnDGem().replan(): Promise<void>. See Advisory Planner.
Hook contract:
useDnDGemContainer()→ callback ref for the positioned containeruseDnDGemItem(id)→{ ref, style }for one itemuseDnDGem()→{ state, ready }- All three throw if used outside
DnDGemProvider
Runtime (published 0.1.0-alpha.4 / @alpha):
VUE_PACKAGE_NAME,VUE_PACKAGE_VERSION,getVuePackageInfoDnDGemProvider(renderless board owner)useDnDGemuseDnDGemContaineruseDnDGemItem
Types:
DnDGemItemBinding,DnDGemItemConfig,DnDGemProviderProps,DnDGemStore- Re-exported DOM callback types:
DragCancelEvent,DragDropResult,DragProposal,LayoutSessionState
DnDGemRegistryKey,DnDGemStateKey,DnDGemRegistrycreateDragInteraction/createLayoutSession(consume via@dndgem/domif needed)@dnd-kit/*
Same behavioral contract as React/DOM: autoLayout?: boolean default off; callback identity does not recreate the session; wait-for-all registration; client mount only. Peer: vue@^3.5.0. Published on @alpha as of 0.1.0-alpha.3 (not in 0.1.0-alpha.1). Nuxt is a validated compatibility environment (no @dndgem/nuxt).
Optional planner parity (DND-4.3): planner?, onPlannerEvent?; useDnDGem().replan(): Promise<void>. See Advisory Planner.
Composable contract:
useDnDGemContainer()→ function ref for the positioned containeruseDnDGemItem(id)→{ ref, style }for one item (styleis a computed)useDnDGem()→{ state, ready }(shallowRef/computed)- All three throw if used outside
DnDGemProvider
Runtime (published 0.1.0-alpha.4 / @alpha):
ANGULAR_PACKAGE_NAME,ANGULAR_PACKAGE_VERSION,getAngularPackageInfoDnDGemBoardDirective([dndgemBoard], board-local provider)DnDGemContainerDirective([dndgemContainer])DnDGemItemDirective([dndgemItem])DnDGemBoard(injectable;state/readysignals)injectDnDGemDNDGEM_BOARD_IMPORTS
Types:
DnDGemItemConfig,DnDGemBoardConfig,DnDGemBoardCallbacks- Re-exported DOM callback types:
DragCancelEvent,DragDropResult,DragProposal,LayoutSessionState
- Board registration maps / session fields
createDragInteraction/createLayoutSession(consume via@dndgem/domif needed)@dnd-kit/*
Same behavioral contract as React/DOM/Vue: autoLayout default off; output/callback identity does not recreate the session; wait-for-all registration; client mount only. Peer: @angular/core@^20.0.0 || ^21.0.0 || ^22.0.0. Published on @alpha as of 0.1.0-alpha.3 (not in 0.1.0-alpha.1). Angular Universal is not validated.
Optional planner parity (DND-4.3): board planner / onPlannerEvent, or directive inputs dndgemPlanner / output dndgemPlannerEvent; replan(): Promise<void> on board / directive. See Advisory Planner.
Directive contract:
dndgemBoard+dndgemContaineron consumer hosts (may share one element)dndgemItem="id"registers that host as the Core item idinjectDnDGem()/DnDGemBoardthrow or fail DI outsidedndgemBoardstate/readyare Angular signals
Runtime (published 0.1.0-alpha.4 / @alpha):
SVELTE_PACKAGE_NAME,SVELTE_PACKAGE_VERSION,getSveltePackageInfoDnDGemProvider(renderless board owner)getDnDGemdndgemContainerdndgemItem
Types:
DnDGemItemConfig,DnDGemProviderProps,DnDGemSnippetProps,DnDGemStore- Re-exported DOM callback types:
DragCancelEvent,DragDropResult,DragProposal,LayoutSessionState
- Board context key / session fields
createDragInteraction/createLayoutSession(consume via@dndgem/domif needed)@dnd-kit/*
Same behavioral contract as React/DOM/Vue/Angular: autoLayout default off; callback identity does not recreate the session; wait-for-all registration; client mount only. Peer: svelte@^5.0.0. Published on @alpha as of 0.1.0-alpha.3 (not in 0.1.0-alpha.1). SvelteKit is a validated compatibility environment (no @dndgem/sveltekit).
Optional planner parity (DND-4.3): provider planner / onPlannerEvent; replan(): Promise<void> via store / context. See Advisory Planner.
Action / snippet contract:
- Children snippet receives
{ state, ready, dndgemContainer, dndgemItem }(state/readyare values) use:dndgemContainer/use:dndgemItem={'id'}register consumer hostsgetDnDGem()throws outsideDnDGemProvidergetDnDGem().state/readyare Svelte readable stores
@dnd-kit/dom is installed only on @dndgem/dom as an implementation dependency. It must not appear in:
@dndgem/corepublic types or dependencies@dndgem/reactpublic types, dependencies, or imports@dndgem/vuepublic types, dependencies, or imports@dndgem/angularpublic types, dependencies, or imports@dndgem/sveltepublic types, dependencies, or imports
Consumers must not import @dnd-kit/* to use DnDGem.
| Error | Package | Meaning |
|---|---|---|
DomainError |
core | Malformed domain input / illegal construction |
ValidityState |
core | Evaluated layout quality, not an exception |
DomAdapterError |
dom | Missing elements, disposed session, environment |
React Error |
react | Hook used outside DnDGemProvider |
Vue Error |
vue | Composable used outside DnDGemProvider |
Angular Error |
angular | Directive/inject used outside dndgemBoard |
Svelte Error |
svelte | Action/getDnDGem used outside DnDGemProvider |
Alpha documents errors and validity honestly. Developer guides and troubleshooting live in docs/guides/ (DND-2.3).
Published package versions are 0.1.0-alpha.4. npm @alpha → 0.1.0-alpha.4. Changesets owns further prereleases. Do not hand-edit packages/*/package.json versions.
- Official dist-tag:
alpha(always install with@alpha;latestis not the Alpha channel) @dndgem/core,@dndgem/dom,@dndgem/react,@dndgem/vue,@dndgem/angular, and@dndgem/svelteare a fixed Changesets group and stay version-alignedget*PackageInfo().versionmust match that package'spackage.jsonversion
See release-strategy.md.