diff --git a/.gitignore b/.gitignore
index 9ad8d4c877..444f5075df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
/.cache
+/.nitro
+/.output
+/.tanstack
/coverage
/dist
/lib
diff --git a/biome.json b/biome.json
index a5a129ee34..2233d3ad96 100644
--- a/biome.json
+++ b/biome.json
@@ -4,6 +4,9 @@
"includes": [
"**",
"!.cache/**/*",
+ "!.nitro/**/*",
+ "!.output/**/*",
+ "!.tanstack/**/*",
"!coverage/**/*",
"!dist/**/*",
"!lib/**/*",
diff --git a/eslint.config.js b/eslint.config.js
index d2513453e8..de7d21d584 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -12,7 +12,7 @@ import testingLibrary from 'eslint-plugin-testing-library';
import markdown from '@eslint/markdown';
export default defineConfig([
- globalIgnores(['.cache', 'coverage', 'dist', 'lib']),
+ globalIgnores(['.cache', '.nitro', '.output', '.tanstack', 'coverage', 'dist', 'lib']),
{
linterOptions: {
diff --git a/index.html b/index.html
deleted file mode 100644
index 8e8135b360..0000000000
--- a/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- React Data Grid
-
-
-
-
-
-
-
diff --git a/package.json b/package.json
index 28d6828837..aa705fa0fe 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
],
"scripts": {
"start": "vite serve --clearScreen false",
- "preview": "vite preview",
+ "preview": "node .output/server/index.mjs",
"build:website": "vite build",
"build": "rolldown -c",
"test": "vitest run",
@@ -58,13 +58,14 @@
"@faker-js/faker": "^9.9.0",
"@ianvs/prettier-plugin-sort-imports": "^4.5.1",
"@linaria/core": "^6.3.0",
- "@tanstack/react-router": "^1.128.0",
- "@tanstack/router-plugin": "^1.128.0",
+ "@tanstack/react-router": "^1.130.12",
+ "@tanstack/react-start": "^1.130.15",
"@types/node": "^24.0.14",
"@types/react": "^19.1.3",
"@types/react-dom": "^19.1.3",
"@typescript-eslint/eslint-plugin": "^8.37.0",
"@typescript-eslint/parser": "^8.37.0",
+ "@vitejs/plugin-react": "^4.7.0",
"@vitejs/plugin-react-oxc": "^0.3.0",
"@vitest/browser": "^3.2.4",
"@vitest/coverage-v8": "^3.2.4",
diff --git a/vite.config.ts b/vite.config.ts
index 00cab27f36..b550fc06c3 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,4 +1,4 @@
-import { tanstackRouter } from '@tanstack/router-plugin/vite';
+import { tanstackStart } from '@tanstack/react-start/plugin/vite';
import react from '@vitejs/plugin-react-oxc';
import wyw from '@wyw-in-js/vite';
import { defineConfig } from 'vite';
@@ -56,12 +56,18 @@ export default defineConfig(({ command, isPreview }) => ({
},
plugins: [
(!isTest || isPreview) &&
- tanstackRouter({
- target: 'react',
- generatedRouteTree: 'website/routeTree.gen.ts',
- routesDirectory: 'website/routes',
- autoCodeSplitting: true,
- verboseFileRoutes: false
+ tanstackStart({
+ customViteReactPlugin: true,
+ tsr: {
+ srcDirectory: 'website',
+ // @ts-expect-error types are not correct
+ autoCodeSplitting: true,
+ verboseFileRoutes: false
+ },
+ prerender: {
+ enabled: true,
+ crawlLinks: true
+ }
}),
react({
exclude: ['./.cache/**/*']
diff --git a/website/root.css b/website/root.css
index 5e21fcd71d..92c76596d5 100644
--- a/website/root.css
+++ b/website/root.css
@@ -16,16 +16,13 @@ body {
}
body {
+ display: grid;
+ grid-template-columns: auto 1fr;
color-scheme: var(--rdg-color-scheme, light dark);
background-color: light-dark(#fff, hsl(0deg 0% 10%));
color: light-dark(#111, #fff);
}
-#root {
- display: grid;
- grid-template-columns: auto 1fr;
-}
-
.fill-grid {
block-size: 100%;
}
diff --git a/website/root.tsx b/website/root.tsx
deleted file mode 100644
index 1f1d9d7e8a..0000000000
--- a/website/root.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import './root.css';
-
-import { StrictMode } from 'react';
-import { createRoot } from 'react-dom/client';
-import {
- createHashHistory,
- createRouter,
- ErrorComponent,
- RouterProvider
-} from '@tanstack/react-router';
-
-import { routeTree } from './routeTree.gen';
-
-const router = createRouter({
- routeTree,
- history: createHashHistory(),
- caseSensitive: true,
- defaultErrorComponent: ErrorComponent,
- defaultNotFoundComponent: NotFound,
- defaultPendingMinMs: 0,
- defaultPreload: 'intent',
- defaultStructuralSharing: true,
- scrollRestoration: true
-});
-
-// Register the router instance for type safety
-declare module '@tanstack/react-router' {
- interface Register {
- router: typeof router;
- }
-}
-
-function NotFound() {
- return 'Nothing to see here';
-}
-
-createRoot(document.getElementById('root')!).render(
-
-
-
-);
diff --git a/website/routeTree.gen.ts b/website/routeTree.gen.ts
index cf9eb65c5b..298150f6d2 100644
--- a/website/routeTree.gen.ts
+++ b/website/routeTree.gen.ts
@@ -9,6 +9,10 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import type { CreateFileRoute, FileRoutesByPath } from '@tanstack/react-router'
+import type {
+ CreateServerFileRoute,
+ ServerFileRoutesByPath,
+} from '@tanstack/react-start/server'
import { Route as rootRouteImport } from './routes/__root'
import { Route as VariableRowHeightRouteImport } from './routes/VariableRowHeight'
@@ -465,6 +469,14 @@ declare module './routes/index' {
FileRoutesByPath['/']['path'],
FileRoutesByPath['/']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/']['parentRoute'],
+ ServerFileRoutesByPath['/']['id'],
+ ServerFileRoutesByPath['/']['path'],
+ ServerFileRoutesByPath['/']['fullPath'],
+ unknown
+ >
}
declare module './routes/AllFeatures' {
const createFileRoute: CreateFileRoute<
@@ -474,6 +486,14 @@ declare module './routes/AllFeatures' {
FileRoutesByPath['/AllFeatures']['path'],
FileRoutesByPath['/AllFeatures']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/AllFeatures']['parentRoute'],
+ ServerFileRoutesByPath['/AllFeatures']['id'],
+ ServerFileRoutesByPath['/AllFeatures']['path'],
+ ServerFileRoutesByPath['/AllFeatures']['fullPath'],
+ unknown
+ >
}
declare module './routes/Animation' {
const createFileRoute: CreateFileRoute<
@@ -483,6 +503,14 @@ declare module './routes/Animation' {
FileRoutesByPath['/Animation']['path'],
FileRoutesByPath['/Animation']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/Animation']['parentRoute'],
+ ServerFileRoutesByPath['/Animation']['id'],
+ ServerFileRoutesByPath['/Animation']['path'],
+ ServerFileRoutesByPath['/Animation']['fullPath'],
+ unknown
+ >
}
declare module './routes/CellNavigation' {
const createFileRoute: CreateFileRoute<
@@ -492,6 +520,14 @@ declare module './routes/CellNavigation' {
FileRoutesByPath['/CellNavigation']['path'],
FileRoutesByPath['/CellNavigation']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/CellNavigation']['parentRoute'],
+ ServerFileRoutesByPath['/CellNavigation']['id'],
+ ServerFileRoutesByPath['/CellNavigation']['path'],
+ ServerFileRoutesByPath['/CellNavigation']['fullPath'],
+ unknown
+ >
}
declare module './routes/ColumnGrouping' {
const createFileRoute: CreateFileRoute<
@@ -501,6 +537,14 @@ declare module './routes/ColumnGrouping' {
FileRoutesByPath['/ColumnGrouping']['path'],
FileRoutesByPath['/ColumnGrouping']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/ColumnGrouping']['parentRoute'],
+ ServerFileRoutesByPath['/ColumnGrouping']['id'],
+ ServerFileRoutesByPath['/ColumnGrouping']['path'],
+ ServerFileRoutesByPath['/ColumnGrouping']['fullPath'],
+ unknown
+ >
}
declare module './routes/ColumnSpanning' {
const createFileRoute: CreateFileRoute<
@@ -510,6 +554,14 @@ declare module './routes/ColumnSpanning' {
FileRoutesByPath['/ColumnSpanning']['path'],
FileRoutesByPath['/ColumnSpanning']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/ColumnSpanning']['parentRoute'],
+ ServerFileRoutesByPath['/ColumnSpanning']['id'],
+ ServerFileRoutesByPath['/ColumnSpanning']['path'],
+ ServerFileRoutesByPath['/ColumnSpanning']['fullPath'],
+ unknown
+ >
}
declare module './routes/ColumnsReordering' {
const createFileRoute: CreateFileRoute<
@@ -519,6 +571,14 @@ declare module './routes/ColumnsReordering' {
FileRoutesByPath['/ColumnsReordering']['path'],
FileRoutesByPath['/ColumnsReordering']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/ColumnsReordering']['parentRoute'],
+ ServerFileRoutesByPath['/ColumnsReordering']['id'],
+ ServerFileRoutesByPath['/ColumnsReordering']['path'],
+ ServerFileRoutesByPath['/ColumnsReordering']['fullPath'],
+ unknown
+ >
}
declare module './routes/CommonFeatures' {
const createFileRoute: CreateFileRoute<
@@ -528,6 +588,14 @@ declare module './routes/CommonFeatures' {
FileRoutesByPath['/CommonFeatures']['path'],
FileRoutesByPath['/CommonFeatures']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/CommonFeatures']['parentRoute'],
+ ServerFileRoutesByPath['/CommonFeatures']['id'],
+ ServerFileRoutesByPath['/CommonFeatures']['path'],
+ ServerFileRoutesByPath['/CommonFeatures']['fullPath'],
+ unknown
+ >
}
declare module './routes/ContextMenu' {
const createFileRoute: CreateFileRoute<
@@ -537,6 +605,14 @@ declare module './routes/ContextMenu' {
FileRoutesByPath['/ContextMenu']['path'],
FileRoutesByPath['/ContextMenu']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/ContextMenu']['parentRoute'],
+ ServerFileRoutesByPath['/ContextMenu']['id'],
+ ServerFileRoutesByPath['/ContextMenu']['path'],
+ ServerFileRoutesByPath['/ContextMenu']['fullPath'],
+ unknown
+ >
}
declare module './routes/CustomizableRenderers' {
const createFileRoute: CreateFileRoute<
@@ -546,6 +622,14 @@ declare module './routes/CustomizableRenderers' {
FileRoutesByPath['/CustomizableRenderers']['path'],
FileRoutesByPath['/CustomizableRenderers']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/CustomizableRenderers']['parentRoute'],
+ ServerFileRoutesByPath['/CustomizableRenderers']['id'],
+ ServerFileRoutesByPath['/CustomizableRenderers']['path'],
+ ServerFileRoutesByPath['/CustomizableRenderers']['fullPath'],
+ unknown
+ >
}
declare module './routes/HeaderFilters' {
const createFileRoute: CreateFileRoute<
@@ -555,6 +639,14 @@ declare module './routes/HeaderFilters' {
FileRoutesByPath['/HeaderFilters']['path'],
FileRoutesByPath['/HeaderFilters']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/HeaderFilters']['parentRoute'],
+ ServerFileRoutesByPath['/HeaderFilters']['id'],
+ ServerFileRoutesByPath['/HeaderFilters']['path'],
+ ServerFileRoutesByPath['/HeaderFilters']['fullPath'],
+ unknown
+ >
}
declare module './routes/InfiniteScrolling' {
const createFileRoute: CreateFileRoute<
@@ -564,6 +656,14 @@ declare module './routes/InfiniteScrolling' {
FileRoutesByPath['/InfiniteScrolling']['path'],
FileRoutesByPath['/InfiniteScrolling']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/InfiniteScrolling']['parentRoute'],
+ ServerFileRoutesByPath['/InfiniteScrolling']['id'],
+ ServerFileRoutesByPath['/InfiniteScrolling']['path'],
+ ServerFileRoutesByPath['/InfiniteScrolling']['fullPath'],
+ unknown
+ >
}
declare module './routes/MasterDetail' {
const createFileRoute: CreateFileRoute<
@@ -573,6 +673,14 @@ declare module './routes/MasterDetail' {
FileRoutesByPath['/MasterDetail']['path'],
FileRoutesByPath['/MasterDetail']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/MasterDetail']['parentRoute'],
+ ServerFileRoutesByPath['/MasterDetail']['id'],
+ ServerFileRoutesByPath['/MasterDetail']['path'],
+ ServerFileRoutesByPath['/MasterDetail']['fullPath'],
+ unknown
+ >
}
declare module './routes/MillionCells' {
const createFileRoute: CreateFileRoute<
@@ -582,6 +690,14 @@ declare module './routes/MillionCells' {
FileRoutesByPath['/MillionCells']['path'],
FileRoutesByPath['/MillionCells']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/MillionCells']['parentRoute'],
+ ServerFileRoutesByPath['/MillionCells']['id'],
+ ServerFileRoutesByPath['/MillionCells']['path'],
+ ServerFileRoutesByPath['/MillionCells']['fullPath'],
+ unknown
+ >
}
declare module './routes/NoRows' {
const createFileRoute: CreateFileRoute<
@@ -591,6 +707,14 @@ declare module './routes/NoRows' {
FileRoutesByPath['/NoRows']['path'],
FileRoutesByPath['/NoRows']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/NoRows']['parentRoute'],
+ ServerFileRoutesByPath['/NoRows']['id'],
+ ServerFileRoutesByPath['/NoRows']['path'],
+ ServerFileRoutesByPath['/NoRows']['fullPath'],
+ unknown
+ >
}
declare module './routes/ResizableGrid' {
const createFileRoute: CreateFileRoute<
@@ -600,6 +724,14 @@ declare module './routes/ResizableGrid' {
FileRoutesByPath['/ResizableGrid']['path'],
FileRoutesByPath['/ResizableGrid']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/ResizableGrid']['parentRoute'],
+ ServerFileRoutesByPath['/ResizableGrid']['id'],
+ ServerFileRoutesByPath['/ResizableGrid']['path'],
+ ServerFileRoutesByPath['/ResizableGrid']['fullPath'],
+ unknown
+ >
}
declare module './routes/RowGrouping' {
const createFileRoute: CreateFileRoute<
@@ -609,6 +741,14 @@ declare module './routes/RowGrouping' {
FileRoutesByPath['/RowGrouping']['path'],
FileRoutesByPath['/RowGrouping']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/RowGrouping']['parentRoute'],
+ ServerFileRoutesByPath['/RowGrouping']['id'],
+ ServerFileRoutesByPath['/RowGrouping']['path'],
+ ServerFileRoutesByPath['/RowGrouping']['fullPath'],
+ unknown
+ >
}
declare module './routes/RowsReordering' {
const createFileRoute: CreateFileRoute<
@@ -618,6 +758,14 @@ declare module './routes/RowsReordering' {
FileRoutesByPath['/RowsReordering']['path'],
FileRoutesByPath['/RowsReordering']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/RowsReordering']['parentRoute'],
+ ServerFileRoutesByPath['/RowsReordering']['id'],
+ ServerFileRoutesByPath['/RowsReordering']['path'],
+ ServerFileRoutesByPath['/RowsReordering']['fullPath'],
+ unknown
+ >
}
declare module './routes/ScrollToCell' {
const createFileRoute: CreateFileRoute<
@@ -627,6 +775,14 @@ declare module './routes/ScrollToCell' {
FileRoutesByPath['/ScrollToCell']['path'],
FileRoutesByPath['/ScrollToCell']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/ScrollToCell']['parentRoute'],
+ ServerFileRoutesByPath['/ScrollToCell']['id'],
+ ServerFileRoutesByPath['/ScrollToCell']['path'],
+ ServerFileRoutesByPath['/ScrollToCell']['fullPath'],
+ unknown
+ >
}
declare module './routes/TreeView' {
const createFileRoute: CreateFileRoute<
@@ -636,6 +792,14 @@ declare module './routes/TreeView' {
FileRoutesByPath['/TreeView']['path'],
FileRoutesByPath['/TreeView']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/TreeView']['parentRoute'],
+ ServerFileRoutesByPath['/TreeView']['id'],
+ ServerFileRoutesByPath['/TreeView']['path'],
+ ServerFileRoutesByPath['/TreeView']['fullPath'],
+ unknown
+ >
}
declare module './routes/VariableRowHeight' {
const createFileRoute: CreateFileRoute<
@@ -645,6 +809,14 @@ declare module './routes/VariableRowHeight' {
FileRoutesByPath['/VariableRowHeight']['path'],
FileRoutesByPath['/VariableRowHeight']['fullPath']
>
+
+ const createServerFileRoute: CreateServerFileRoute<
+ ServerFileRoutesByPath['/VariableRowHeight']['parentRoute'],
+ ServerFileRoutesByPath['/VariableRowHeight']['id'],
+ ServerFileRoutesByPath['/VariableRowHeight']['path'],
+ ServerFileRoutesByPath['/VariableRowHeight']['fullPath'],
+ unknown
+ >
}
const rootRouteChildren: RootRouteChildren = {
diff --git a/website/router.tsx b/website/router.tsx
new file mode 100644
index 0000000000..893620de29
--- /dev/null
+++ b/website/router.tsx
@@ -0,0 +1,28 @@
+import { createRouter as createTanStackRouter, ErrorComponent } from '@tanstack/react-router';
+
+import { routeTree } from './routeTree.gen';
+
+export function createRouter() {
+ return createTanStackRouter({
+ basepath: '/react-data-grid/',
+ routeTree,
+ caseSensitive: true,
+ defaultErrorComponent: ErrorComponent,
+ defaultNotFoundComponent: NotFound,
+ defaultPendingMinMs: 0,
+ defaultPreload: 'intent',
+ defaultStructuralSharing: true,
+ scrollRestoration: true
+ });
+}
+
+// Register the router instance for type safety
+declare module '@tanstack/react-router' {
+ interface Register {
+ router: ReturnType;
+ }
+}
+
+function NotFound() {
+ return 'Nothing to see here';
+}
diff --git a/website/routes/__root.tsx b/website/routes/__root.tsx
index 796e87ff3a..e2db03fb8c 100644
--- a/website/routes/__root.tsx
+++ b/website/routes/__root.tsx
@@ -1,5 +1,7 @@
-import { useState } from 'react';
-import { createRootRoute, Outlet } from '@tanstack/react-router';
+import '../root.css';
+
+import { useState, type ReactNode } from 'react';
+import { createRootRoute, HeadContent, Outlet, Scripts } from '@tanstack/react-router';
import { css } from '@linaria/core';
import type { Direction } from '../../src/types';
@@ -7,6 +9,21 @@ import { DirectionContext } from '../directionContext';
import Nav from '../Nav';
export const Route = createRootRoute({
+ head: () => ({
+ meta: [
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1'
+ },
+ {
+ name: 'description',
+ content: 'Feature-rich and customizable data grid React component.'
+ },
+ {
+ title: 'React Data Grid'
+ }
+ ]
+ }),
component: Root
});
@@ -23,11 +40,27 @@ function Root() {
const [direction, setDirection] = useState('ltr');
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ );
+}
+
+function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
+ return (
+
+
+
+
+
+ {children}
+
+
+
);
}
diff --git a/website/routes/index.tsx b/website/routes/index.tsx
index 6191d381ab..6d4f0a6962 100644
--- a/website/routes/index.tsx
+++ b/website/routes/index.tsx
@@ -1,8 +1,7 @@
-import { redirect } from '@tanstack/react-router';
+// import { redirect } from '@tanstack/react-router';
export const Route = createFileRoute({
beforeLoad() {
- // eslint-disable-next-line @typescript-eslint/only-throw-error
- throw redirect({ to: '/CommonFeatures' });
+ // throw redirect({ to: '/CommonFeatures' });
}
});