Future evolution toward a Nuxt 4 module
The current phase publishes QForm Builder as a Nuxt Layer npm package.
The next natural step is to create a real Nuxt 4 module:
@vevedh/nuxt-qform-builderDifference between layer and module
| Topic | Nuxt Layer | Nuxt Module |
|---|---|---|
| Fast publication | excellent | medium |
| Explicit options | limited | excellent |
| Runtime registration | implicit | controlled |
| Host app pollution risk | medium | low |
| Long-term product packaging | good | excellent |
Why not convert immediately?
The current project already works as a layer. Converting too early would add complexity before the public component contract is fully stabilized.
Target module structure
nuxt-qform-builder/
├── src/
│ ├── module.ts
│ └── runtime/
│ ├── components/
│ ├── composables/
│ ├── constants/
│ ├── stores/
│ ├── types/
│ └── utils/
├── playground/
├── docs/
└── package.jsonTarget options
export default defineNuxtConfig({
modules: ['@vevedh/nuxt-qform-builder'],
qformBuilder: {
prefix: '',
installPinia: true,
installFormKit: true,
installQuasar: true,
injectCss: true,
},
})Target module.ts example
import {
addComponentsDir,
addImportsDir,
createResolver,
defineNuxtModule,
installModule,
} from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: '@vevedh/nuxt-qform-builder',
configKey: 'qformBuilder',
},
defaults: {
prefix: '',
installPinia: true,
installFormKit: true,
installQuasar: true,
injectCss: true,
},
async setup(options, nuxt) {
const resolver = createResolver(import.meta.url)
if (options.installPinia) await installModule('@pinia/nuxt')
if (options.installFormKit) await installModule('@formkit/nuxt')
if (options.installQuasar) await installModule('nuxt-quasar-ui')
addComponentsDir({
path: resolver.resolve('./runtime/components'),
prefix: options.prefix,
pathPrefix: false,
global: true,
})
addImportsDir(resolver.resolve('./runtime/composables'))
addImportsDir(resolver.resolve('./runtime/stores'))
if (options.injectCss) {
nuxt.options.css.push(resolver.resolve('./runtime/assets/scss/index.scss'))
}
},
})Refactors required before the module
1. Stabilize internal imports
Avoid host-app aliases such as ~/... in published runtime code. Prefer relative imports or module-specific aliases.
Potential future aliases:
#qform-builder/types
#qform-builder/runtime2. Export public types
The public type contract must remain stable:
import type { FormBuilderSchema } from '@vevedh/qform-builder-layer/types'3. Make the catalog extensible
The future module should allow custom fields, panels and groups.
4. Separate builder and viewer
A future host app should be able to install only the viewer if it does not need the visual builder.
Module roadmap
Phase M1 — minimal module packaging
Move runtime code under src/runtime and register components with Nuxt Kit.
Phase M2 — configurable options
Add options for prefix, Quasar installation, FormKit installation, CSS injection and component groups.
Phase M3 — Vueform Builder parity
Add advanced conditions, validation, templates, theme builder and extensibility points.
Convention to keep
The Community layer remains the stable base. Pro and Studio features should be delivered as separate packages.