docs-i18n 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/package.json +1 -1
  2. package/template/app/utils/content-loader.ts +4 -0
  3. package/template/app/utils/docs.server.ts +7 -0
  4. package/template/content/blog/en/announcing-query-v5.md +110 -0
  5. package/template/content/blog/en/hello-world.md +26 -0
  6. package/template/content/blog/en/i18n-best-practices.md +57 -0
  7. package/template/content/blog/en/react-query-vs-swr.md +100 -0
  8. package/template/content/blog/en/state-management-2024.md +143 -0
  9. package/template/content/blog/en/tanstack-router-1.0.md +121 -0
  10. package/template/content/blog/ja/announcing-query-v5.md +110 -0
  11. package/template/content/blog/ja/hello-world.md +26 -0
  12. package/template/content/blog/zh-hans/announcing-query-v5.md +93 -0
  13. package/template/content/blog/zh-hans/hello-world.md +26 -0
  14. package/template/content/docs-i18n/docs.config.json +25 -0
  15. package/template/content/docs-i18n/en/admin.md +143 -0
  16. package/template/content/docs-i18n/en/architecture.md +222 -0
  17. package/template/content/docs-i18n/en/cli.md +324 -0
  18. package/template/content/docs-i18n/en/configuration.md +331 -0
  19. package/template/content/docs-i18n/en/deployment.md +209 -0
  20. package/template/content/docs-i18n/en/getting-started.md +168 -0
  21. package/template/content/docs.config.json +25 -0
  22. package/template/content/en/admin.md +151 -0
  23. package/template/content/en/architecture.md +222 -0
  24. package/template/content/en/cli.md +269 -0
  25. package/template/content/en/configuration.md +331 -0
  26. package/template/content/en/deployment.md +209 -0
  27. package/template/content/en/getting-started.md +168 -0
  28. package/template/content/form/docs.config.json +18 -0
  29. package/template/content/form/en/guides/validation.md +175 -0
  30. package/template/content/form/en/installation.md +63 -0
  31. package/template/content/form/en/overview.md +71 -0
  32. package/template/content/form/en/quick-start.md +121 -0
  33. package/template/content/form/ja/installation.md +63 -0
  34. package/template/content/form/ja/overview.md +71 -0
  35. package/template/content/form/zh-hans/installation.md +63 -0
  36. package/template/content/form/zh-hans/overview.md +71 -0
  37. package/template/content/query/docs.config.json +32 -0
  38. package/template/content/query/en/guides/mutations.md +126 -0
  39. package/template/content/query/en/guides/pagination.md +98 -0
  40. package/template/content/query/en/guides/queries.md +120 -0
  41. package/template/content/query/en/installation.md +78 -0
  42. package/template/content/query/en/overview.md +72 -0
  43. package/template/content/query/en/quick-start.md +108 -0
  44. package/template/content/query/ja/installation.md +78 -0
  45. package/template/content/query/ja/overview.md +72 -0
  46. package/template/content/query/zh-hans/guides/mutations.md +126 -0
  47. package/template/content/query/zh-hans/guides/pagination.md +98 -0
  48. package/template/content/query/zh-hans/guides/queries.md +120 -0
  49. package/template/content/query/zh-hans/installation.md +95 -0
  50. package/template/content/query/zh-hans/overview.md +72 -0
  51. package/template/content/query/zh-hans/quick-start.md +108 -0
  52. package/template/content/router/docs.config.json +18 -0
  53. package/template/content/router/en/guides/routing-concepts.md +131 -0
  54. package/template/content/router/en/installation.md +57 -0
  55. package/template/content/router/en/overview.md +74 -0
  56. package/template/content/router/en/quick-start.md +88 -0
  57. package/template/content/router/ja/installation.md +57 -0
  58. package/template/content/router/ja/overview.md +78 -0
  59. package/template/content/router/zh-hans/guides/routing-concepts.md +131 -0
  60. package/template/content/router/zh-hans/installation.md +57 -0
  61. package/template/content/router/zh-hans/overview.md +81 -0
  62. package/template/content/router/zh-hans/quick-start.md +88 -0
  63. package/template/content/table/docs.config.json +18 -0
  64. package/template/content/table/en/guides/column-definitions.md +135 -0
  65. package/template/content/table/en/installation.md +56 -0
  66. package/template/content/table/en/overview.md +79 -0
  67. package/template/content/table/en/quick-start.md +112 -0
  68. package/template/content/table/ja/installation.md +56 -0
  69. package/template/content/table/ja/overview.md +79 -0
  70. package/template/content/table/zh-hans/installation.md +56 -0
  71. package/template/content/table/zh-hans/overview.md +79 -0
  72. package/template/content/virtual/docs.config.json +18 -0
  73. package/template/content/virtual/en/guides/dynamic-sizing.md +129 -0
  74. package/template/content/virtual/en/installation.md +57 -0
  75. package/template/content/virtual/en/overview.md +74 -0
  76. package/template/content/virtual/en/quick-start.md +114 -0
  77. package/template/content/virtual/ja/installation.md +57 -0
  78. package/template/content/virtual/ja/overview.md +74 -0
  79. package/template/content/virtual/zh-hans/installation.md +57 -0
  80. package/template/content/virtual/zh-hans/overview.md +74 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docs-i18n",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Universal documentation translation engine — parse, translate, cache, assemble, manage.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -82,7 +82,11 @@ export function createFsLoader(
