Skip to content

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.

ts
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 :

txt
app/
├── assets/
├── components/
├── composables/
├── constants/
├── stores/
├── types/
└── utils/

nuxt.config.ts
formkit.config.ts
.playground/

Cette structure permet de partager :

  • les composants FormBuilder et FormViewer ;
  • 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

txt
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.md

Les 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 :

txt
/autonome
/multi-instance
/viewer

nuxt.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.

ts
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 :

ts
ssr: false

Ce choix appartient à l’application hôte.

Pour un usage sûr avec SSR activé, envelopper FormBuilder dans ClientOnly :

vue
<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 :

json
{
  "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 :

json
{
  "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 :

bash
bun install
bun run docs:build
bun run typecheck:nuxt
bun run pack:dry-run

La commande importante avant publication est :

bash
npm pack --dry-run

Elle permet de vérifier exactement les fichiers qui seront publiés.

Publier sur npm

Connexion :

bash
npm login

Publication d’un package scoped public :

bash
npm publish --access public

Le package contient déjà :

json
{
  "publishConfig": {
    "access": "public"
  }
}

Donc la commande suivante suffit aussi dans la majorité des cas :

bash
npm publish

Référence npm : https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/

Installation dans une application Nuxt 4

bash
bun add @vevedh/qform-builder-layer \
  nuxt-quasar-ui @pinia/nuxt @formkit/nuxt \
  quasar @quasar/extras \
  @formkit/core @formkit/i18n @formkit/vue @formkit/utils

Puis :

ts
export default defineNuxtConfig({
  extends: ['@vevedh/qform-builder-layer'],

  compatibilityDate: '2026-05-08'
})

Exemple minimal

vue
<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 :

vue
<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 :

txt
FormBuilder
FormViewer
@vevedh/qform-builder-layer/types

Les 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 :

bash
bun run pack:dry-run

Commandes finales recommandées

bash
bunx nuxi cleanup .playground
bun install
bun run release:doctor
bun run release:publish:dry-run

La publication réelle reste :

bash
npm login
npm publish --access public

QForm Builder — couche Nuxt 4 / Quasar / FormKit réutilisable.