Primeros pasos
El objetivo soportado es Nuxt 4 con el módulo comunitario nuxt-quasar-ui.
Versiones revisadas el 21 oct 2026: nuxt 4.6.2, nuxt-quasar-ui 3.1.2, quasar 2.35.2, @quasar/extras 2.1.0, @nuxtjs/i18n 10.6.0.
Instalación
npx nuxi@latest module add quasar # installs and registers nuxt-quasar-ui
npm i quasar @quasar/extras
npm i -D sass # required when sassVariables points at a file
npx nuxi@latest module add i18n # @nuxtjs/i18n, see Locales
npm i -D @types/node # nuxt.config.ts imports node:url
npm i -D typescript@^6 vue-tsc # only for `nuxi typecheck`; vue-tsc 3.3 can't load TypeScript 7Tokens
Copia tokens/ del repositorio del sistema de diseño a la raíz del proyecto. No edites las copias; actualízalas desde el repositorio.
my-app/
├─ app/
│ ├─ app.vue
│ ├─ layouts/default.vue # QLayout shell, see 03-patterns/page-layout.md
│ └─ pages/
├─ tokens/
│ ├─ quasar.variables.scss # SCSS tokens, compiled into Quasar
│ └─ csa.css # --csa-* runtime tokens and .csa-* classes
├─ app.config.ts # optional, runtime Quasar config
└─ nuxt.config.tsNuxt 4 pone el código fuente en app/. tokens/ se queda en la raíz, así que haz referencia a esa carpeta con ~~ (alias de la raíz), no con ~ (que apunta a app/).
¿Haces referencia a tokens/ desde fuera de la raíz del proyecto (monorepo)? Construye ambas rutas con fileURLToPath(new URL('../tokens/…', globalThis._importMeta_.url)) y agrega la carpeta a vite.server.fs.allow, o el servidor de desarrollo responderá 403 de forma intermitente para csa.css.
nuxt.config.ts
import { fileURLToPath } from 'node:url'
export default defineNuxtConfig({
compatibilityDate: '2026-10-01',
modules: ['nuxt-quasar-ui'],
app: {
head: {
link: [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' },
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap',
},
],
},
},
// The module prepends Quasar's CSS, so csa.css loads after it and wins ties.
css: ['~~/tokens/csa.css'],
quasar: {
// Absolute path: the module injects `@use '<path>' as *` into every SCSS block.
sassVariables: fileURLToPath(new URL('./tokens/quasar.variables.scss', globalThis._importMeta_.url)),
plugins: ['Notify', 'Dialog', 'Loading'],
iconSet: 'material-symbols-rounded',
autoIncludeIconSet: false, // the Google Fonts link supplies the icon font; don't bundle it
extras: {
font: null, // no Roboto; Plus Jakarta Sans comes from the Google Fonts link above
},
config: {
dark: false, // see Dark mode below
notify: { // see 02-components/notify.md
position: 'top-right',
timeout: 5000,
actions: [{ icon: 'sym_r_close', color: 'white', round: true, dense: true, 'aria-label': 'Dismiss' }],
},
},
},
})sassVariablesnecesita una ruta absoluta. Con una ruta, el módulo compila Quasar desde el código fuente, así que$primary,$h1y los demás tokens llegan al interior de los componentes.sassdebe estar instalado.- Los colores de marca vienen del archivo SCSS. Deja
config.brandsin definir; crearía una segunda fuente de valores hex. iconSet: 'material-symbols-rounded'hace que los íconos internos de Quasar usen el mismo set.app.head.linkcarga Plus Jakarta Sans y la fuente de iconos desde Google Fonts en tiempo de ejecución. La app no incluye archivos de fuente.pluginslista los plugins de Quasar por nombre.NotifyyDialogsostienen el patrón Feedback.
Valores predeterminados de componentes
nuxt-quasar-ui admite props predeterminadas por componente mediante quasar.components.defaults. Es la forma aprobada de aplicar las convenciones de componentes; no hay componentes wrapper.
quasar: {
components: {
defaults: {
QBtn: { noCaps: true, unelevated: true },
QCard: { flat: true, bordered: true },
QInput: { outlined: true },
QSelect: { outlined: true },
QTable: { flat: true, bordered: true },
QTabs: {
noCaps: true,
align: 'left',
breakpoint: 0,
narrowIndicator: true,
activeColor: 'primary',
indicatorColor: 'primary',
},
},
},
},Modo oscuro
El modo oscuro es el plugin Dark de Quasar. Activa body--dark en <body>, lo que cambia los valores --csa-* de csa.css y los estilos oscuros propios de Quasar.
<!-- app/components/DarkToggle.vue -->
<script setup lang="ts">
const $q = useQuasar()
const pref = useCookie<boolean>('csa-dark', { default: () => false })
$q.dark.set(pref.value) // runs on the server too, so SSR HTML has the right body class
function toggle() {
$q.dark.toggle()
pref.value = $q.dark.isActive
}
</script>
<template>
<!-- Toggle button: fixed name, state in aria-pressed (WCAG 4.1.2). -->
<q-btn flat round no-caps :icon="$q.dark.isActive ? 'sym_r_light_mode' : 'sym_r_dark_mode'"
aria-label="Dark mode" :aria-pressed="$q.dark.isActive ? 'true' : 'false'" @click="toggle" />
</template>Móntalo una vez (en el encabezado) o mueve la llamada a set a app.vue para que se ejecute en cada solicitud. La cookie evita el destello claro que dark: 'auto' produce bajo SSR a quienes prefieren el modo oscuro.
Locales
@nuxtjs/i18n sirve inglés en / y español (México) en /es-mx. Los mensajes viven en i18n/locales/; los textos propios de los componentes de Quasar vienen de su paquete de idioma y cambian con el Locale.
Verificación
Ejecuta desde la raíz de la aplicación, en este orden. npm run a11y debe reportar cero violaciones.
npx nuxi typecheck
npm run build
npx nuxi dev --port 3457 # dev server; a11y expects this port
npm run a11y # axe + structure + keyboard; needs the dev serverGuía completa, con notas sobre SSR y un apéndice de Quasar CLI: docs/04-setup-nuxt.md en el repositorio del sistema de diseño.