Create @refrakt-md/next adapter package
Build the Next.js framework adapter. Uses React Server Components + renderToHtml() for zero-hydration content rendering, with a thin client component for behavior initialization.
Acceptance Criteria
packages/next/package exists with correctpackage.json(peer depnext@^14.0.0 || ^15.0.0)RefraktContentServer Component renders viarenderToHtml()+dangerouslySetInnerHTML(no'use client')BehaviorInitClient Component ('use client') initializes behaviors viauseEffect, cleans up on unmount, re-initializes on route changemetadata.tshelper transforms page SEO data into Next.jsMetadataobjects forgenerateMetadata()loader.tswrapsloadContent()for Next.js patterns (caching, revalidation)- Content loading works via
generateStaticParams()+ async Server Component - CSS injection works via
import '@refrakt-md/lumina'in rootapp/layout.tsx - Lumina Next.js adapter exports theme config + types
- Custom elements (
rf-*) render correctly via raw HTML string (bypasses React's custom element issues) - Example site renders core runes, layouts, behaviors, and web components correctly
- Adapter documentation page at
site/content/docs/adapters/nextjs.mdwith installation, project structure, configuration, code examples (RefraktContent server component, BehaviorInit client component, generateMetadata helper, generateStaticParams, CSS import, layout setup), and getting-started guide matching the depth of existing SvelteKit adapter docs
Approach
The key insight is that renderToHtml() produces complete HTML strings, and RSC can inject them via dangerouslySetInnerHTML with zero hydration cost. This sidesteps all React custom element issues since React never processes the rf-* elements as components.
Behaviors need a separate 'use client' component since they require DOM access. This component renders nothing (return null) and manages behavior lifecycle via useEffect.
No custom HMR in Phase 1 — rely on Next.js dev server defaults. Custom Webpack/Turbopack plugin for content HMR is a future optimization.
Dependencies
- Extract shared utilities from @refrakt-md/svelte to @refrakt-md/transform (shared utility extraction)
References
- Framework Adapter System (Phase 3)
- Framework Readiness Investigation: Next.js, Eleventy, Nuxt (Next.js section)
Resolution
Completed: 2026-04-04
Branch: claude/implement-spec-030-F0LFn
What was done
- Created
packages/next/with RefraktContent server component, BehaviorInit client component, buildMetadata helper - Separate ./client export for tree-shaking (client code stays out of server bundles)
- Uses moduleResolution: bundler in tsconfig for Next.js compatibility
- Lumina Next.js adapter at
packages/lumina/next/index.ts - Docs page at
site/content/docs/adapters/nextjs.md
Notes
- RefraktContent uses dangerouslySetInnerHTML — zero hydration cost
- BehaviorInit manages lifecycle via useEffect, re-inits on pathname change
- hasInteractiveRunes uses getBehaviorNames() from @refrakt-md/behaviors registry
Relationships
History
- 59ded4aResolution recorded
- f262d7bsource+ADR-002,SPEC-030
- 4765c91statusready→done
- 11e81a8milestone+v1.0.0
- 982a9db
- + Adapter documentation page at `site/content/docs/adapters/nextjs.md` with installation, project structure, configuration, code examples (RefraktContent server component, BehaviorInit client component, generateMetadata helper, generateStaticParams, CSS import, layout setup), and getting-started guide matching the depth of existing SvelteKit adapter docs
- ead9531Created (ready, medium, moderate, frameworks, nextjs)