Publier QForm Builder comme Nuxt Layer npm
Cette phase transforme QForm Builder en Nuxt Layer publiable sur npm.
L’objectif est de pouvoir installer le package dans une nouvelle application Nuxt 4 ou dans une application Nuxt 4 existante, puis de l’activer avec extends.
export default defineNuxtConfig({
extends: ['@vevedh/qform-builder-layer']
})Référence officielle : https://nuxt.com/docs/4.x/guide/going-further/layers
Pourquoi publier d’abord comme layer ?
Le projet est déjà naturellement structuré comme une couche Nuxt :
app/
├── assets/
├── components/
├── composables/
├── constants/
├── stores/
├── types/
└── utils/
nuxt.config.ts
formkit.config.ts
.playground/Cette structure permet de partager :
- les composants
FormBuilderetFormViewer; - les composants Quasar/FormKit internes ;
- les composables ;
- les stores Pinia ;
- les types TypeScript ;
- les styles SCSS ;
- la configuration Nuxt utile au builder.
Structure retenue pour la phase 1
qform-builder-layer/
├── app/
│ ├── assets/
│ ├── components/
│ ├── composables/
│ ├── constants/
│ ├── stores/
│ ├── types/
│ └── utils/
├── .playground/
│ └── app/
│ ├── app.vue
│ ├── layouts/
│ └── pages/
├── docs/
├── formkit.config.ts
├── nuxt.config.ts
├── package.json
└── README.mdLes pages de démonstration sont volontairement déplacées dans .playground/app/pages.
Elles ne doivent pas être publiées dans le layer runtime, car une application consommatrice ne doit pas recevoir automatiquement les routes de démonstration :
/autonome
/multi-instance
/viewernuxt.config.ts du layer
Le layer doit rester le plus neutre possible.
Il fournit les modules nécessaires, les styles, Quasar et FormKit, mais il ne doit pas imposer de choix globaux dangereux à l’application hôte.
export default defineNuxtConfig({
modules: [
'nuxt-quasar-ui',
'@pinia/nuxt',
'@formkit/nuxt'
],
css: [
'~/assets/scss/index.scss'
],
quasar: {
lang: 'fr',
iconSet: 'material-icons',
plugins: [
'BottomSheet',
'Dialog',
'Loading',
'LoadingBar',
'Notify',
'Dark',
'LocalStorage',
'Platform'
]
}
})Le layer ne doit pas définir :
ssr: falseCe choix appartient à l’application hôte.
Pour un usage sûr avec SSR activé, envelopper FormBuilder dans ClientOnly :
<template>
<ClientOnly>
<FormBuilder
builder-id="admin-contact-builder"
v-model:schema="schema"
v-model:values="values"
/>
</ClientOnly>
</template>FormViewer peut être rendu plus facilement côté runtime, mais il reste recommandé de tester le comportement selon les composants Quasar/FormKit utilisés.
package.json de publication
Le package utilise :
{
"name": "@vevedh/qform-builder-layer",
"main": "./nuxt.config.ts",
"publishConfig": {
"access": "public"
},
"files": [
"app/assets",
"app/components",
"app/composables",
"app/constants",
"app/stores",
"app/types",
"app/types.ts",
"app/utils",
"docs",
"formkit.config.ts",
"nuxt.config.ts",
"README.md",
"LICENSE"
]
}Le champ files est essentiel : il évite de publier .playground, .nuxt, .output, node_modules, les caches et les fichiers de patch internes.
Dépendances peer
QForm Builder est un layer d’intégration. Les dépendances principales sont donc déclarées comme peerDependencies :
{
"peerDependencies": {
"nuxt": "^4.0.0",
"vue": "^3.5.0",
"pinia": "^3.0.0",
"@pinia/nuxt": "^0.11.0",
"quasar": "^2.18.0",
"@quasar/extras": "^1.17.0",
"nuxt-quasar-ui": "^2.1.0",
"@formkit/core": "^1.7.0",
"@formkit/i18n": "^1.7.0",
"@formkit/nuxt": "^1.7.0",
"@formkit/utils": "^1.7.0",
"@formkit/vue": "^1.7.0"
}
}Cela laisse l’application hôte garder la maîtrise de ses versions Nuxt, Vue, Quasar et FormKit.
Tester le package avant publication
Depuis le dépôt du layer :
bun install
bun run docs:build
bun run typecheck:nuxt
bun run pack:dry-runLa commande importante avant publication est :
npm pack --dry-runElle permet de vérifier exactement les fichiers qui seront publiés.
Publier sur npm
Connexion :
npm loginPublication d’un package scoped public :
npm publish --access publicLe package contient déjà :
{
"publishConfig": {
"access": "public"
}
}Donc la commande suivante suffit aussi dans la majorité des cas :
npm publishRéférence npm : https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/
Installation dans une application Nuxt 4
bun add @vevedh/qform-builder-layer \
nuxt-quasar-ui @pinia/nuxt @formkit/nuxt \
quasar @quasar/extras \
@formkit/core @formkit/i18n @formkit/vue @formkit/utilsPuis :
export default defineNuxtConfig({
extends: ['@vevedh/qform-builder-layer'],
compatibilityDate: '2026-05-08'
})Exemple minimal
<script setup lang="ts">
import type { FormKitSchemaDefinition } from '@formkit/core'
type FormBuilderSchema = FormKitSchemaDefinition[]
type FormBuilderValues = Record<string, unknown>
const schema = ref<FormBuilderSchema>([])
const values = ref<FormBuilderValues>({})
</script>
<template>
<ClientOnly>
<FormBuilder
builder-id="contact-form-builder"
v-model:schema="schema"
v-model:values="values"
autosave
storage-key="contact-form-builder"
/>
</ClientOnly>
</template>Bonne pratique
Dans une application métier, ne pas utiliser builder-id="default".
Utiliser une clé stable :
<FormBuilder :builder-id="`workspace-${workspaceId}-form-${formId}`" />Cela garantit l’isolation des stores, de l’historique, de l’autosave et des offsets UI.
Contrat Community finalisé
La phase 1 considère comme stable le contrat suivant :
FormBuilder
FormViewer
@vevedh/qform-builder-layer/typesLes fichiers de démonstration, le contexte projet et les journaux de patch ne sont pas publiés sur npm.
Pour vérifier cette règle :
bun run pack:dry-runCommandes finales recommandées
bunx nuxi cleanup .playground
bun install
bun run release:doctor
bun run release:publish:dry-runLa publication réelle reste :
npm login
npm publish --access public