Nuxt 4 Integration
Use gp-grid in Nuxt 4 with global styles, SSR-safe rendering, server data sources, optional client-only rendering, and stable grid sizing for production apps.
gp-grid works with Nuxt 4 through the @gp-grid/vue package. The component is
SSR-safe: it renders its initial structure on the server and starts DOM
measurement, event listeners, and Web Workers only after it mounts in the
browser.
Installation
Install the Vue package:
pnpm add @gp-grid/vueRegister the stylesheet globally in nuxt.config.ts:
export default defineNuxtConfig({
css: ["@gp-grid/vue/dist/styles.css"],
});No Nuxt module or Vite transpilation configuration is required.
Basic Usage
Nuxt 4 places application pages under app/pages by default:
<!-- app/pages/grid.vue -->
<script setup lang="ts">
import { GpGrid, type ColumnDefinition } from "@gp-grid/vue";
interface Person {
id: number;
name: string;
}
const columns: ColumnDefinition[] = [
{ field: "id", cellDataType: "number", width: 80, headerName: "ID" },
{ field: "name", cellDataType: "text", width: 200, headerName: "Name" },
];
const { data } = await useFetch<Person[]>("/api/users", {
default: () => [],
});
</script>
<template>
<div style="width: 100%; height: 500px">
<GpGrid
:columns="columns"
:row-data="data"
:row-height="36"
:initial-height="500"
/>
</div>
</template>The parent must have an explicit height because the grid fills its container.
initial-width and initial-height can provide stable dimensions for the
server render; after hydration, ResizeObserver measures the actual container.
SSR and Client-Only Rendering
<ClientOnly> is not required for the GpGrid component. Use it when the grid
has no useful server-rendered content, or when its surrounding setup depends on
browser-only APIs:
<template>
<ClientOnly>
<div style="width: 100%; height: 500px">
<GpGrid :columns="columns" :row-data="rows" :row-height="36" />
</div>
<template #fallback>
<div style="width: 100%; height: 500px" aria-busy="true">
Loading grid...
</div>
</template>
</ClientOnly>
</template>For a reusable client-only wrapper, place the grid in a component whose name
ends in .client.vue, such as app/components/UserGrid.client.vue.
Client Data Sources During SSR
Passing row-data is the simplest SSR-safe option because GpGrid creates its
client data source after mounting.
If you create a client data source in <script setup>, disable Web Workers for
the server-rendered instance:
<script setup lang="ts">
import {
GpGrid,
createClientDataSource,
type ColumnDefinition,
} from "@gp-grid/vue";
const columns: ColumnDefinition[] = [
{ field: "id", cellDataType: "number", width: 80 },
{ field: "name", cellDataType: "text", width: 200 },
];
const rows = [
{ id: 1, name: "Giovanni" },
{ id: 2, name: "Luca" },
];
const dataSource = createClientDataSource(rows, { useWorker: false });
</script>
<template>
<div style="height: 500px">
<GpGrid
:columns="columns"
:data-source="dataSource"
:row-height="36"
/>
</div>
</template>To retain worker-backed sorting, construct the data source inside a
.client.vue component so its setup runs only in the browser.
Server-Side Data with API Routes
For large datasets, connect the grid to a Nuxt server route with
createServerDataSource.
API Route
// server/api/grid-data.post.ts
import { defineEventHandler, readBody } from "h3";
export default defineEventHandler(async (event) => {
const { range, sort, filter } = await readBody(event);
// Query your database. endRow is exclusive.
const results = await db.query({
offset: range.startRow,
limit: range.endRow - range.startRow,
orderBy: sort,
where: filter,
});
return {
rows: results.data,
totalRows: results.total,
};
});Grid Component
<script setup lang="ts">
import {
GpGrid,
createServerDataSource,
type ColumnDefinition,
} from "@gp-grid/vue";
const columns: ColumnDefinition[] = [
{ field: "id", cellDataType: "number", width: 80, headerName: "ID" },
{ field: "name", cellDataType: "text", width: 200, headerName: "Name" },
];
const dataSource = createServerDataSource(async (request) => {
return await $fetch("/api/grid-data", {
method: "POST",
body: request,
});
});
</script>
<template>
<div style="height: 500px">
<GpGrid
:columns="columns"
:data-source="dataSource"
:row-height="36"
/>
</div>
</template>The request includes the visible row range together with the active sort and filter models. Return the requested rows and the total number of matching rows.
Dark Mode with Nuxt Color Mode
When using @nuxtjs/color-mode, pass its state to the dark-mode prop:
<script setup lang="ts">
import { GpGrid } from "@gp-grid/vue";
const colorMode = useColorMode();
const isDark = computed(() => colorMode.value === "dark");
</script>
<template>
<div style="height: 500px">
<GpGrid
:columns="columns"
:row-data="rows"
:row-height="36"
:dark-mode="isDark"
/>
</div>
</template>If the server cannot determine the user's preferred color mode, wrap only the
theme-dependent grid instance in <ClientOnly> or provide a matching fallback
to avoid a visible theme change during hydration.
Basic Usage
Build your first gp-grid table in Vue 3, configuring columns, binding reactive data sources, and exploring the component's reactive prop interface together.
Examples
Browse interactive Vue 3 examples and copy-paste code samples that demonstrate how to wire up gp-grid features inside a typical Vue application stack.