diff --git a/ui-v2/package-lock.json b/ui-v2/package-lock.json
index 0dce47f4e3..fbde466228 100644
--- a/ui-v2/package-lock.json
+++ b/ui-v2/package-lock.json
@@ -8,6 +8,8 @@
"name": "goose-v2",
"version": "1.0.0",
"dependencies": {
+ "@tanstack/react-router": "^1.120.5",
+ "@tanstack/router": "^0.0.1-beta.53",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
@@ -358,7 +360,6 @@
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
"integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -2965,6 +2966,124 @@
"tailwindcss": "4.1.7"
}
},
+ "node_modules/@tanstack/history": {
+ "version": "1.115.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.115.0.tgz",
+ "integrity": "sha512-K7JJNrRVvyjAVnbXOH2XLRhFXDkeP54Kt2P4FR1Kl2KDGlIbkua5VqZQD2rot3qaDrpufyUa63nuLai1kOLTsQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/react-router": {
+ "version": "1.120.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.120.5.tgz",
+ "integrity": "sha512-A+YRftGwAeFBxa8DF5ujNYqkSEbjCa1KjxDNYr+jWj16jjTxrz/XqgOJCv5ZfbAqqqOa3yLYoQbWa7OGz5jHuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/history": "1.115.0",
+ "@tanstack/react-store": "^0.7.0",
+ "@tanstack/router-core": "1.120.5",
+ "jsesc": "^3.1.0",
+ "tiny-invariant": "^1.3.3",
+ "tiny-warning": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0 || >=19.0.0",
+ "react-dom": ">=18.0.0 || >=19.0.0"
+ }
+ },
+ "node_modules/@tanstack/react-store": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.7.0.tgz",
+ "integrity": "sha512-S/Rq17HaGOk+tQHV/yrePMnG1xbsKZIl/VsNWnNXt4XW+tTY8dTlvpJH2ZQ3GRALsusG5K6Q3unAGJ2pd9W/Ng==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/store": "0.7.0",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tanstack/router": {
+ "version": "0.0.1-beta.53",
+ "resolved": "https://registry.npmjs.org/@tanstack/router/-/router-0.0.1-beta.53.tgz",
+ "integrity": "sha512-nX1avh939ufOCoXhJ5wihX/ft6sn50ARrj4FAhRYn50KKzo9fXsYSmPyVgqVdW0hJ4n9XXKIMkwwpzEhLQmqrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.16.7",
+ "@tanstack/store": "0.0.1-beta.52",
+ "tiny-invariant": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/router-core": {
+ "version": "1.120.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.120.5.tgz",
+ "integrity": "sha512-IXLNv3j7rpTL/YNCWHijZgrnxFuvD4Nz/nUiGSak4x5BKzlnuZEso81xFcIuczVrEW72NxZv8IfzpR5M5Tuc0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/history": "1.115.0",
+ "@tanstack/store": "^0.7.0",
+ "tiny-invariant": "^1.3.3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/router/node_modules/@tanstack/store": {
+ "version": "0.0.1-beta.52",
+ "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.0.1-beta.52.tgz",
+ "integrity": "sha512-3/5XqeG09sCJnakHpq8qgXjdVpm97aITbi1wfbjLGXdVsss62zpJAvc4vL8ccHf+J/OmoS4dJTNuEZ0alywZtg==",
+ "license": "MIT",
+ "dependencies": {
+ "immer": "^9.0.15"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/store": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.0.tgz",
+ "integrity": "sha512-CNIhdoUsmD2NolYuaIs8VfWM467RK6oIBAW4nPEKZhg1smZ+/CwtCdpURgp7nxSqOaV9oKkzdWD80+bC66F/Jg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
"node_modules/@testing-library/dom": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
@@ -8200,6 +8319,16 @@
"node": ">= 4"
}
},
+ "node_modules/immer": {
+ "version": "9.0.21",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
+ "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -8995,7 +9124,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
@@ -11808,7 +11936,6 @@
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "dev": true,
"license": "MIT"
},
"node_modules/regexp.prototype.flags": {
@@ -13581,6 +13708,18 @@
"license": "MIT",
"optional": true
},
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "license": "MIT"
+ },
+ "node_modules/tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
+ "license": "MIT"
+ },
"node_modules/tinybench": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
@@ -14139,6 +14278,15 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/username": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/username/-/username-5.1.0.tgz",
diff --git a/ui-v2/package.json b/ui-v2/package.json
index 7c82046e96..5e9eeda7ba 100644
--- a/ui-v2/package.json
+++ b/ui-v2/package.json
@@ -32,6 +32,8 @@
"prepare": "cd ../.. && husky install"
},
"dependencies": {
+ "@tanstack/react-router": "^1.120.5",
+ "@tanstack/router": "^0.0.1-beta.53",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
diff --git a/ui-v2/playwright.config.ts b/ui-v2/playwright.config.ts
index 0c7e3a3148..ce73727bd9 100644
--- a/ui-v2/playwright.config.ts
+++ b/ui-v2/playwright.config.ts
@@ -25,4 +25,4 @@ export default defineConfig({
timeout: 15000, // Increase expect timeout
},
reporter: [['html'], ['list']],
-});
\ No newline at end of file
+});
diff --git a/ui-v2/src/App.tsx b/ui-v2/src/App.tsx
index 456645634e..fc11393ec7 100644
--- a/ui-v2/src/App.tsx
+++ b/ui-v2/src/App.tsx
@@ -1,5 +1,7 @@
import React, { Suspense } from 'react';
+import { Outlet } from '@tanstack/react-router';
+
import GooseLogo from './components/GooseLogo';
import SuspenseLoader from './components/SuspenseLoader';
@@ -7,13 +9,14 @@ const App: React.FC = (): React.ReactElement => {
return (
An AI assistant for developers
+