Skip to content
Runtime
Framework

Nuxt

Framework

A module plus a request-scoped runtime plugin for server rendering.

Package
@queryweave/nuxt
Runtime
Nuxt server and client
Depends on
@queryweave/core, @queryweave/vue, @queryweave/vue-router
Requires
nuxt
InstallQuick examplePackage: @queryweave/nuxt

The Nuxt package does two separable things: it configures your application at build time, and it creates one adapter per Vue application instance at runtime. Those live in different entry points because they run at different times.

Terminal window
pnpm add @queryweave/core @queryweave/vue @queryweave/nuxt
nuxt.config.ts
export default defineNuxtConfig({
modules: ["@queryweave/nuxt"],
});

Requires Nuxt 4.

app/pages/products.vue
<script setup lang="ts">
import { defineQueryModel, param } from "@queryweave/core";
const products = defineQueryModel({
search: param.text().optional(),
page: param.integer({ min: 1 }).default(1),
});
// useQueryModel is auto-imported by the module.
const filters = useQueryModel(products);
const search = filters.field("search", { navigation: "replace" });
</script>
<template>
<input v-model="search" type="search" />
<p>Page {{ filters.values.page }}</p>
</template>

No adapter is provided by hand. The module registers a plugin that installs one for you, and the Vue binding finds it through injection.

nuxt.config.ts
export default defineNuxtConfig({
modules: ["@queryweave/nuxt"],
queryweave: {
autoImports: true, // register useQueryModel and provideQueryAdapter — default true
enabled: true, // register the runtime plugin at all — default true
},
});

Setting enabled: false disables the module entirely, which is useful when you want to install an adapter yourself.

This is the part that matters for server rendering.

Nuxt creates a fresh Vue application for every server-rendered request. The QueryWeave plugin creates its adapter inside that application’s setup and installs it on that instance:

// packages/nuxt/src/runtime/plugin.ts, in essence
const adapter = createNuxtQueryAdapter(nuxtApp.$router);
installQueryAdapter(nuxtApp.vueApp, adapter);

Nothing is stored at module scope. A server handling two requests concurrently therefore has two adapters, each bound to its own router, and neither can observe the other.

The adapter is backed by Vue Router, which Nuxt initializes from the request URL on the server and from location on the client. Both sides therefore decode the same query with the same model, and the first client render matches the server’s.

There is no state-transfer payload for query state, and none is needed: the URL is the transfer.

Nuxt mode names the three parts that make hydration safe: the SSR initial query, the Vue Router runtime, and per-request state.

History1 / 1

Products

6 matching

  • Edge runtime handbookactive$59
  • Node.js request toolkitactive$39
  • Nuxt deployment guidearchived$19
  • SSR initial query
  • Vue Router runtime
  • hydration-safe state

One adapter per Vue application instance, which on the server means one per request.

Type a query, press Enter.

Typed state

{
  "page": 1,
  "sort": "created_at",
  "status": "all"
}

Canonical URL

Valid
/products

    For applications that want to wire things themselves:

    import { createNuxtQueryAdapter, installQueryAdapter } from "@queryweave/nuxt/runtime";
    export default defineNuxtPlugin((nuxtApp) => {
    const adapter = createNuxtQueryAdapter(nuxtApp.$router as Router);
    installQueryAdapter(nuxtApp.vueApp, adapter);
    });

    installQueryAdapter accepts any QueryAdapter, so an application can substitute its own — a memory adapter in a test, for example — without leaving the module.

    The plugin also exposes the adapter as $queryWeaveAdapter on the Nuxt app, for code that needs it outside a component.

    • useQueryModel outside a component cannot use injection. Pass an adapter or a runtime explicitly.
    • Static generation decodes the query at request time in the browser; a pre-rendered page has no query of its own.
    • Disabling auto-imports means importing useQueryModel from @queryweave/vue yourself; the behavior is identical.
    • isolatedDeclarations is off for this package alone, because the Nuxt module type cannot be expressed without it. This is recorded in ADR 0007.

    tests/nuxt/module.test.ts and tests/nuxt/registration.test.ts cover module setup and plugin registration. The stronger check is the nuxt consumer fixture, which installs the packed archive into a clean project, builds it, server-renders two concurrent requests with different queries, asserts they do not leak into each other, and then hydrates.