82
82
  const baseDirs = [
83
83
  resolve(projectRoot, 'content', project, version, lang),
84
84
  resolve(projectRoot, 'content', project, lang),
85
+ resolve(projectRoot, 'content', version, lang),
85
86
  resolve(projectRoot, 'content', lang),
87
+ // Flat structure (no lang subdir): content/{version}/ directly
88
+ resolve(projectRoot, 'content', project, version),
89
+ resolve(projectRoot, 'content', version),
86
90
  ]
87
91
 
88
92
  if (!urlMapper) {
@@ -108,7 +108,11 @@ function loadFilesystemSidebar(
108
108
  const candidates = [
109
109
  resolve(root, 'content', project, version, 'en'),
110
110
  resolve(root, 'content', project, 'en'),
111
+ resolve(root, 'content', version, 'en'),
111
112
  resolve(root, 'content', 'en'),
113
+ // Flat structure (no lang subdir)
114
+ resolve(root, 'content', project, version),
115
+ resolve(root, 'content', version),
112
116
  ]
113
117
  for (const dir of candidates) {
114
118
  if (existsSync(dir) && statSync(dir).isDirectory()) {
@@ -130,7 +134,10 @@ function autoScanDocs(
130
134
  const candidates = [
131
135
  resolve(root, 'content', project, version, 'en'),
132
136
  resolve(root, 'content', project, 'en'),
137
+ resolve(root, 'content', version, 'en'),
133
138
  resolve(root, 'content', 'en'),
139
+ resolve(root, 'content', project, version),
140
+ resolve(root, 'content', version),
134
141
  ]
135
142
 
136
143
  for (const dir of candidates) {
@@ -0,0 +1,110 @@
1
+ ---
2
+ title: "Announcing TanStack Query v5"
3
+ published: "2024-10-01"
4
+ excerpt: "TanStack Query v5 is here with a simplified API, better TypeScript support, improved devtools, and a smaller bundle size. Here is everything you need to know."
5
+ authors:
6
+ - "Tanner Linsley"
7
+ - "Dominik Dorfmeister"
8
+ ---
9
+
10
+ We are thrilled to announce the release of TanStack Query v5! This release represents months of work from the community and brings significant improvements across the board.
11
+
12
+ ## What's New
13
+
14
+ ### Simplified API
15
+
16
+ The most visible change in v5 is the simplified API. We have removed the object syntax overloads in favor of a single, consistent object syntax for all hooks:
17
+
18
+ ```tsx
19
+ // v4 — multiple overloads
20
+ useQuery(['todos'], fetchTodos)
21
+ useQuery(['todos'], fetchTodos, { staleTime: 5000 })
22
+ useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
23
+
24
+ // v5 — single consistent API
25
+ useQuery({
26
+ queryKey: ['todos'],
27
+ queryFn: fetchTodos,
28
+ staleTime: 5000,
29
+ })
30
+ ```
31
+
32
+ This makes the API easier to learn and provides better TypeScript inference.
33
+
34
+ ### Better TypeScript Support
35
+
36
+ v5 includes major TypeScript improvements:
37
+
38
+ - **Strict query key typing** — query keys are now strictly typed throughout
39
+ - **Inferred return types** — `useQuery` correctly infers the return type from `queryFn`
40
+ - **Type-safe error handling** — errors are properly typed with the new `Error` generic parameter
41
+
42
+ ```tsx
43
+ // Error type is now inferred and type-safe
44
+ const { data, error } = useQuery({
45
+ queryKey: ['user', userId],
46
+ queryFn: async () => {
47
+ const res = await fetch(`/api/users/${userId}`)
48
+ if (!res.ok) throw new ApiError(res.status, await res.text())
49
+ return res.json() as Promise<User>
50
+ },
51
+ })
52
+
53
+ // error is typed as ApiError | null
54
+ if (error) {
55
+ console.log(error.status) // TypeScript knows this exists
56
+ }
57
+ ```
58
+
59
+ ### New Devtools
60
+
61
+ The devtools have been completely rewritten with a new design, better performance, and new features:
62
+
63
+ - **Query timeline** — visualize query fetches over time
64
+ - **Mutation inspector** — inspect mutation state and variables
65
+ - **Cache explorer** — browse the entire query cache
66
+ - **Online/offline toggle** — test offline behavior
67
+
68
+ ### Smaller Bundle Size
69
+
70
+ We have reduced the core bundle size by approximately 20% through tree-shaking improvements and removing deprecated APIs.
71
+
72
+ | Package | v4 | v5 | Change |
73
+ |---|---|---|---|
74
+ | `@tanstack/react-query` | 12.4 KB | 9.8 KB | -21% |
75
+ | `@tanstack/query-core` | 10.1 KB | 8.2 KB | -19% |
76
+
77
+ ## Breaking Changes
78
+
79
+ > [!WARNING]
80
+ > v5 includes several breaking changes. Please review the full [migration guide](/en/query/docs/guides/migration-v5) before upgrading.
81
+
82
+ Key breaking changes:
83
+
84
+ 1. **Removed overloaded signatures** — all hooks now use object-only syntax
85
+ 2. **Renamed `cacheTime` to `gcTime`** — better reflects its purpose (garbage collection time)
86
+ 3. **`status: 'loading'` renamed to `status: 'pending'`** — aligns with Promise terminology
87
+ 4. **Removed `keepPreviousData`** — replaced with `placeholderData: keepPreviousData` (import from query core)
88
+ 5. **Minimum TypeScript version is now 4.7**
89
+
90
+ ## Migration
91
+
92
+ We have built a codemod to automate most of the migration:
93
+
94
+ ```bash
95
+ npx @tanstack/query-codemod v5 ./src
96
+ ```
97
+
98
+ This will handle the most common transformations automatically. Review the changes and test thoroughly.
99
+
100
+ ## Thank You
101
+
102
+ Thank you to the 100+ contributors who made this release possible. TanStack Query v5 would not exist without the incredible open source community.
103
+
104
+ Get started with v5 today:
105
+
106
+ ```bash
107
+ npm install @tanstack/react-query@latest
108
+ ```
109
+
110
+ Happy querying!
@@ -0,0 +1,26 @@
1
+ ---
2
+ title: "Hello World: Introducing docs-i18n Blog"
3
+ published: "2024-01-15"
4
+ excerpt: "Welcome to the docs-i18n blog! We will share updates, tutorials, and best practices for internationalizing your documentation."
5
+ authors:
6
+ - "docs-i18n Team"
7
+ ---
8
+
9
+ Welcome to the docs-i18n blog! This is where we will share project updates, tutorials, and best practices for documentation internationalization.
10
+
11
+ ## What is docs-i18n?
12
+
13
+ docs-i18n is a universal documentation translation engine that makes it easy to maintain multilingual documentation sites. It provides:
14
+
15
+ - **Filesystem-based content loading** with i18n fallback
16
+ - **Markdown rendering** with syntax highlighting and framework-aware content
17
+ - **Admin interface** for managing translations
18
+ - **CLI tools** for automating translation workflows
19
+
20
+ ## Getting Started
21
+
22
+ Check out our [getting started guide](/en/getting-started) to learn how to set up docs-i18n for your project.
23
+
24
+ ## Stay Tuned
25
+
26
+ We have exciting features planned for upcoming releases. Follow this blog for the latest updates!
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: "Best Practices for Documentation i18n"
3
+ published: "2024-02-10"
4
+ excerpt: "Learn the key principles and patterns for effectively internationalizing your documentation, from content structure to translation workflows."
5
+ authors:
6
+ - "docs-i18n Team"
7
+ ---
8
+
9
+ Internationalizing documentation is more than just translating text. Here are the best practices we have learned from building docs-i18n.
10
+
11
+ ## Structure Content for Translation
12
+
13
+ ### Use English as Source of Truth
14
+
15
+ Keep your English content as the canonical source. All translations derive from it, and the system falls back to English when a translation is missing.
16
+
17
+ ### Separate Content from Presentation
18
+
19
+ Store your documentation as plain markdown files organized by locale:
20
+
21
+ ```
22
+ content/
23
+ blog/
24
+ en/
25
+ my-post.md
26
+ zh-hans/
27
+ my-post.md
28
+ ja/
29
+ my-post.md
30
+ ```
31
+
32
+ ### Use Frontmatter for Metadata
33
+
34
+ Each document should have frontmatter with at least a `title` field. For blog posts, include `published`, `excerpt`, and `authors`.
35
+
36
+ ## Translation Workflow
37
+
38
+ ### Start with High-Impact Pages
39
+
40
+ Not all pages need translation at once. Prioritize:
41
+
42
+ 1. Getting started guides
43
+ 2. Core concept documentation
44
+ 3. API reference
45
+ 4. Blog posts and announcements
46
+
47
+ ### Leverage Fallback Content
48
+
49
+ docs-i18n automatically falls back to English when a translation is missing. This means your site works for all locales immediately — translations improve it incrementally.
50
+
51
+ ### Keep Translations in Sync
52
+
53
+ When the English source changes, translations may become outdated. Use the docs-i18n admin interface to track which translations need updating.
54
+
55
+ ## Conclusion
56
+
57
+ Good documentation internationalization is an ongoing process. Start simple, prioritize high-impact content, and iterate.
@@ -0,0 +1,100 @@
1
+ ---
2
+ title: "TanStack Query vs SWR: A Detailed Comparison"
3
+ published: "2024-06-15"
4
+ excerpt: "An honest, detailed comparison of TanStack Query and SWR — two of the most popular data fetching libraries in the React ecosystem."
5
+ authors:
6
+ - "docs-i18n Team"
7
+ ---
8
+
9
+ Choosing a data fetching library is an important architectural decision. TanStack Query and SWR are the two most popular options in the React ecosystem. Here is an honest comparison to help you decide.
10
+
11
+ ## Overview
12
+
13
+ Both libraries solve the same core problem: managing server state in React applications. They both provide hooks for fetching, caching, and synchronizing server data. However, they differ significantly in scope and philosophy.
14
+
15
+ | Feature | TanStack Query | SWR |
16
+ |---|---|---|
17
+ | Bundle size (minified + gzip) | ~12 KB | ~4 KB |
18
+ | Framework support | React, Vue, Solid, Svelte, Angular | React only |
19
+ | Devtools | Built-in, feature-rich | Community extension |
20
+ | Mutations | First-class `useMutation` | Manual implementation |
21
+ | Infinite queries | Built-in `useInfiniteQuery` | Built-in `useSWRInfinite` |
22
+ | Offline support | Built-in | Manual |
23
+ | Query cancellation | Built-in with AbortSignal | Manual |
24
+ | Garbage collection | Configurable `gcTime` | No automatic GC |
25
+ | Optimistic updates | Built-in helpers | Manual |
26
+
27
+ ## Data Fetching
28
+
29
+ Both libraries make basic data fetching simple:
30
+
31
+ ```tsx
32
+ // TanStack Query
33
+ import { useQuery } from '@tanstack/react-query'
34
+
35
+ function Todos() {
36
+ const { data, isLoading } = useQuery({
37
+ queryKey: ['todos'],
38
+ queryFn: () => fetch('/api/todos').then((r) => r.json()),
39
+ })
40
+ }
41
+
42
+ // SWR
43
+ import useSWR from 'swr'
44
+
45
+ function Todos() {
46
+ const { data, isLoading } = useSWR('/api/todos', (url) =>
47
+ fetch(url).then((r) => r.json())
48
+ )
49
+ }
50
+ ```
51
+
52
+ SWR has a slightly more concise API for simple cases. TanStack Query requires explicit query keys and uses an object syntax exclusively.
53
+
54
+ ## Mutations
55
+
56
+ This is where the libraries diverge significantly. TanStack Query provides a dedicated `useMutation` hook:
57
+
58
+ ```tsx
59
+ // TanStack Query — built-in mutation support
60
+ const mutation = useMutation({
61
+ mutationFn: (newTodo) => fetch('/api/todos', {
62
+ method: 'POST',
63
+ body: JSON.stringify(newTodo),
64
+ }),
65
+ onSuccess: () => {
66
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
67
+ },
68
+ })
69
+
70
+ // Provides isPending, isError, isSuccess, mutate, mutateAsync
71
+ mutation.mutate({ title: 'New Todo' })
72
+ ```
73
+
74
+ SWR does not have a built-in mutation hook. You typically use `useSWRMutation` from the `swr/mutation` module or handle mutations manually.
75
+
76
+ ## When to Choose TanStack Query
77
+
78
+ Choose TanStack Query when:
79
+
80
+ - You need first-class mutation support with optimistic updates
81
+ - You want built-in devtools for debugging
82
+ - Your app has complex caching requirements
83
+ - You need offline support
84
+ - You might switch frameworks in the future (Vue, Solid, etc.)
85
+
86
+ ## When to Choose SWR
87
+
88
+ Choose SWR when:
89
+
90
+ - Bundle size is critical
91
+ - You have simple data fetching needs without complex mutations
92
+ - You prefer a minimal API surface
93
+ - You are already in the Vercel/Next.js ecosystem
94
+
95
+ ## Conclusion
96
+
97
+ Both are excellent libraries. TanStack Query is more feature-rich and better suited for complex applications with lots of mutations and caching needs. SWR is lighter and simpler, ideal for applications with straightforward data fetching requirements.
98
+
99
+ > [!NOTE]
100
+ > This comparison is based on TanStack Query v5 and SWR v2. Both libraries are actively maintained and improve with each release.
@@ -0,0 +1,143 @@
1
+ ---
2
+ title: "The State of State Management in 2024"
3
+ published: "2024-08-20"
4
+ excerpt: "Server state vs client state, signals vs hooks, atoms vs stores — a practical guide to choosing the right state management approach for your React application in 2024."
5
+ authors:
6
+ - "docs-i18n Team"
7
+ ---
8
+
9
+ State management in React has evolved dramatically. The days of putting everything in Redux are over. In 2024, the ecosystem has matured into a set of specialized tools, each solving a specific problem well.
10
+
11
+ ## The Two Kinds of State
12
+
13
+ The most important mental model shift in modern state management is the distinction between **server state** and **client state**.
14
+
15
+ **Server state** is data that:
16
+ - Lives on the server / database
17
+ - Is fetched asynchronously
18
+ - Can become stale
19
+ - Is shared across users
20
+
21
+ **Client state** is data that:
22
+ - Exists only in the browser
23
+ - Is synchronous
24
+ - Is local to the user's session
25
+ - Examples: UI toggles, form inputs, selected tabs
26
+
27
+ ```tsx
28
+ // Server state — use TanStack Query
29
+ const { data: todos } = useQuery({
30
+ queryKey: ['todos'],
31
+ queryFn: fetchTodos,
32
+ })
33
+
34
+ // Client state — use React state or a small store
35
+ const [isOpen, setIsOpen] = useState(false)
36
+ const [selectedTab, setSelectedTab] = useState('all')
37
+ ```
38
+
39
+ > [!NOTE]
40
+ > If you separate server state from client state, you will find that most applications need very little client state management. TanStack Query (or a similar library) handles the majority of your state.
41
+
42
+ ## Server State Libraries
43
+
44
+ ### TanStack Query
45
+
46
+ The most feature-rich option for server state management. Provides caching, background refetching, mutations with optimistic updates, pagination, infinite scroll, and excellent devtools.
47
+
48
+ ```tsx
49
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
50
+
51
+ function TodoApp() {
52
+ const queryClient = useQueryClient()
53
+ const todos = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
54
+
55
+ const addTodo = useMutation({
56
+ mutationFn: createTodo,
57
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
58
+ })
59
+
60
+ return (
61
+ <div>
62
+ {todos.data?.map((todo) => <Todo key={todo.id} todo={todo} />)}
63
+ <button onClick={() => addTodo.mutate({ title: 'New' })}>Add</button>
64
+ </div>
65
+ )
66
+ }
67
+ ```
68
+
69
+ ### SWR
70
+
71
+ A lighter alternative focused on data fetching. Smaller bundle, simpler API, fewer features.
72
+
73
+ ### tRPC
74
+
75
+ End-to-end type-safe APIs. Built on top of TanStack Query, so you get all its caching benefits plus type-safe API calls.
76
+
77
+ ## Client State Libraries
78
+
79
+ ### React `useState` / `useReducer`
80
+
81
+ For most client state, built-in React state is sufficient. Do not reach for a library until you have a clear need.
82
+
83
+ ### Zustand
84
+
85
+ When you need global client state (theme, user preferences, complex UI state), Zustand provides a minimal, hook-based API:
86
+
87
+ ```tsx
88
+ import { create } from 'zustand'
89
+
90
+ const useStore = create((set) => ({
91
+ bears: 0,
92
+ increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
93
+ }))
94
+
95
+ function BearCounter() {
96
+ const bears = useStore((state) => state.bears)
97
+ return <h1>{bears} bears</h1>
98
+ }
99
+ ```
100
+
101
+ ### Jotai
102
+
103
+ Atomic state management inspired by Recoil. Great for fine-grained reactivity:
104
+
105
+ ```tsx
106
+ import { atom, useAtom } from 'jotai'
107
+
108
+ const countAtom = atom(0)
109
+ const doubledAtom = atom((get) => get(countAtom) * 2)
110
+
111
+ function Counter() {
112
+ const [count, setCount] = useAtom(countAtom)
113
+ const [doubled] = useAtom(doubledAtom)
114
+ return <div>{count} (doubled: {doubled})</div>
115
+ }
116
+ ```
117
+
118
+ ## Decision Framework
119
+
120
+ | Need | Recommended Tool |
121
+ |---|---|
122
+ | Fetching / caching server data | TanStack Query or SWR |
123
+ | Local component state | `useState` / `useReducer` |
124
+ | Shared UI state (theme, modals) | Zustand or Jotai |
125
+ | Complex form state | TanStack Form |
126
+ | URL state (search params, pagination) | TanStack Router |
127
+ | End-to-end type-safe API | tRPC + TanStack Query |
128
+
129
+ ## The Pattern
130
+
131
+ The most successful React applications in 2024 follow this pattern:
132
+
133
+ 1. **TanStack Query** for all server state
134
+ 2. **TanStack Router** for URL-driven state
135
+ 3. **React `useState`** for local UI state
136
+ 4. **Zustand or Jotai** (only if needed) for global client state
137
+
138
+ > [!WARNING]
139
+ > Avoid putting server data in a global client state store (Redux, Zustand, etc.). This leads to stale data, duplicated caching logic, and unnecessary complexity. Use TanStack Query for server state.
140
+
141
+ ## Conclusion
142
+
143
+ State management in 2024 is not about choosing one library to rule them all. It is about using the right tool for the right kind of state. Start simple, add complexity only when needed, and let specialized libraries handle what they do best.
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: "TanStack Router 1.0: Type-Safe Routing for React"
3
+ published: "2024-03-15"
4
+ excerpt: "TanStack Router 1.0 is stable! With 100% type-safe navigation, built-in search params, and first-class data loading, it is the most type-safe router for React."
5
+ authors:
6
+ - "Tanner Linsley"
7
+ ---
8
+
9
+ After years of development and months of beta testing, we are proud to announce TanStack Router 1.0 is stable and production-ready.
10
+
11
+ ## Why Another Router?
12
+
13
+ React Router has served the community well for years. But as TypeScript adoption has grown, developers have increasingly wanted a router that provides end-to-end type safety. TanStack Router was built from the ground up with TypeScript as a first-class citizen.
14
+
15
+ ## Key Features
16
+
17
+ ### 100% Type-Safe Navigation
18
+
19
+ Every `Link`, `navigate`, and `redirect` in TanStack Router is fully type-checked:
20
+
21
+ ```tsx
22
+ // TypeScript will error if:
23
+ // - The route does not exist
24
+ // - Required params are missing
25
+ // - Search params do not match the schema
26
+ <Link
27
+ to="/users/$userId/posts/$postId"
28
+ params={{ userId: '1', postId: '42' }}
29
+ search={{ sort: 'date' }}
30
+ />
31
+
32
+ // This would be a type error:
33
+ <Link
34
+ to="/users/$userId/posts/$postId"
35
+ params={{ userId: '1' }} // Error: missing postId
36
+ />
37
+ ```
38
+
39
+ ### First-Class Search Params
40
+
41
+ URL search parameters are validated and typed:
42
+
43
+ ```tsx
44
+ const productsRoute = createRoute({
45
+ path: '/products',
46
+ validateSearch: z.object({
47
+ page: z.number().default(1),
48
+ category: z.string().optional(),
49
+ sort: z.enum(['price', 'name', 'rating']).default('name'),
50
+ }),
51
+ })
52
+
53
+ // In your component:
54
+ const { page, category, sort } = productsRoute.useSearch()
55
+ // ^ All fully typed!
56
+ ```
57
+
58
+ ### Built-In Data Loading
59
+
60
+ No need for separate data fetching libraries for route-level data:
61
+
62
+ ```tsx
63
+ const userRoute = createRoute({
64
+ path: '/users/$userId',
65
+ loader: async ({ params, context }) => {
66
+ return context.queryClient.ensureQueryData({
67
+ queryKey: ['user', params.userId],
68
+ queryFn: () => fetchUser(params.userId),
69
+ })
70
+ },
71
+ })
72
+ ```
73
+
74
+ ### File-Based Routing
75
+
76
+ For larger applications, file-based routing generates the type-safe route tree automatically:
77
+
78
+ ```
79
+ routes/
80
+ __root.tsx
81
+ index.tsx
82
+ about.tsx
83
+ users.tsx
84
+ users.$userId.tsx
85
+ users.$userId.posts.tsx
86
+ users.$userId.posts.$postId.tsx
87
+ ```
88
+
89
+ The router plugin generates a `routeTree.gen.ts` file with complete type information.
90
+
91
+ ## Migration from React Router
92
+
93
+ We understand that migrating routers is a significant effort. We have published a detailed [migration guide](/en/router/docs/guides/migration-from-react-router) and built a codemod to help:
94
+
95
+ ```bash
96
+ npx @tanstack/router-codemod from-react-router ./src
97
+ ```
98
+
99
+ ## Performance
100
+
101
+ TanStack Router is designed for performance:
102
+
103
+ - **Route-level code splitting** works out of the box with file-based routing
104
+ - **Prefetching** on link hover ensures instant navigations
105
+ - **Parallel data loading** fetches data for all matched routes simultaneously
106
+ - **Stale-while-revalidate** keeps the UI responsive during refetches
107
+
108
+ > [!NOTE]
109
+ > TanStack Router pairs beautifully with TanStack Query. Use the router for route-level data loading and Query for component-level data fetching.
110
+
111
+ ## Get Started
112
+
113
+ Install TanStack Router today:
114
+
115
+ ```bash
116
+ npm install @tanstack/react-router @tanstack/router-plugin
117
+ ```
118
+
119
+ Read the [quick start guide](/en/router/docs/quick-start) to build your first type-safe route.
120
+
121
+ Thank you to everyone who contributed during the alpha and beta phases. Your feedback shaped this release into something we are truly proud of.