Evolution to a Nuxt 4 module
The current distribution is an npm Nuxt Layer. The recommended next distribution is a real Nuxt 4 module under a new name, while retaining the layer as a compatibility reference.
Recommended technical name:
@vevedh/nuxt-form-buildernpm and trademark availability must be checked before publication.
Migration decision
The project can start the module phase because the public contract is frozen, FormBuilder and FormViewer are clearly identified, pure engines are exported, an independent host application is built, browser/multi-OS tests exist, and no backend is mandatory.
The module should not be published as stable immediately. The first milestone is a packaging migration without functional changes.
Layer versus module
| Topic | Nuxt Layer | Nuxt 4 module |
|---|---|---|
| Activation | extends | modules |
| Configuration | config merging | typed configKey options |
| Public components | layer scan | explicit registration |
| Auto-imports | inherited directories | Nuxt Kit registration |
| Nuxt dependencies | inherited | moduleDependencies |
| Distribution | layer sources | compiled module/runtime |
| Long-term role | compatibility | primary distribution |
Target structure
packages/nuxt-form-builder/
├── src/
│ ├── module.ts
│ └── runtime/
│ ├── assets/
│ ├── components/
│ ├── composables/
│ ├── constants/
│ ├── stores/
│ ├── types/
│ └── utils/
├── playground/
├── test/
├── docs/
└── package.jsonA multi-package architecture may extract pure engines into qform-core and retain a temporary layer wrapper.
Target options
export interface NuxtFormBuilderModuleOptions {
prefix?: string
locale?: 'fr' | 'en'
injectCss?: boolean
components?: {
builder?: boolean
viewer?: boolean
}
dependencies?: {
pinia?: boolean
formkit?: boolean
quasar?: boolean
unocss?: boolean
}
}Modern module entrypoint
Module dependencies should be declared with moduleDependencies; installModule() is now deprecated in Nuxt Kit.
import {
addComponent,
addImportsDir,
createResolver,
defineNuxtModule,
} from '@nuxt/kit'
export interface NuxtFormBuilderModuleOptions {
prefix?: string
locale?: 'fr' | 'en'
injectCss?: boolean
components?: {
builder?: boolean
viewer?: boolean
}
}
export default defineNuxtModule<NuxtFormBuilderModuleOptions>({
meta: {
name: '@vevedh/nuxt-form-builder',
configKey: 'formBuilder',
compatibility: { nuxt: '^4.0.0' },
},
defaults: {
prefix: '',
locale: 'fr',
injectCss: true,
components: { builder: true, viewer: true },
},
moduleDependencies: {
'@pinia/nuxt': { version: '>=0.11.0' },
'@formkit/nuxt': { version: '>=2.1.0 <3.0.0' },
'nuxt-quasar-ui': { version: '>=2.1.0' },
'@unocss/nuxt': { version: '>=66.0.0' },
},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url)
const runtime = resolver.resolve('./runtime')
const prefix = options.prefix || ''
if (options.components?.builder !== false) {
addComponent({
name: `${prefix}FormBuilder`,
filePath: resolver.resolve(runtime, 'components/FormBuilder.vue'),
})
}
if (options.components?.viewer !== false) {
addComponent({
name: `${prefix}FormViewer`,
filePath: resolver.resolve(runtime, 'components/FormViewer.vue'),
})
}
addImportsDir(resolver.resolve(runtime, 'composables'))
if (options.injectCss !== false) {
nuxt.options.css.push(resolver.resolve(runtime, 'assets/scss/index.scss'))
}
},
})The example illustrates the module boundary; FormKit configuration and internal component registration need a dedicated strategy before publication.
Required refactors
- Replace FormKit adapter imports from layer
#componentswith generated or direct runtime registration. - Replace inherited layer auto-imports with explicit Nuxt Kit registration or direct internal imports.
- Globally register only
FormBuilderandFormViewer; keep 85 internal components private. - Resolve styles and runtime paths through
createResolver(import.meta.url). - Publish compiled module/runtime output and preserve or re-export current public subpaths.
- Test installed tarballs in clean Nuxt applications on SSR, Windows and Linux.
Features already complete
The module migration must preserve rather than redevelop catalog/config panels, conditions, validation, templates, Theme Builder, history, tree, migrations, i18n, accessibility and import/export.
Phase 3 features — Zod/NFZ, CRUD generation, business packs, code export, headless and guided generation — should begin only after module parity.
Module roadmap
- M0: reproducible layer reference, lockfile, remote CI, real screenshots/baselines.
- M1: official module skeleton and runtime migration without feature changes.
- M2: FormKit, Quasar, Pinia, UnoCSS, styles, types and public subpaths.
- M3: prefix, locale, CSS and separate Builder/Viewer options.
- M4: installed-tarball, SSR, Windows/Linux and consumer type tests.
- M5: alpha, real product integration, RC and stable.
Compatibility convention
@vevedh/qform-builder-layer # retained layer distribution
@vevedh/nuxt-form-builder # new module distributionThe module should be a new envelope around the same core, not a functional rewrite.