You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/blog/announcing-tanstack-start-v1.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,7 +37,7 @@ That page will stay current with the exact commands for the RC and the final 1.0
37
37
38
38
## Path to 1.0 stable
39
39
40
-
We plan to cut 1.0 shortly after collecting RC feedback. Expect a few small RC iterations; any breaking changes will be clearly documented. As we approach stable, only light polish remains—no major API shifts.
40
+
We plan to cut 1.0 shortly after collecting RC feedback. Expect a few small RC iterations; any breaking changes will be clearly documented. As we approach stable, only light polish remains. No major API shifts.
41
41
42
42
> **Note:** React Server Components support is in active development and will land as a non-breaking v1.x addition.
43
43
@@ -67,6 +67,6 @@ Their collaboration is a pivotal force driving the open web forward. Explore the
67
67
68
68
## Your feedback counts
69
69
70
-
This is the moment when your feedback matters most. Try the RC in a new or existing project and tell us what you think via the docs feedback links. If you hit an issue, the migration notes and examples in the docs will help—and we’ll be quick to respond.
70
+
This is the moment when your feedback matters most. Try the RC in a new or existing project and tell us what you think via the docs feedback links. If you hit an issue, the migration notes and examples in the docs will help. And we’ll be quick to respond.
71
71
72
72
Thanks for building with us. Let’s ship 1.0, together.
Copy file name to clipboardExpand all lines: src/blog/netlify-partnership.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@ Netlify has earned its reputation as the ultimate deployment platform for modern
18
18
19
19
## Why Netlify?
20
20
21
-
Netlify is more than just a deployment provider—they’ve worked closely with us to ensure that deploying TanStack Start applications is not just fast, but optimized for the best possible developer experience. Whether you’re building interactive UIs, data-heavy dashboards, real-time tools, or AI-powered applications, Netlify’s platform makes the process seamless.
21
+
Netlify is more than just a deployment provider. They’ve worked closely with us to ensure that deploying TanStack Start applications is not just fast, but optimized for the best possible developer experience. Whether you’re building interactive UIs, data-heavy dashboards, real-time tools, or AI-powered applications, Netlify’s platform makes the process seamless.
22
22
23
23
As part of this partnership, Netlify has also launched a **full-stack AI chatbot starter template** that showcases TanStack Start’s powerful data management capabilities alongside Netlify Functions. This template provides:
Copy file name to clipboardExpand all lines: src/blog/search-params-are-state.md
+13-13Lines changed: 13 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,9 +7,9 @@ authors:
7
7
8
8

