Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,399 changes: 1,350 additions & 49 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions rsbuild/tanstack-start/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
node_modules
package-lock.json
yarn.lock

.DS_Store
.cache
.env
.vercel
.output
.nitro
/build/
/api/
/server/build
/public/build# Sentry Config File
.env.sentry-build-plugin
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
.tanstack
36 changes: 36 additions & 0 deletions rsbuild/tanstack-start/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# TanStack Start - Basic Example

This is the basic TanStack Start example, demonstrating the fundamentals of building applications with TanStack Router and TanStack Start.

- [TanStack Router Docs](https://tanstack.com/router)

It's deployed automagically with Netlify!

- [Netlify](https://netlify.com/)

## Start a new project based on this example

To start a new project based on this example, run:

```sh
npx gitpick TanStack/router/tree/main/examples/react/start-basic start-basic
```

## Getting Started

From your terminal:

```sh
pnpm install
pnpm dev
```

This starts your app in development mode, rebuilding assets on file changes.

## Build

To build the app for production:

```sh
pnpm build
```
33 changes: 33 additions & 0 deletions rsbuild/tanstack-start/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "tanstack-start-example-rscs",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"dev": "rsbuild dev",
"build": "rsbuild build && tsc --noEmit",
"start": "node server.js"
},
"dependencies": {
"@tanstack/react-router": "^1.170.11",
"@tanstack/react-router-devtools": "^1.167.0",
"@tanstack/react-start": "^1.168.19",
"dexie": "^4.0.10",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"tailwind-merge": "^3.6.0",
"zod": "^4.4.3",
"zustand": "^5.0.10"
},
"devDependencies": {
"@rsbuild/core": "^2.0.9",
"@rsbuild/plugin-react": "^2.0.0",
"@rsbuild/plugin-tailwindcss": "^2.0.1",
"@types/node": "22.10.2",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"nitro": "npm:nitro-nightly@latest",
"tailwindcss": "^4.1.18",
"typescript": "^5.7.2"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added rsbuild/tanstack-start/public/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added rsbuild/tanstack-start/public/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added rsbuild/tanstack-start/public/favicon.ico
Binary file not shown.
Binary file added rsbuild/tanstack-start/public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions rsbuild/tanstack-start/public/site.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
23 changes: 23 additions & 0 deletions rsbuild/tanstack-start/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { pluginTailwindcss } from '@rsbuild/plugin-tailwindcss';
import { tanstackStart } from '@tanstack/react-start/plugin/rsbuild';

export default defineConfig({
mode: 'development',
source: {
include: [/[\\/]node_modules[\\/]/],
},
server: {
port: 3000,
},
plugins: [
pluginReact(),
pluginTailwindcss(),
tanstackStart({
rsc: {
enabled: true,
},
}),
],
});
54 changes: 54 additions & 0 deletions rsbuild/tanstack-start/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import fs from 'node:fs';
import path from 'node:path';
import { spawn } from 'node:child_process';
import { pathToFileURL } from 'node:url';

const distDir = process.env.E2E_DIST_DIR || 'dist';

function resolveDistClientDir() {
return path.resolve(distDir, 'client');
}

function resolveDistServerEntryPath() {
const serverJsPath = path.resolve(distDir, 'server', 'server.js');
if (fs.existsSync(serverJsPath)) {
return serverJsPath;
}

const indexJsPath = path.resolve(distDir, 'server', 'index.js');
if (fs.existsSync(indexJsPath)) {
return indexJsPath;
}

return serverJsPath;
}

export function resolveStartCommand() {
const distClientDir = resolveDistClientDir();
const distServerEntryPath = resolveDistServerEntryPath();
return `srvx --prod -s ${JSON.stringify(distClientDir)} ${JSON.stringify(distServerEntryPath)}`;
}

export function start() {
const child = spawn(
'srvx',
['--prod', '-s', resolveDistClientDir(), resolveDistServerEntryPath()],
{
stdio: 'inherit',
shell: process.platform === 'win32',
},
);

child.on('exit', (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
return;
}

process.exit(code ?? 0);
});
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
start();
}
129 changes: 129 additions & 0 deletions rsbuild/tanstack-start/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { useState } from 'react';
import { Link, Outlet, useRouterState } from '@tanstack/react-router';

const navItems = [
{ path: '/', label: 'Home', description: 'Overview of all demos' },
{
path: '/pokemon-rsc',
label: 'Pokemon RSC',
description: 'Async server components',
},
{
path: '/e-commerce',
label: 'eCommerce Demo',
description: 'Composite RSC pattern',
},
{
path: '/low-level-api',
label: 'Low-Level API',
description: 'RSC primitives',
},
];

export function Layout() {
const [sidebarOpen, setSidebarOpen] = useState(false);
const routerState = useRouterState();
const currentPath = routerState.location.pathname;

return (
<div className="min-h-screen bg-gray-100 flex flex-col">
{/* Top Navigation Bar */}
<nav className="bg-white shadow-sm border-b border-gray-200 sticky top-0 z-40">
<div className="max-w-6xl mx-auto px-4">
<div className="flex items-center justify-between h-14">
<div className="flex items-center gap-3">
<button
onClick={() => setSidebarOpen(!sidebarOpen)}
className="p-2 rounded-lg hover:bg-gray-100 transition-colors"
aria-label="Toggle navigation menu"
>
<svg
className="w-6 h-6 text-gray-700"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
{sidebarOpen ? (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
)}
</svg>
</button>
<Link to="/" className="flex items-center gap-2">
<span className="text-xl font-bold text-gray-900">TanStack RSC Examples</span>
</Link>
</div>
</div>
</div>
</nav>

<div className="flex flex-1">
{/* Sidebar Overlay */}
{sidebarOpen && (
<div
className="fixed inset-0 bg-black/20 z-30 lg:hidden"
onClick={() => setSidebarOpen(false)}
/>
)}

{/* Sidebar */}
<aside
className={`fixed lg:sticky top-14 left-0 h-[calc(100vh-3.5rem)] w-64 bg-white border-r border-gray-200 z-40 transform transition-transform duration-200 ease-in-out ${
sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'
}`}
>
<nav className="p-4 space-y-1">
{navItems.map((item) => (
<Link
key={item.path}
to={item.path}
onClick={() => setSidebarOpen(false)}
className={`block px-4 py-3 rounded-lg transition-colors ${
currentPath === item.path
? 'bg-indigo-50 text-indigo-700 border-l-4 border-indigo-500'
: 'text-gray-700 hover:bg-gray-50'
}`}
>
<div className="font-medium">{item.label}</div>
<div className="text-xs text-gray-500 mt-0.5">{item.description}</div>
</Link>
))}
</nav>
</aside>

{/* Main Content */}
<main className="flex-1 min-w-0">
<Outlet />

{/* Legend Footer */}
<footer className="mt-12 py-8 border-t border-gray-200 bg-white">
<div className="max-w-4xl mx-auto px-4">
<div className="flex flex-wrap gap-6 justify-center">
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded border-4 border-solid border-blue-500" />
<span className="text-gray-600 font-medium">Server Component</span>
</div>
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded border-4 border-dashed border-green-500" />
<span className="text-gray-600 font-medium">Client Component</span>
</div>
</div>
<p className="text-center text-gray-400 text-sm mt-4">TanStack Start RSC Examples</p>
</div>
</footer>
</main>
</div>
</div>
);
}
Loading
Loading