Skip to content

Commit 6bd9f83

Browse files
committed
docs: add TanStack Start docs
1 parent bd7e28f commit 6bd9f83

4 files changed

Lines changed: 232 additions & 0 deletions

File tree

docs/TanStackStart.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
---
2+
layout: default
3+
title: "TanStack Start Integration"
4+
---
5+
6+
# TanStack Start Integration
7+
8+
[TanStack Start](https://tanstack.com/start) is a full-stack React framework built on top of TanStack Router. React-admin supports [TanStack Router](https://tanstack.com/router/latest) as an alternative to react-router, so you can use react-admin in a TanStack Start application.
9+
10+
## Setting Up TanStack Start
11+
12+
Let's start by creating a new TanStack Start project. Run the following command:
13+
14+
```bash
15+
npm create @tanstack/start@latest
16+
# or
17+
yarn create @tanstack/start
18+
```
19+
20+
This script will ask you for more details about your project. The prompts include:
21+
22+
- What would you like to name your project? (example: `tanstack-admin`)
23+
- Select toolchain
24+
- Select deployment adapter
25+
- What add-ons would you like for your project?
26+
- Would you like an example?
27+
- Initialize git repository
28+
- Install dependencies
29+
30+
For this tutorial, we used the following choices in our local setup: `ESLint` toolchain, `Nitro (agnostic)` deployment adapter, `Query` add-on, and `None` for the example. You can pick different options depending on your needs.
31+
32+
If you want to see the current list of add-ons, run:
33+
34+
```bash
35+
npm create @tanstack/start@latest --list-add-ons
36+
# or
37+
yarn create @tanstack/start --list-add-ons
38+
```
39+
40+
The project structure should look like this:
41+
42+
![TanStack Start project structure](./img/tanstack-structure.png)
43+
44+
## Setting Up React-Admin In TanStack Start
45+
46+
Add the `react-admin` and `ra-router-tanstack` packages, as well as a data provider package. In this example, we'll use `ra-data-json-server` to connect to a test API provided by [JSONPlaceholder](https://jsonplaceholder.typicode.com).
47+
48+
```bash
49+
cd tanstack-admin
50+
npm install react-admin ra-router-tanstack ra-data-json-server
51+
# or
52+
yarn add react-admin ra-router-tanstack ra-data-json-server
53+
```
54+
55+
## Adding React-Admin At The Root
56+
57+
TanStack Start uses file-based routing. React-admin generates dynamic routes for each resource (e.g. `/users`, `/users/:id`). To avoid “Not Found” pages, we create explicit routes for the resource paths and render the same admin component in each route.
58+
59+
First, update the root route at `src/routes/index.tsx`:
60+
61+
```tsx
62+
// in src/routes/index.tsx
63+
import { createFileRoute } from '@tanstack/react-router';
64+
import {
65+
Admin,
66+
Resource,
67+
ListGuesser,
68+
EditGuesser,
69+
} from 'react-admin';
70+
import jsonServerProvider from 'ra-data-json-server';
71+
import { tanStackRouterProvider } from 'ra-router-tanstack';
72+
73+
const dataProvider = jsonServerProvider('https://jsonplaceholder.typicode.com');
74+
75+
export const Route = createFileRoute('/')({ component: App });
76+
77+
function App() {
78+
return (
79+
<Admin
80+
dataProvider={dataProvider}
81+
routerProvider={tanStackRouterProvider}
82+
>
83+
<Resource
84+
name="users"
85+
list={ListGuesser}
86+
edit={EditGuesser}
87+
/>
88+
</Admin>
89+
);
90+
}
91+
92+
export default App;
93+
```
94+
95+
Then create the routes for the resource and its dynamic paths:
96+
97+
```tsx
98+
// in src/routes/users.tsx
99+
import { createFileRoute } from '@tanstack/react-router';
100+
import App from './index';
101+
102+
export const Route = createFileRoute('/users')({ component: App });
103+
```
104+
105+
```tsx
106+
// in src/routes/users.$id.tsx
107+
import { createFileRoute } from '@tanstack/react-router';
108+
import App from './index';
109+
110+
export const Route = createFileRoute('/users/$id')({ component: App });
111+
```
112+
113+
114+
You can now start the app in `development` mode:
115+
116+
```bash
117+
npm run dev
118+
# or
119+
yarn dev
120+
```
121+
122+
The admin should render at `/` on your dev server.
123+
124+
![TanStack Start admin screen](./img/tanstack-admin.png)
125+
126+
**Tip**: If you add more resources, create matching file-based routes for each resource list and edit path and point them to the same `App` component.
127+
128+
## Removing The TanStack Header
129+
130+
TanStack Start adds a default header in the root layout. If you want the admin to render without that header, edit `src/routes/__root.tsx` and remove the `<Header />` component from `RootDocument`.
131+
132+
## Adding an API
133+
134+
TanStack Start doesn't force a specific backend. If you need an API for your admin, you can:
135+
136+
- Use an external CRUD backend like Supabase or PostgREST
137+
- Proxy requests through your app's server runtime (if your deployment includes one)
138+
139+
For example, you can create a REST API with Supabase and proxy it through TanStack Start so you don't expose service keys to the browser.
140+
141+
First, create a Supabase REST API and its associated PostgreSQL database directly on the [Supabase website](https://app.supabase.com/) (it's free for tests and low usage). Once the setup is finished, use the Supabase manager to add the following table:
142+
143+
- `users` with fields: `id`, `name`, and `email`
144+
145+
You can populate these tables via the Supabase UI if you want.
146+
147+
Supabase exposes a REST API at `https://YOUR_INSTANCE.supabase.co/rest/v1`.
148+
149+
Next, create a configuration to let the TanStack Start app connect to Supabase. Create a `.env` file:
150+
151+
```sh
152+
# In `.env`
153+
SUPABASE_URL="https://MY_INSTANCE.supabase.co"
154+
SUPABASE_SERVICE_ROLE="MY_SERVICE_ROLE_KEY"
155+
```
156+
157+
**Tip**: This example uses the **service role key** here and not the anonymous role. This allows mutations without dealing with authorization. **You shouldn't do this in production**, but use the [Supabase authorization](https://supabase.com/docs/guides/auth) feature instead.
158+
159+
Time to bootstrap the API Proxy. Create a new TanStack Start route at `src/routes/api.$.ts`:
160+
161+
```ts
162+
// in src/routes/api.$.ts
163+
import { createFileRoute } from '@tanstack/react-router'
164+
165+
export const Route = createFileRoute('/api/$')({
166+
server: {
167+
handlers: {
168+
GET: ({ request }) => proxy(request),
169+
POST: ({ request }) => proxy(request),
170+
PUT: ({ request }) => proxy(request),
171+
DELETE: ({ request }) => proxy(request),
172+
},
173+
},
174+
})
175+
176+
const API_PREFIX = '/api'
177+
178+
const proxy = (request: Request) => {
179+
const apiUrl = getSupabaseUrlFromRequestUrl(request.url)
180+
181+
return fetch(apiUrl, {
182+
method: request.method,
183+
body: request.body,
184+
headers: {
185+
prefer: request.headers.get('prefer') ?? '',
186+
accept: request.headers.get('accept') ?? 'application/json',
187+
'Accept-Encoding': '',
188+
apiKey: `${process.env.SUPABASE_SERVICE_ROLE}`,
189+
Authorization: `Bearer ${process.env.SUPABASE_SERVICE_ROLE}`,
190+
},
191+
})
192+
}
193+
194+
const getSupabaseUrlFromRequestUrl = (url: string) => {
195+
const startOfRequest = url.indexOf(API_PREFIX)
196+
const query = url.substring(startOfRequest + API_PREFIX.length)
197+
return `${process.env.SUPABASE_URL}/rest/v1${query}`
198+
}
199+
```
200+
201+
**Tip**: Some of this code is PostgREST-specific. The `prefer` header is required to let PostgREST return one record instead of an array containing one record in response to `getOne` requests. A proxy for another CRUD API will require different parameters.
202+
203+
Update the react-admin data provider to use the Supabase adapter instead of the JSON Server one. As Supabase provides a PostgREST endpoint, we'll use [`ra-data-postgrest`](https://github.com/raphiniert-com/ra-data-postgrest):
204+
205+
```sh
206+
npm install @raphiniert/ra-data-postgrest
207+
# or
208+
yarn add @raphiniert/ra-data-postgrest
209+
```
210+
211+
Finally, update your Admin dataProvider:
212+
213+
```tsx
214+
// in src/routes/index.tsx
215+
import { Admin, Resource, ListGuesser, fetchUtils } from 'react-admin';
216+
import postgrestRestProvider from '@raphiniert/ra-data-postgrest';
217+
import { tanStackRouterProvider } from 'ra-router-tanstack';
218+
219+
const dataProvider = postgrestRestProvider({
220+
apiUrl: '/api',
221+
httpClient: fetchUtils.fetchJson,
222+
defaultListOp: 'eq',
223+
schema: () => '',
224+
});
225+
226+
// ... keep the rest of the file the same
227+
```
228+
229+
## Next Steps
230+
231+
For standalone vs embedded setups, see the [TanStack Router Integration](./TanStackRouter.md).

docs/img/tanstack-admin.png

64.2 KB
Loading

docs/img/tanstack-structure.png

7.74 KB
Loading

docs/navigation.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<li {% if page.path == 'Remix.md' %} class="active" {% endif %}><a class="nav-link" href="./Remix.html">Remix</a></li>
1717
<li {% if page.path == 'ReactRouterFramework.md' %} class="active" {% endif %}><a class="nav-link" href="./ReactRouterFramework.html">React Router Framework</a></li>
1818
<li {% if page.path == 'Deploy.md' %} class="active beginner" {% endif %}><a class="nav-link" href="./Deploy.html">Deployment</a></li>
19+
<li {% if page.path == 'TanStackStart.md' %} class="active" {% endif %}><a class="nav-link" href="./TanStackStart.html">TanStack Start</a></li>
1920
</ul>
2021

2122
<ul><div>Guides & Concepts</div>

0 commit comments

Comments
 (0)