9
9
10
-
## Search Params Are State — Treat Them That Way
10
+
## Search Params Are State . Treat Them That Way
11
11
12
-
Search params have been historically treated like second-class state. They're global, serializable, and shareable — but in most apps, they’re still hacked together with string parsing, loose conventions, and brittle utils.
12
+
Search params have been historically treated like second-class state. They're global, serializable, and shareable . but in most apps, they’re still hacked together with string parsing, loose conventions, and brittle utils.
13
13
14
14
Even something simple, like validating a `sort` param, quickly turns verbose:
15
15
@@ -30,7 +30,7 @@ This works, but it’s manual and repetitive. There’s no inference, no connect
30
30
31
31
Even worse, `URLSearchParams` is string-only. It doesn’t support nested JSON, arrays (beyond naive comma-splitting), or type coercion. So unless your state is flat and simple, you’re going to hit walls fast.
32
32
33
-
That’s why we’re starting to see a rise in tools and proposals — things like Nuqs, Next.js RFCs, and userland patterns — aimed at making search params more type-safe and ergonomic. Most of these focus on improving _reading_ from the URL.
33
+
That’s why we’re starting to see a rise in tools and proposals . things like Nuqs, Next.js RFCs, and userland patterns . aimed at making search params more type-safe and ergonomic. Most of these focus on improving _reading_ from the URL.
34
34
35
35
But almost none of them solve the deeper, harder problem: **writing** search params, safely and atomically, with full awareness of routing context.
36
36
@@ -56,15 +56,15 @@ Constraint is what makes coordination possible. It’s what allows **non-local c
56
56
57
57
---
58
58
59
-
### Local Abstractions Can Help — But They Don’t Coordinate
59
+
### Local Abstractions Can Help . But They Don’t Coordinate
60
60
61
-
Tools like **Nuqs** are a great example of how local abstractions can improve the _ergonomics_ of search param handling. You get Zod-powered parsing, type inference, even writable APIs — all scoped to a specific component or hook.
61
+
Tools like **Nuqs** are a great example of how local abstractions can improve the _ergonomics_ of search param handling. You get Zod-powered parsing, type inference, even writable APIs . all scoped to a specific component or hook.
62
62
63
-
They make it easier to read and write search params **in isolation**— and that’s valuable.
63
+
They make it easier to read and write search params **in isolation**. and that’s valuable.
64
64
65
65
But they don’t solve the broader issue of **coordination**. You still end up with duplicated schemas, disjointed expectations, and no way to enforce consistency between routes or components. Defaults can conflict. Types can drift. And when routes evolve, nothing guarantees all the callers update with them.
66
66
67
-
That’s the real fragmentation problem — and fixing it requires bringing search param schemas into the routing layer itself.
67
+
That’s the real fragmentation problem . and fixing it requires bringing search param schemas into the routing layer itself.
68
68
69
69
---
70
70
@@ -100,13 +100,13 @@ navigate({
100
100
})
101
101
```
102
102
103
-
It’s reducer-style, transactional, and integrates directly with the router’s reactivity model. Components only re-render when the specific search param they use changes — not every time the URL mutates.
103
+
It’s reducer-style, transactional, and integrates directly with the router’s reactivity model. Components only re-render when the specific search param they use changes . not every time the URL mutates.
104
104
105
105
---
106
106
107
107
### How TanStack Router Prevents Schema Fragmentation
108
108
109
-
When your search param logic lives in userland — scattered across hooks, utils, and helpers — it’s only a matter of time before you end up with **conflicting schemas**.
109
+
When your search param logic lives in userland . scattered across hooks, utils, and helpers . it’s only a matter of time before you end up with **conflicting schemas**.
110
110
111
111
Maybe one component expects \`sort: 'asc' | 'desc'\`. Another adds a \`filter\`. A third assumes \`sort: 'desc'\` by default. None of them share a source of truth.
112
112
@@ -117,7 +117,7 @@ This leads to:
117
117
- Navigation that sets values others can’t parse
118
118
- Broken deep linking and bugs you can’t trace
119
119
120
-
TanStack Router prevents this by tying schemas directly to your route definitions —**hierarchically**.
120
+
TanStack Router prevents this by tying schemas directly to your route definitions .**hierarchically**.
121
121
122
122
Parent routes can define shared search param validation. Child routes inherit that context, add to it, or extend it in type-safe ways. This makes it _impossible_ to accidentally create overlapping, incompatible schemas in different parts of your app.
123
123
@@ -160,23 +160,23 @@ validateSearch: z.object({
160
160
})
161
161
```
162
162
163
-
This kind of enforcement makes nested routes composable _and_ safe — a rare combo.
163
+
This kind of enforcement makes nested routes composable _and_ safe . a rare combo.
164
164
165
165
---
166
166
167
167
### Built-In Discipline
168
168
169
169
The magic here is that you don’t need to teach your team to follow conventions. The route _owns_ the schema. Everyone just uses it. There’s no duplication. No drift. No silent bugs. No guessing.
170
170
171
-
When you bring validation, typing, and ownership into the router itself, you stop treating URLs like strings and start treating them like real state — because that’s what they are.
171
+
When you bring validation, typing, and ownership into the router itself, you stop treating URLs like strings and start treating them like real state . because that’s what they are.
172
172
173
173
---
174
174
175
175
### Search Params Are State
176
176
177
177
Most routing systems treat search params like an afterthought. Something you _can_ read, maybe parse, maybe stringify, but rarely something you can actually **trust**.
178
178
179
-
TanStack Router flips that on its head. It makes search params a core part of the routing contract — validated, inferable, writable, and reactive.
179
+
TanStack Router flips that on its head. It makes search params a core part of the routing contract . validated, inferable, writable, and reactive.
180
180
181
181
Because if you’re not treating search params like state, you’re going to keep leaking it, breaking it, and working around it.
Copy file name to clipboardExpand all lines: src/blog/tanstack-ai-alpha-2.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@ Our goals were simple: move away from monolithic adapters and their complexity,
15
15
16
16
## New Adapter Architecture
17
17
18
-
We wanted to support everything AI providers offer—image generation, video, audio, text-to-speech, transcription—without updating every adapter simultaneously.
18
+
We wanted to support everything AI providers offer. Image generation, video, audio, text-to-speech, transcription. Without updating every adapter simultaneously.
19
19
20
20
We're a small team. Adding image support shouldn't mean extending `BaseAdapter`, updating 5+ provider implementations, ensuring per-model type safety for each, and combing through docs manually. That's a week per provider. Multiply that by 20 providers and 6 modalities.
**Incremental feature support.** Add image generation to OpenAI this week, Gemini next week, video for a third provider the week after. Smaller releases, same pace.
39
39
40
-
**Easier maintenance.** Our adapter abstraction had grown to 7 type generics with only text, summarization, and embeddings. Adding 6 more modalities would have exploded complexity. Now each adapter is focused—3 generics max.
40
+
**Easier maintenance.** Our adapter abstraction had grown to 7 type generics with only text, summarization, and embeddings. Adding 6 more modalities would have exploded complexity. Now each adapter is focused. 3 generics max.
41
41
42
42
**Better bundle size.** You control what you pull in. Want only text? Import `openaiText`. Want text and images? Import both. Your bundle, your choice.
43
43
@@ -168,4 +168,4 @@ We're confident in this direction. We think you'll like it too.
168
168
169
169
<!-- ---
170
170
171
-
_Curious how we got here? Read [The `ai()` Function That Almost Was](/blog/tanstack-ai-the-ai-function-postmortem)—a post-mortem on the API we loved, built, and had to kill._ -->
171
+
_Curious how we got here? Read [The `ai()` Function That Almost Was](/blog/tanstack-ai-the-ai-function-postmortem). a post-mortem on the API we loved, built, and had to kill._ -->
Copy file name to clipboardExpand all lines: src/blog/tanstack-ai-the-ai-function-postmortem.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ ai({
36
36
})
37
37
```
38
38
39
-
Simple. Single function. Powers everything AI-related. Clear naming—you're using AI. Types constrained to each adapter's capabilities. Pass image options to an image adapter, text options to a text adapter.
39
+
Simple. Single function. Powers everything AI-related. Clear naming. You're using AI. Types constrained to each adapter's capabilities. Pass image options to an image adapter, text options to a text adapter.
40
40
41
41
Change models? Type errors if something's not supported. Change adapters? Type errors if something's not supported.
42
42
@@ -54,7 +54,7 @@ The simplicity of `ai()` for end users hid enormous implementation complexity.
54
54
55
55
**Attempt 1: Function Overloads**
56
56
57
-
We tried using function overloads to constrain each adapter's options. Too many scenarios. The overloads resolved to wrong signatures—you could end up providing video options instead of image options. We got it to 99% working, but the 1% felt wrong and was a bigger hurdle than you'd think.
57
+
We tried using function overloads to constrain each adapter's options. Too many scenarios. The overloads resolved to wrong signatures. You could end up providing video options instead of image options. We got it to 99% working, but the 1% felt wrong and was a bigger hurdle than you'd think.
58
58
59
59
Having 10+ overloads is cumbersome. Get the order wrong and it all falls apart. This would exponentially increase the difficulty of contributions and lowered our confidence in shipping stable releases.
60
60
@@ -68,7 +68,7 @@ We'll take complexity on our side over forcing you to use `as` casts or `any` ty
68
68
69
69
### The aiOptions Nightmare
70
70
71
-
We added a `createXXXOptions` API—`createTextOptions`, `createImageOptions`, etc. You can construct options as ready-made agents and pass them into functions, overriding what you need.
71
+
We added a `createXXXOptions` API. `createTextOptions`, `createImageOptions`, etc. You can construct options as ready-made agents and pass them into functions, overriding what you need.
72
72
73
73
To match the theme, we called it `aiOptions`. It would constrain everything to the modality and provider:
74
74
@@ -82,13 +82,13 @@ ai(opts)
82
82
83
83
Here's where we hit the wall.
84
84
85
-
When `aiOptions` returned readonly values, spreading into `ai()` worked. But `aiOptions` was loosely typed—you could pass anything in.
85
+
When `aiOptions` returned readonly values, spreading into `ai()` worked. But `aiOptions` was loosely typed. You could pass anything in.
86
86
87
87
When we fixed `aiOptions` to accept only valid properties, the spread would cast the `ai()` function to `any`. Then it would accept anything.
88
88
89
89
We went in circles. Get one part working, break another. Fix that, break the first thing.
90
90
91
-
I believe it could have been done. Our approach was probably just wrong—some subtle bug in the system causing everything to break. But that proves the point: it was too complex to wrap your head around and find the root cause. Any fix would have to propagate through all the adapters. Very costly.
91
+
I believe it could have been done. Our approach was probably just wrong. Some subtle bug in the system causing everything to break. But that proves the point: it was too complex to wrap your head around and find the root cause. Any fix would have to propagate through all the adapters. Very costly.
92
92
93
93
We spent almost a week trying to get this API to work perfectly. We couldn't. Maybe another week would have done it. But then what? How would we fix bugs in this brittle type system? How would we find root causes?
94
94
@@ -98,7 +98,7 @@ Even if we'd gotten it working, there was another problem.
98
98
99
99
We'd just split our adapters into smaller pieces so bundlers could tree-shake what you don't use. Then we put all that complexity right back into `ai()`.
100
100
101
-
We don't want to be the lodash of AI libraries—bundling everything you don't use and calling it a day. If a huge adapter that bundles everything is not okay, a single function that does the same thing is definitely not okay.
101
+
We don't want to be the lodash of AI libraries, bundling everything you don't use and calling it a day. If a huge adapter that bundles everything is not okay, a single function that does the same thing is definitely not okay.
102
102
103
103
## The Warnings We Missed
104
104
@@ -112,7 +112,7 @@ The warning sign we missed? LLMs couldn't reliably generate code for this API.
112
112
113
113
Think about that. We're building tools for AI, and AI couldn't figure out how to use them. That should have been a massive clue that humans wouldn't reliably write to this API unaided either.
114
114
115
-
LLMs like function names that indicate what the thing does. `ai()`—who knows?`generateImage()`—crystal clear.
115
+
LLMs like function names that indicate what the thing does. `ai()`? Who knows.`generateImage()`? Crystal clear.
116
116
117
117
When we finally asked the LLMs directly what they thought of the API, they were 4-0 against `ai()` and for the more descriptive approach we ended up with.
118
118
@@ -147,7 +147,7 @@ adapter.image('model')
147
147
adapter.text('model')
148
148
```
149
149
150
-
Looks nicer. Feels more unified. Same problem—still bundles everything.
150
+
Looks nicer. Feels more unified. Same problem: still bundles everything.
151
151
152
152
We could have done custom bundling in TanStack Start to strip unused parts, but we don't want to force you to use our framework for the best experience. This library is for the web ecosystem, not just TanStack users.
0 commit comments