Source: ddx-documentation/research/rq5-frameworks.md
**Question** (BRIEF.md RQ5, G6.1): which libraries beyond shadcn/ui earn a place for the variant API, data grid, charts, carousel, DI container, rich text, markdown, PDF, drag and drop, forms and dates? Evidence: a comparison table with one pick and one rejected option each. **Answer:** one library per concern, listed below. The decision and the frozen install list are in [../adr/0005-frameworks.md](/en/docs/adr/0005-frameworks). Task 009 installs that list once. No other dependency may be added without a new ADR (plan invariant 8). ## Method 1. Stack majors from `~/.claude/ddx-topic-flows/VERSIONS.md` (verified 2026-10-10). 2. Baseline = `~/.claude/skills/create-nextjs/templates/package.json` (what the scaffold ships). 3. Live check `npm view <pkg> version` on 2026-10-23 for every package outside VERSIONS.md. 4. Defect list: `findings/hms-pattern-audit/components.md` §6 (HMS runs 2 markdown engines, 3 PDF viewers, 5 TipTap editors, `zodResolver` in 21 files vs mandated `standardSchemaResolver`). ## Comparison table | Concern | Pick | Rejected | Why the pick wins | Why the reject loses | |---|---|---|---|---| | Variant API | `class-variance-authority` (+ `clsx`, `tailwind-merge`) | `tailwind-variants` | shadcn/ui components already use cva; one variant dialect in the whole tree; tiny runtime | second dialect beside shadcn's cva; slots/compound API duplicates what ADR 0009 defines in our own prop shape | | Data grid | `@tanstack/react-table` + `@tanstack/react-virtual` | AG Grid | headless: markup and tokens stay ours (invariant 4); shadcn data-table recipe; template already pins it | ships its own theme CSS and DOM; enterprise licence for row grouping/server model; fights semantic tokens | | Charts | `recharts` | `visx` | shadcn `chart` component wraps recharts; theming by CSS variables (`--token-*`) | low-level primitives: every chart becomes hand-built SVG = more code per family | | Carousel | `embla-carousel-react` | `swiper` | shadcn `carousel` wraps embla; headless, small, no CSS file | bundles own CSS + module system; styling fights tokens | | DI container | hand-rolled typed container (React `cache()` per request on server, React context on client) | `inversify` | zero dependency; scope maps exactly to RSC request / client tree (RQ6); typed by plain TS | needs `reflect-metadata` + decorators; its singleton scope is per process, which leaks user/org state across RSC requests (ADR 0008) | | Rich text | TipTap (`@tiptap/react`, `@tiptap/pm`, `@tiptap/starter-kit`) | Lexical | ProseMirror schema, mature extension set, markdown/HTML round-trip; ONE editor family (HMS had 5–6) | smaller extension ecosystem for tables/mentions; would mean re-learning HMS editor needs on a new core | | Markdown | `streamdown` | `react-markdown` | built for streamed LLM output (unterminated blocks render safely); one engine for chat, stream and docs | **forbidden by AC14.4**; does not handle partial streamed markdown; HMS ran 2 engines | | PDF view | `pdfjs-dist` (own `PdfViewer`, one inventory family) | `react-pdf` (viewer wrapper) | direct control of worker, canvas and text layer; we own the toolbar markup (tokens) | wrapper adds a second release cycle and pins a pdf.js version we cannot move alone | | PDF build | `@react-pdf/renderer` | headless-browser print (Puppeteer) | React components → PDF in Node, no browser binary; fits `PortalPagePrint` | ships a Chromium; heavy for dev; not needed for R&D | | Drag and drop | `@dnd-kit/core` + `@dnd-kit/sortable` + `@dnd-kit/utilities` | `react-dnd` | accessible (keyboard sensor, live region), works with React 19, used by shadcn kanban/sortable recipes | HTML5 backend lacks touch and keyboard by default; low maintenance | | Forms | `react-hook-form` + `@hookform/resolvers` (`standardSchemaResolver`) + `zod` | Formik | uncontrolled inputs, Standard Schema resolver = same Zod 4 schema as ddx-api (`@ddx/contracts`) | slower re-render model; no Standard Schema resolver; HMS defect = `zodResolver` drift | | Dates | `date-fns` | `dayjs` | tree-shakable pure functions, locale objects for en/fr/de/es; `react-day-picker` (shadcn calendar) already uses it | mutable-plugin model; second date lib beside react-day-picker's | | Colour mode | `next-themes` | hand-rolled script | template baseline; `class="dark"` seeded from settings `ui.theme` (frontend-layout D8) | flash-of-wrong-theme risk, more code | | Object storage client (ddx-api) | `@aws-sdk/client-s3` + `@aws-sdk/s3-request-presigner` | `minio` JS SDK | S3 API works with MinIO and any S3 later; presigned URLs for org-scoped keys | MinIO-only API; locks the media seam to one vendor | | Motion | CSS transitions on `--token-motion-*` | `motion` (Framer) | token values only (invariant 4, B1: 50/120/200/320/480 ms) | JS durations in components = raw motion values | | Voice / call room (demo) | browser Web Speech API + local loopback adapter, no package | `livekit-client` | WS14 NOT: no LiveKit product wiring; adapters sit behind provider interfaces | product wiring is out of scope | ## Notes on versions - `@tanstack/react-table`: npm latest is `9.3.1`, but the scaffold pins `8.21.3` exactly. A major jump would break the shadcn data-table recipe and the `ddx-tanstack-table` skill. Keep 8. - `@hookform/resolvers`: npm latest is `6.0.0`; the scaffold ships `^5.9.1`, which has `standardSchemaResolver`. Keep 5 (a major bump needs its own ADR). - `react-markdown` and `sonner` are banned names: no task may install them (AC14.4, toast ban in `rules/shared/dudoxx-design-system.md`). ## APPROVED DEPENDENCY TABLE Summary view (package | app | version source). The binding copy, with exact ranges, dep/dev kind, the full scaffold baseline and the removed packages, is [ADR 0005 §Approved dependency table](/en/docs/adr/0005-frameworks#approved-dependency-table). If the two ever disagree, ADR 0005 wins. | Package | App | Version source | |---|---|---| | `next` / `react` / `react-dom` | ddx-web | VERSIONS.md `next16` / `react19` | | `typescript` | all (ddx-api via TS 6 alias for build) | VERSIONS.md `ts7` | | `tailwindcss`, `@tailwindcss/postcss` | ddx-web | VERSIONS.md `tw4` | | `next-intl` | ddx-web | VERSIONS.md `nextintl4` | | `@tanstack/react-query` (+ devtools) | ddx-web | VERSIONS.md `tanstack5` | | `zod` | ddx-web, ddx-api, contracts | VERSIONS.md `zod4` | | `better-auth` | ddx-web (client), ddx-api (server) | VERSIONS.md `betterauth1` | | `@nestjs/*` | ddx-api | VERSIONS.md `nest12` + create-nestjs baseline | | `@prisma/client`, `prisma`, `@prisma/adapter-pg` | ddx-api | VERSIONS.md `prisma7` | | `pg`, `@types/pg` | ddx-api | npm view 2026-10-23 | | `@aws-sdk/client-s3`, `@aws-sdk/s3-request-presigner` | ddx-api | npm view 2026-10-23 | | `class-variance-authority`, `clsx`, `tailwind-merge` | ddx-web | create-nextjs baseline | | `@tanstack/react-table` (8.21.3 exact) | ddx-web | create-nextjs baseline | | `@tanstack/react-virtual` | ddx-web | npm view 2026-10-23 | | `recharts` | ddx-web | npm view 2026-10-23 | | `embla-carousel-react` | ddx-web | npm view 2026-10-23 | | `@tiptap/react`, `@tiptap/pm`, `@tiptap/starter-kit` | ddx-web | npm view 2026-10-23 | | `streamdown` | ddx-web | npm view 2026-10-23 | | `pdfjs-dist` | ddx-web | npm view 2026-10-23 | | `@react-pdf/renderer` | ddx-web | npm view 2026-10-23 | | `@dnd-kit/core`, `@dnd-kit/sortable`, `@dnd-kit/utilities` | ddx-web | npm view 2026-10-23 | | `react-hook-form`, `@hookform/resolvers`, `@standard-schema/spec` | ddx-web | create-nextjs baseline | | `date-fns`, `react-day-picker` | ddx-web | create-nextjs baseline | | `next-themes`, `lucide-react`, `cmdk`, `server-only` | ddx-web | create-nextjs baseline | | `jose` | ddx-web | npm view 2026-10-23 | | `@ddx/contracts` | ddx-web, ddx-api | workspace package |
Question (BRIEF.md RQ5, G6.1): which libraries beyond shadcn/ui earn a place for the variant API, data grid, charts, carousel, DI container, rich text, markdown, PDF, drag and drop, forms and dates? Evidence: a comparison table with one pick and one rejected option each.
Answer: one library per concern, listed below. The decision and the frozen install list are in . Task 009 installs that list once. No other dependency may be added without a new ADR (plan invariant 8).
~/.claude/ddx-topic-flows/VERSIONS.md (verified 2026-10-10).~/.claude/skills/create-nextjs/templates/package.json (what the scaffold ships).npm view <pkg> version on 2026-10-23 for every package outside VERSIONS.md.findings/hms-pattern-audit/components.md §6 (HMS runs 2 markdown engines,
3 PDF viewers, 5 TipTap editors, zodResolver in 21 files vs mandated standardSchemaResolver).@tanstack/react-table: npm latest is 9.3.1, but the scaffold pins 8.21.3 exactly. A
major jump would break the shadcn data-table recipe and the ddx-tanstack-table skill. Keep 8.@hookform/resolvers: npm latest is 6.0.0; the scaffold ships ^5.9.1, which has
standardSchemaResolver. Keep 5 (a major bump needs its own ADR).react-markdown and sonner are banned names: no task may install them (AC14.4, toast ban
in rules/shared/dudoxx-design-system.md).Summary view (package | app | version source). The binding copy, with exact ranges, dep/dev kind, the full scaffold baseline and the removed packages, is . If the two ever disagree, ADR 0005 wins.
adr/
deploy/
research/