Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

example: tanstack-router spa implementation run by waku #1165

Merged
merged 12 commits into from
Jan 21, 2025
23 changes: 23 additions & 0 deletions examples/52_tanstack-router/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "52_tanstack-router",
"private": true,
"type": "module",
"scripts": {
"dev": "waku dev",
"build": "waku build",
"start": "waku start"
},
"dependencies": {
"@tanstack/react-router": "1.97.3",
"@tanstack/router-devtools": "1.97.3",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-server-dom-webpack": "19.0.0",
"waku": "0.21.16"
},
"devDependencies": {
"@types/react": "19.0.7",
"@types/react-dom": "19.0.3",
"typescript": "5.7.3"
}
}
27 changes: 27 additions & 0 deletions examples/52_tanstack-router/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Router } from './router';

export const App = () => {
return (
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Waku</title>
<script src="https://cdn.tailwindcss.com"></script>
<style type="text/tailwindcss">
{`html {
color-scheme: light dark;
}
* {
@apply border-gray-200 dark:border-gray-800;
}
body {
@apply bg-gray-50 text-gray-950 dark:bg-gray-900 dark:text-gray-200;
}`}
</style>
</head>
<body>
<Router />
</body>
</html>
);
};
11 changes: 11 additions & 0 deletions examples/52_tanstack-router/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { unstable_defineEntries as defineEntries } from 'waku/minimal/server';

export default defineEntries({
handleRequest: async (input, { renderRsc }) => {
if (input.type === 'function') {
const value = await input.fn(...input.args);
return renderRsc({ _value: value });
}
},
handleBuild: () => null,
});
11 changes: 11 additions & 0 deletions examples/52_tanstack-router/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './app';

const rootElement = (
<StrictMode>
<App />
</StrictMode>
);

createRoot(document as any).render(rootElement);
63 changes: 63 additions & 0 deletions examples/52_tanstack-router/src/router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {
Link,
Outlet,
RouterProvider,
createRootRoute,
createRoute,
createRouter,
} from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
import { ServerTime } from './server-time';

const rootRoute = createRootRoute({
component: () => (
<>
<div className="flex gap-2 p-2">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>{' '}
<Link to="/about" className="[&.active]:font-bold">
About
</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
<ServerTime />
</>
),
});

const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: function Index() {
return (
<div className="p-2">
<h3>Welcome Home!</h3>
</div>
);
},
});

const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
component: function About() {
return <div className="p-2">Hello from About!</div>;
},
});

const routeTree = rootRoute.addChildren([indexRoute, aboutRoute]);

const router = createRouter({ routeTree, defaultPreload: 'intent' });

declare module '@tanstack/react-router' {
interface Register {
router: typeof router;
}
}

export const Router = () => {
return <RouterProvider router={router} />;
};
8 changes: 8 additions & 0 deletions examples/52_tanstack-router/src/server-fns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use server';

export const getServerTime = async () => {
// Wait for 1 second
await new Promise((resolve) => setTimeout(resolve, 1000));
// Return the current time
return new Date().toISOString();
};
21 changes: 21 additions & 0 deletions examples/52_tanstack-router/src/server-time.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useState } from 'react';
import { getServerTime } from './server-fns';

export const ServerTime = () => {
const [serverTime, setServerTime] = useState<string | null>(null);

return (
<div>
<p>Server Time: {serverTime}</p>
<button
onClick={async () => {
setServerTime(null);
const serverTime = await getServerTime();
setServerTime(serverTime);
}}
>
Get Server Time
</button>
</div>
);
};
15 changes: 15 additions & 0 deletions examples/52_tanstack-router/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"strict": true,
"target": "esnext",
"downlevelIteration": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"types": ["react/experimental"],
"jsx": "react-jsx"
}
}
10 changes: 10 additions & 0 deletions examples/52_tanstack-router/waku.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from 'waku/config';

export default defineConfig({
middleware: () => [
import('waku/middleware/context'),
import('waku/middleware/dev-server'),
import('waku/middleware/handler'),
import('waku/middleware/fallback'),
],
});
Loading
Loading