@tanstack/cta-framework-react-cra 0.33.0 → 0.34.0
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.
- package/add-ons/drizzle/assets/_dot_env.local.append.ejs +7 -0
- package/add-ons/drizzle/assets/drizzle.config.ts.ejs +13 -0
- package/add-ons/drizzle/assets/public/drizzle.svg +1 -0
- package/add-ons/drizzle/assets/src/db/index.ts.ejs +27 -0
- package/add-ons/drizzle/assets/src/db/schema.ts.ejs +32 -0
- package/add-ons/drizzle/assets/src/routes/demo/drizzle.tsx +187 -0
- package/add-ons/drizzle/info.json +32 -0
- package/add-ons/drizzle/package.json.ejs +24 -0
- package/add-ons/drizzle/small-logo.svg +1 -0
- package/add-ons/start/assets/src/routes/demo/start.api-request.tsx.ejs +1 -1
- package/add-ons/start/assets/src/routes/index.tsx.ejs +127 -141
- package/hosts/cloudflare/assets/{wrangler.json → wrangler.jsonc} +1 -4
- package/package.json +2 -2
- package/project/base/_dot_gitignore +1 -0
- package/tests/snapshots/react-cra/cr-js-form-npm.json +1 -1
- package/tests/snapshots/react-cra/cr-js-npm.json +1 -1
- package/tests/snapshots/react-cra/cr-ts-npm.json +1 -1
- package/tests/snapshots/react-cra/cr-ts-start-npm.json +3 -3
- package/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json +3 -3
- package/tests/snapshots/react-cra/fr-ts-biome-npm.json +2 -2
- package/tests/snapshots/react-cra/fr-ts-npm.json +1 -1
- package/tests/snapshots/react-cra/fr-ts-tw-npm.json +1 -1
- package/toolchains/biome/assets/biome.json +2 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<% if (addOnOption.drizzle.database === 'postgresql') { %>
|
|
2
|
+
# Database URL for PostgreSQL
|
|
3
|
+
DATABASE_URL="postgresql://username:password@localhost:5432/mydb"<% } else if (addOnOption.drizzle.database === 'mysql') { %>
|
|
4
|
+
# Database URL for MySQL
|
|
5
|
+
DATABASE_URL="mysql://username:password@localhost:3306/mydb"<% } else if (addOnOption.drizzle.database === 'sqlite') { %>
|
|
6
|
+
# Database URL for SQLite
|
|
7
|
+
DATABASE_URL="file:./dev.db"<% } %>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { config } from "dotenv";
|
|
2
|
+
import { defineConfig } from 'drizzle-kit';
|
|
3
|
+
|
|
4
|
+
config();
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
out: "./drizzle",
|
|
8
|
+
schema: "./src/db/schema.ts",
|
|
9
|
+
dialect: '<%= addOnOption.drizzle.database %>',
|
|
10
|
+
dbCredentials: {
|
|
11
|
+
url: process.env.DATABASE_URL,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="160" fill="none" viewBox="0 0 160 160"><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 43.48 67.304)"/><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 76.94 46.534)"/><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 128.424 46.535)"/><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 94.957 67.304)"/></svg>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { config } from 'dotenv'
|
|
2
|
+
<% if (addOnOption.drizzle.database === 'postgresql') { %>
|
|
3
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
4
|
+
import { Pool } from 'pg';
|
|
5
|
+
<% } else if (addOnOption.drizzle.database === 'mysql') {%>
|
|
6
|
+
import { drizzle } from 'drizzle-orm/mysql2';
|
|
7
|
+
import mysql from 'mysql2/promise';
|
|
8
|
+
<% } else if (addOnOption.drizzle.database === 'sqlite') {%>
|
|
9
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
10
|
+
import Database from 'better-sqlite3';
|
|
11
|
+
<% } %>
|
|
12
|
+
import * as schema from './schema.ts'
|
|
13
|
+
|
|
14
|
+
config()
|
|
15
|
+
|
|
16
|
+
<% if (addOnOption.drizzle.database === 'sqlite') { %>
|
|
17
|
+
const sqlite = new Database(process.env.DATABASE_URL!);
|
|
18
|
+
export const db = drizzle(sqlite, { schema });
|
|
19
|
+
<% } else if (addOnOption.drizzle.database === 'postgresql') { %>
|
|
20
|
+
const pool = new Pool({
|
|
21
|
+
connectionString: process.env.DATABASE_URL!,
|
|
22
|
+
});
|
|
23
|
+
export const db = drizzle(pool, { schema });
|
|
24
|
+
<% } else if (addOnOption.drizzle.database === 'mysql') { %>
|
|
25
|
+
const connection = await mysql.createConnection(process.env.DATABASE_URL!);
|
|
26
|
+
export const db = drizzle(connection, { schema });
|
|
27
|
+
<% } %>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<% if (addOnOption.drizzle.database === 'postgresql') { %>
|
|
2
|
+
import { pgTable, serial, text, timestamp } from
|
|
3
|
+
'drizzle-orm/pg-core';
|
|
4
|
+
|
|
5
|
+
export const todos = pgTable('todos', {
|
|
6
|
+
id: serial('id').primaryKey(),
|
|
7
|
+
title: text('title').notNull(),
|
|
8
|
+
createdAt: timestamp('created_at').defaultNow(),
|
|
9
|
+
});
|
|
10
|
+
<% } else if (addOnOption.drizzle.database === 'mysql') {
|
|
11
|
+
%>
|
|
12
|
+
import { mysqlTable, int, text, timestamp } from
|
|
13
|
+
'drizzle-orm/mysql-core';
|
|
14
|
+
|
|
15
|
+
export const todos = mysqlTable('todos', {
|
|
16
|
+
id: int('id').primaryKey().autoincrement(),
|
|
17
|
+
title: text('title').notNull(),
|
|
18
|
+
createdAt: timestamp('created_at', { mode: 'date' }).defaultNow(),
|
|
19
|
+
});
|
|
20
|
+
<% } else if (addOnOption.drizzle.database === 'sqlite') {
|
|
21
|
+
%>
|
|
22
|
+
import { sqliteTable, integer, text } from
|
|
23
|
+
'drizzle-orm/sqlite-core';
|
|
24
|
+
import { sql } from 'drizzle-orm';
|
|
25
|
+
|
|
26
|
+
export const todos = sqliteTable('todos', {
|
|
27
|
+
id: integer('id', { mode: 'number' }).primaryKey({
|
|
28
|
+
autoIncrement: true }),
|
|
29
|
+
title: text('title').notNull(),
|
|
30
|
+
createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`(unixepoch())`),
|
|
31
|
+
});
|
|
32
|
+
<% } %>
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { createFileRoute, useRouter } from '@tanstack/react-router'
|
|
2
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
3
|
+
import { db } from '@/db'
|
|
4
|
+
import { desc } from 'drizzle-orm'
|
|
5
|
+
import { todos } from '@/db/schema'
|
|
6
|
+
|
|
7
|
+
const getTodos = createServerFn({
|
|
8
|
+
method: 'GET',
|
|
9
|
+
}).handler(async () => {
|
|
10
|
+
return await db.query.todos.findMany({
|
|
11
|
+
orderBy: [desc(todos.createdAt)],
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const createTodo = createServerFn({
|
|
16
|
+
method: 'POST',
|
|
17
|
+
})
|
|
18
|
+
.inputValidator((data: { title: string }) => data)
|
|
19
|
+
.handler(async ({ data }) => {
|
|
20
|
+
await db.insert(todos).values({ title: data.title })
|
|
21
|
+
return { success: true }
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export const Route = createFileRoute('/demo/drizzle')({
|
|
25
|
+
component: DemoDrizzle,
|
|
26
|
+
loader: async () => await getTodos(),
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
function DemoDrizzle() {
|
|
30
|
+
const router = useRouter()
|
|
31
|
+
const todos = Route.useLoaderData()
|
|
32
|
+
|
|
33
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
34
|
+
e.preventDefault()
|
|
35
|
+
const formData = new FormData(e.target as HTMLFormElement)
|
|
36
|
+
const title = formData.get('title') as string
|
|
37
|
+
|
|
38
|
+
if (!title) return
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
await createTodo({ data: { title } })
|
|
42
|
+
router.invalidate()
|
|
43
|
+
;(e.target as HTMLFormElement).reset()
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('Failed to create todo:', error)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
className="flex items-center justify-center min-h-screen p-4 text-white"
|
|
52
|
+
style={{
|
|
53
|
+
background:
|
|
54
|
+
'linear-gradient(135deg, #0c1a2b 0%, #1a2332 50%, #16202e 100%)',
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<div
|
|
58
|
+
className="w-full max-w-2xl p-8 rounded-xl shadow-2xl border border-white/10"
|
|
59
|
+
style={{
|
|
60
|
+
background:
|
|
61
|
+
'linear-gradient(135deg, rgba(22, 32, 46, 0.95) 0%, rgba(12, 26, 43, 0.95) 100%)',
|
|
62
|
+
backdropFilter: 'blur(10px)',
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
<div
|
|
66
|
+
className="flex items-center justify-center gap-4 mb-8 p-4 rounded-lg"
|
|
67
|
+
style={{
|
|
68
|
+
background:
|
|
69
|
+
'linear-gradient(90deg, rgba(93, 103, 227, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%)',
|
|
70
|
+
border: '1px solid rgba(93, 103, 227, 0.2)',
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<div className="relative group">
|
|
74
|
+
<div className="absolute -inset-2 bg-gradient-to-r from-indigo-500 via-purple-500 to-indigo-500 rounded-lg blur-lg opacity-60 group-hover:opacity-100 transition duration-500"></div>
|
|
75
|
+
<div className="relative bg-gradient-to-br from-indigo-600 to-purple-600 p-3 rounded-lg">
|
|
76
|
+
<img
|
|
77
|
+
src="/drizzle.svg"
|
|
78
|
+
alt="Drizzle Logo"
|
|
79
|
+
className="w-8 h-8 transform group-hover:scale-110 transition-transform duration-300"
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
<h1 className="text-3xl font-bold bg-gradient-to-r from-indigo-300 via-purple-300 to-indigo-300 text-transparent bg-clip-text">
|
|
84
|
+
Drizzle Database Demo
|
|
85
|
+
</h1>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<h2 className="text-2xl font-bold mb-4 text-indigo-200">Todos</h2>
|
|
89
|
+
|
|
90
|
+
<ul className="space-y-3 mb-6">
|
|
91
|
+
{todos.map((todo) => (
|
|
92
|
+
<li
|
|
93
|
+
key={todo.id}
|
|
94
|
+
className="rounded-lg p-4 shadow-md border transition-all hover:scale-[1.02] cursor-pointer group"
|
|
95
|
+
style={{
|
|
96
|
+
background:
|
|
97
|
+
'linear-gradient(135deg, rgba(93, 103, 227, 0.15) 0%, rgba(139, 92, 246, 0.15) 100%)',
|
|
98
|
+
borderColor: 'rgba(93, 103, 227, 0.3)',
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
<div className="flex items-center justify-between">
|
|
102
|
+
<span className="text-lg font-medium text-white group-hover:text-indigo-200 transition-colors">
|
|
103
|
+
{todo.title}
|
|
104
|
+
</span>
|
|
105
|
+
<span className="text-xs text-indigo-300/70">#{todo.id}</span>
|
|
106
|
+
</div>
|
|
107
|
+
</li>
|
|
108
|
+
))}
|
|
109
|
+
{todos.length === 0 && (
|
|
110
|
+
<li className="text-center py-8 text-indigo-300/70">
|
|
111
|
+
No todos yet. Create one below!
|
|
112
|
+
</li>
|
|
113
|
+
)}
|
|
114
|
+
</ul>
|
|
115
|
+
|
|
116
|
+
<form onSubmit={handleSubmit} className="flex gap-2">
|
|
117
|
+
<input
|
|
118
|
+
type="text"
|
|
119
|
+
name="title"
|
|
120
|
+
placeholder="Add a new todo..."
|
|
121
|
+
className="flex-1 px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 transition-all text-white placeholder-indigo-300/50"
|
|
122
|
+
style={{
|
|
123
|
+
background: 'rgba(93, 103, 227, 0.1)',
|
|
124
|
+
borderColor: 'rgba(93, 103, 227, 0.3)',
|
|
125
|
+
focusRing: 'rgba(93, 103, 227, 0.5)',
|
|
126
|
+
}}
|
|
127
|
+
/>
|
|
128
|
+
<button
|
|
129
|
+
type="submit"
|
|
130
|
+
className="px-6 py-3 font-semibold rounded-lg shadow-lg transition-all duration-200 hover:shadow-xl hover:scale-105 active:scale-95 whitespace-nowrap"
|
|
131
|
+
style={{
|
|
132
|
+
background: 'linear-gradient(135deg, #5d67e3 0%, #8b5cf6 100%)',
|
|
133
|
+
color: 'white',
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
Add Todo
|
|
137
|
+
</button>
|
|
138
|
+
</form>
|
|
139
|
+
|
|
140
|
+
<div
|
|
141
|
+
className="mt-8 p-6 rounded-lg border"
|
|
142
|
+
style={{
|
|
143
|
+
background: 'rgba(93, 103, 227, 0.05)',
|
|
144
|
+
borderColor: 'rgba(93, 103, 227, 0.2)',
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
<h3 className="text-lg font-semibold mb-2 text-indigo-200">
|
|
148
|
+
Powered by Drizzle ORM
|
|
149
|
+
</h3>
|
|
150
|
+
<p className="text-sm text-indigo-300/80 mb-4">
|
|
151
|
+
Next-generation ORM for Node.js & TypeScript with PostgreSQL
|
|
152
|
+
</p>
|
|
153
|
+
<div className="space-y-2 text-sm">
|
|
154
|
+
<p className="text-indigo-200 font-medium">Setup Instructions:</p>
|
|
155
|
+
<ol className="list-decimal list-inside space-y-2 text-indigo-300/80">
|
|
156
|
+
<li>
|
|
157
|
+
Configure your{' '}
|
|
158
|
+
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
159
|
+
DATABASE_URL
|
|
160
|
+
</code>{' '}
|
|
161
|
+
in .env.local
|
|
162
|
+
</li>
|
|
163
|
+
<li>
|
|
164
|
+
Run:{' '}
|
|
165
|
+
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
166
|
+
npx drizzle-kit generate
|
|
167
|
+
</code>
|
|
168
|
+
</li>
|
|
169
|
+
<li>
|
|
170
|
+
Run:{' '}
|
|
171
|
+
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
172
|
+
npx drizzle-kit migrate
|
|
173
|
+
</code>
|
|
174
|
+
</li>
|
|
175
|
+
<li>
|
|
176
|
+
Optional:{' '}
|
|
177
|
+
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
178
|
+
npx drizzle-kit studio
|
|
179
|
+
</code>
|
|
180
|
+
</li>
|
|
181
|
+
</ol>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
)
|
|
187
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Drizzle",
|
|
3
|
+
"description": "Add Drizzle ORM to your application.",
|
|
4
|
+
"phase": "add-on",
|
|
5
|
+
"type": "add-on",
|
|
6
|
+
"priority": 48,
|
|
7
|
+
"link": "https://orm.drizzle.team/",
|
|
8
|
+
"modes": ["file-router"],
|
|
9
|
+
"dependsOn": ["start"],
|
|
10
|
+
"options": {
|
|
11
|
+
"database": {
|
|
12
|
+
"type": "select",
|
|
13
|
+
"label": "Database Provider",
|
|
14
|
+
"description": "Choose your database provider",
|
|
15
|
+
"default": "postgresql",
|
|
16
|
+
"options": [
|
|
17
|
+
{ "value": "postgresql", "label": "PostgreSQL" },
|
|
18
|
+
{ "value": "sqlite", "label": "SQLite" },
|
|
19
|
+
{ "value": "mysql", "label": "MySQL" }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"routes": [
|
|
24
|
+
{
|
|
25
|
+
"icon": "Database",
|
|
26
|
+
"url": "/demo/drizzle",
|
|
27
|
+
"name": "Drizzle",
|
|
28
|
+
"path": "src/routes/demo/drizzle.tsx",
|
|
29
|
+
"jsName": "DemoDrizzle"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"drizzle-orm": "^0.39.0",
|
|
4
|
+
"drizzle-kit": "^0.30.0"<% if (addOnOption.drizzle.database === 'postgresql') { %>,
|
|
5
|
+
"pg": "^8.11.0"<% } %><% if (addOnOption.drizzle.database === 'mysql') { %>,
|
|
6
|
+
"mysql2": "^3.6.0"<% } %><% if (addOnOption.drizzle.database === 'sqlite') { %>,
|
|
7
|
+
"better-sqlite3": "^9.4.0"<% } %>
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"dotenv": "^16.0.0",
|
|
11
|
+
"tsx": "^4.0.0",
|
|
12
|
+
<% if (addOnOption.drizzle.database === 'postgresql') { %>
|
|
13
|
+
"@types/pg": "^8.10.0"<% } %><% if (addOnOption.drizzle.database === 'mysql') { %>
|
|
14
|
+
"@types/mysql2": "^3.6.0"<% } %><% if (addOnOption.drizzle.database === 'sqlite') { %>
|
|
15
|
+
"@types/better-sqlite3": "^7.6.0"<% } %>
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"db:generate": "drizzle-kit generate",
|
|
19
|
+
"db:migrate": "drizzle-kit migrate",
|
|
20
|
+
"db:push": "drizzle-kit push",
|
|
21
|
+
"db:pull": "drizzle-kit pull",
|
|
22
|
+
"db:studio": "drizzle-kit studio"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="160" fill="none" viewBox="0 0 160 160"><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 43.48 67.304)"/><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 76.94 46.534)"/><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 128.424 46.535)"/><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 94.957 67.304)"/></svg>
|
|
@@ -6,7 +6,7 @@ import { useEffect, useState } from 'react'
|
|
|
6
6
|
import { createFileRoute } from '@tanstack/react-router'
|
|
7
7
|
|
|
8
8
|
function getNames() {
|
|
9
|
-
return fetch('/demo/api/names').then((res) => res.json())
|
|
9
|
+
return fetch('/demo/api/names').then((res) => res.json() as Promise<string[]>)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export const Route = createFileRoute('/demo/start/api-request')({
|
|
@@ -1,154 +1,140 @@
|
|
|
1
|
-
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import "../App.css";
|
|
1
|
+
import { createFileRoute } from "@tanstack/react-router"; <% if (!tailwind) { %>
|
|
2
|
+
import logo from "../logo.svg"
|
|
3
|
+
import "../App.css"
|
|
5
4
|
<% } else { %>
|
|
6
5
|
import {
|
|
7
|
-
Zap,
|
|
8
|
-
Server,
|
|
9
|
-
Route as RouteIcon,
|
|
10
|
-
Shield,
|
|
11
|
-
Waves,
|
|
12
|
-
Sparkles,
|
|
13
|
-
} from "lucide-react";
|
|
6
|
+
Zap, Server, Route as RouteIcon, Shield, Waves, Sparkles, } from "lucide-react";
|
|
14
7
|
<% } %>
|
|
15
8
|
|
|
16
|
-
export const Route = createFileRoute("/")({
|
|
17
|
-
component: App,
|
|
18
|
-
});
|
|
9
|
+
export const Route = createFileRoute("/")({ component: App, });
|
|
19
10
|
|
|
20
|
-
function App() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
icon: <Sparkles className="w-12 h-12 text-cyan-400" />,
|
|
55
|
-
title: "Next Generation Ready",
|
|
56
|
-
description:
|
|
57
|
-
"Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.",
|
|
58
|
-
},
|
|
59
|
-
];
|
|
11
|
+
function App() { <% if (tailwind) { %>
|
|
12
|
+
const features = [
|
|
13
|
+
{
|
|
14
|
+
icon: <Zap className="w-12 h-12 text-cyan-400" />,
|
|
15
|
+
title: "Powerful Server Functions",
|
|
16
|
+
description: "Write server-side code that seamlessly integrates with your client components. Type-safe, secure, and simple.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
icon: <Server className="w-12 h-12 text-cyan-400" />,
|
|
20
|
+
title: "Flexible Server Side Rendering",
|
|
21
|
+
description: "Full-document SSR, streaming, and progressive enhancement out of the box. Control exactly what renders where.",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
icon: <RouteIcon className="w-12 h-12 text-cyan-400" />,
|
|
25
|
+
title: "API Routes",
|
|
26
|
+
description: "Build type-safe API endpoints alongside your application. No separate backend needed.",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
icon: <Shield className="w-12 h-12 text-cyan-400" />,
|
|
30
|
+
title: "Strongly Typed Everything",
|
|
31
|
+
description: "End-to-end type safety from server to client. Catch errors before they reach production.",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
icon: <Waves className="w-12 h-12 text-cyan-400" />,
|
|
35
|
+
title: "Full Streaming Support",
|
|
36
|
+
description: "Stream data from server to client progressively. Perfect for AI applications and real-time updates.",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
icon: <Sparkles className="w-12 h-12 text-cyan-400" />,
|
|
40
|
+
title: "Next Generation Ready",
|
|
41
|
+
description: "Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.",
|
|
42
|
+
},
|
|
43
|
+
];
|
|
60
44
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<p className="text-lg text-gray-400 max-w-3xl mx-auto mb-8">
|
|
83
|
-
Full-stack framework powered by TanStack Router for React and Solid.
|
|
84
|
-
Build modern applications with server functions, streaming, and type
|
|
85
|
-
safety.
|
|
86
|
-
</p>
|
|
87
|
-
<div className="flex flex-col items-center gap-4">
|
|
88
|
-
<a
|
|
89
|
-
href="https://tanstack.com/start"
|
|
90
|
-
target="_blank"
|
|
91
|
-
rel="noopener noreferrer"
|
|
92
|
-
className="px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50"
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
className="min-h-screen bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900"
|
|
48
|
+
>
|
|
49
|
+
<section className="relative py-20 px-6 text-center overflow-hidden">
|
|
50
|
+
<div
|
|
51
|
+
className="absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10"
|
|
52
|
+
></div>
|
|
53
|
+
<div className="relative max-w-5xl mx-auto">
|
|
54
|
+
<div className="flex items-center justify-center gap-6 mb-6">
|
|
55
|
+
<img
|
|
56
|
+
src="/tanstack-circle-logo.png"
|
|
57
|
+
alt="TanStack Logo"
|
|
58
|
+
className="w-24 h-24 md:w-32 md:h-32"
|
|
59
|
+
/>
|
|
60
|
+
<h1
|
|
61
|
+
className="text-6xl md:text-7xl font-black text-white [letter-spacing:-0.08em]"
|
|
62
|
+
>
|
|
63
|
+
<span className="text-gray-300">TANSTACK</span>{" "}
|
|
64
|
+
<span
|
|
65
|
+
className="bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent"
|
|
93
66
|
>
|
|
94
|
-
|
|
95
|
-
</
|
|
96
|
-
|
|
97
|
-
Begin your TanStack Start journey by editing{" "}
|
|
98
|
-
<code className="px-2 py-1 bg-slate-700 rounded text-cyan-400">
|
|
99
|
-
/src/routes/index.tsx
|
|
100
|
-
</code>
|
|
101
|
-
</p>
|
|
102
|
-
</div>
|
|
67
|
+
START
|
|
68
|
+
</span>
|
|
69
|
+
</h1>
|
|
103
70
|
</div>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<section className="py-16 px-6 max-w-7xl mx-auto">
|
|
107
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
108
|
-
{features.map((feature, index) => (
|
|
109
|
-
<div
|
|
110
|
-
key={index}
|
|
111
|
-
className="bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10"
|
|
112
|
-
>
|
|
113
|
-
<div className="mb-4">{feature.icon}</div>
|
|
114
|
-
<h3 className="text-xl font-semibold text-white mb-3">
|
|
115
|
-
{feature.title}
|
|
116
|
-
</h3>
|
|
117
|
-
<p className="text-gray-400 leading-relaxed">
|
|
118
|
-
{feature.description}
|
|
119
|
-
</p>
|
|
120
|
-
</div>
|
|
121
|
-
))}
|
|
122
|
-
</div>
|
|
123
|
-
</section>
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
126
|
-
<% } else { %>
|
|
127
|
-
return (
|
|
128
|
-
<div className="App">
|
|
129
|
-
<header className="App-header">
|
|
130
|
-
<img src={logo} className="App-logo" alt="logo" />
|
|
131
|
-
<p>
|
|
132
|
-
Edit <code>src/routes/index.tsx</code> and save to reload.
|
|
71
|
+
<p className="text-2xl md:text-3xl text-gray-300 mb-4 font-light">
|
|
72
|
+
The framework for next generation AI applications
|
|
133
73
|
</p>
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
>
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
74
|
+
<p className="text-lg text-gray-400 max-w-3xl mx-auto mb-8">
|
|
75
|
+
Full-stack framework powered by TanStack Router for React and Solid.
|
|
76
|
+
Build modern applications with server functions, streaming, and type
|
|
77
|
+
safety.
|
|
78
|
+
</p>
|
|
79
|
+
<div className="flex flex-col items-center gap-4">
|
|
80
|
+
<a
|
|
81
|
+
href="https://tanstack.com/start"
|
|
82
|
+
target="_blank"
|
|
83
|
+
rel="noopener noreferrer"
|
|
84
|
+
className="px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50"
|
|
85
|
+
>
|
|
86
|
+
Documentation
|
|
87
|
+
</a>
|
|
88
|
+
<p className="text-gray-400 text-sm mt-2">
|
|
89
|
+
Begin your TanStack Start journey by editing{" "}
|
|
90
|
+
<code className="px-2 py-1 bg-slate-700 rounded text-cyan-400">
|
|
91
|
+
/src/routes/index.tsx
|
|
92
|
+
</code>
|
|
93
|
+
</p>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</section>
|
|
97
|
+
|
|
98
|
+
<section className="py-16 px-6 max-w-7xl mx-auto">
|
|
99
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
100
|
+
{features.map((feature, index) => (
|
|
101
|
+
<div
|
|
102
|
+
key="{index}"
|
|
103
|
+
className="bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10"
|
|
147
104
|
>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
105
|
+
<div className="mb-4">{feature.icon}</div>
|
|
106
|
+
<h3 className="text-xl font-semibold text-white mb-3">
|
|
107
|
+
{feature.title}
|
|
108
|
+
</h3>
|
|
109
|
+
<p className="text-gray-400 leading-relaxed">{feature.description}</p>
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
</section>
|
|
114
|
+
</div>
|
|
115
|
+
); <% } else { %> return (
|
|
116
|
+
<div className="App">
|
|
117
|
+
<header className="App-header">
|
|
118
|
+
<img src="{logo}" className="App-logo" alt="logo" />
|
|
119
|
+
<p>Edit <code>src/routes/index.tsx</code> and save to reload.</p>
|
|
120
|
+
<a
|
|
121
|
+
className="App-link"
|
|
122
|
+
href="https://reactjs.org"
|
|
123
|
+
target="_blank"
|
|
124
|
+
rel="noopener noreferrer"
|
|
125
|
+
>
|
|
126
|
+
Learn React
|
|
127
|
+
</a>
|
|
128
|
+
<a
|
|
129
|
+
className="App-link"
|
|
130
|
+
href="https://tanstack.com"
|
|
131
|
+
target="_blank"
|
|
132
|
+
rel="noopener noreferrer"
|
|
133
|
+
>
|
|
134
|
+
Learn TanStack
|
|
135
|
+
</a>
|
|
136
|
+
</header>
|
|
137
|
+
</div>
|
|
152
138
|
);
|
|
153
139
|
<% } %>
|
|
154
140
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/cta-framework-react-cra",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "CTA Framework for React (Create React App)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "Jack Herrington <jherr@pobox.com>",
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@tanstack/cta-engine": "0.
|
|
26
|
+
"@tanstack/cta-engine": "0.34.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^24.6.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": true,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": false,\n \"typescript\": false,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": [\n \"form\"\n ]\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": false,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": false,\n \"typescript\": false,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": []\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": false,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": false,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": []\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": true,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": true,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": [\n \"start\"\n ]\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.output\n.vinxi\ntodos.json\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n.output\n.vinxi\ntodos.json\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"/src/router.tsx": "import { createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\n// Create a new router instance\nexport const getRouter = () => {\n return createRouter({\n routeTree,\n scrollRestoration: true,\n defaultPreloadStaleTime: 0,\n })\n}\n",
|
|
11
11
|
"/src/routes/__root.tsx": "import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nimport Header from '../components/Header'\n\nimport appCss from '../styles.css?url'\n\nexport const Route = createRootRoute({\n head: () => ({\n meta: [\n {\n charSet: 'utf-8',\n },\n {\n name: 'viewport',\n content: 'width=device-width, initial-scale=1',\n },\n {\n title: 'TanStack Start Starter',\n },\n ],\n links: [\n {\n rel: 'stylesheet',\n href: appCss,\n },\n ],\n }),\n\n shellComponent: RootDocument,\n})\n\nfunction RootDocument({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\">\n <head>\n <HeadContent />\n </head>\n <body>\n <Header />\n {children}\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n <Scripts />\n </body>\n </html>\n )\n}\n",
|
|
12
12
|
"/src/routes/demo/api.names.ts": "import { createFileRoute } from '@tanstack/react-router'\nimport { json } from '@tanstack/react-start'\n\nexport const Route = createFileRoute('/demo/api/names')({\n server: {\n handlers: {\n GET: () => json(['Alice', 'Bob', 'Charlie']),\n },\n },\n})\n",
|
|
13
|
-
"/src/routes/demo/start.api-request.tsx": "import { useEffect, useState } from 'react'\n\nimport { createFileRoute } from '@tanstack/react-router'\n\nfunction getNames() {\n return fetch('/demo/api/names').then((res) => res.json())\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const [names, setNames] = useState<Array<string>>([])\n\n useEffect(() => {\n getNames().then(setNames)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen p-4 text-white\"\n style={{\n backgroundColor: '#000',\n backgroundImage:\n 'radial-gradient(ellipse 60% 60% at 0% 100%, #444 0%, #222 60%, #000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start API Request Demo - Names List</h1>\n <ul className=\"mb-4 space-y-2\">\n {names.map((name) => (\n <li\n key={name}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{name}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
13
|
+
"/src/routes/demo/start.api-request.tsx": "import { useEffect, useState } from 'react'\n\nimport { createFileRoute } from '@tanstack/react-router'\n\nfunction getNames() {\n return fetch('/demo/api/names').then((res) => res.json() as Promise<string[]>)\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const [names, setNames] = useState<Array<string>>([])\n\n useEffect(() => {\n getNames().then(setNames)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen p-4 text-white\"\n style={{\n backgroundColor: '#000',\n backgroundImage:\n 'radial-gradient(ellipse 60% 60% at 0% 100%, #444 0%, #222 60%, #000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start API Request Demo - Names List</h1>\n <ul className=\"mb-4 space-y-2\">\n {names.map((name) => (\n <li\n key={name}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{name}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
14
14
|
"/src/routes/demo/start.server-funcs.tsx": "import fs from 'node:fs'\nimport { useCallback, useState } from 'react'\nimport { createFileRoute, useRouter } from '@tanstack/react-router'\nimport { createServerFn } from '@tanstack/react-start'\n\n/*\nconst loggingMiddleware = createMiddleware().server(\n async ({ next, request }) => {\n console.log(\"Request:\", request.url);\n return next();\n }\n);\nconst loggedServerFunction = createServerFn({ method: \"GET\" }).middleware([\n loggingMiddleware,\n]);\n*/\n\nconst TODOS_FILE = 'todos.json'\n\nasync function readTodos() {\n return JSON.parse(\n await fs.promises.readFile(TODOS_FILE, 'utf-8').catch(() =>\n JSON.stringify(\n [\n { id: 1, name: 'Get groceries' },\n { id: 2, name: 'Buy a new phone' },\n ],\n null,\n 2,\n ),\n ),\n )\n}\n\nconst getTodos = createServerFn({\n method: 'GET',\n}).handler(async () => await readTodos())\n\nconst addTodo = createServerFn({ method: 'POST' })\n .inputValidator((d: string) => d)\n .handler(async ({ data }) => {\n const todos = await readTodos()\n todos.push({ id: todos.length + 1, name: data })\n await fs.promises.writeFile(TODOS_FILE, JSON.stringify(todos, null, 2))\n return todos\n })\n\nexport const Route = createFileRoute('/demo/start/server-funcs')({\n component: Home,\n loader: async () => await getTodos(),\n})\n\nfunction Home() {\n const router = useRouter()\n let todos = Route.useLoaderData()\n\n const [todo, setTodo] = useState('')\n\n const submitTodo = useCallback(async () => {\n todos = await addTodo({ data: todo })\n setTodo('')\n router.invalidate()\n }, [addTodo, todo])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #23272a 0%, #18181b 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start Server Functions - Todo Example</h1>\n <ul className=\"mb-4 space-y-2\">\n {todos?.map((t) => (\n <li\n key={t.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{t.name}</span>\n </li>\n ))}\n </ul>\n <div className=\"flex flex-col gap-2\">\n <input\n type=\"text\"\n value={todo}\n onChange={(e) => setTodo(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n submitTodo()\n }\n }}\n placeholder=\"Enter a new todo...\"\n className=\"w-full px-4 py-3 rounded-lg border border-white/20 bg-white/10 backdrop-blur-sm text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent\"\n />\n <button\n disabled={todo.trim().length === 0}\n onClick={submitTodo}\n className=\"bg-blue-500 hover:bg-blue-600 disabled:bg-blue-500/50 disabled:cursor-not-allowed text-white font-bold py-3 px-4 rounded-lg transition-colors\"\n >\n Add todo\n </button>\n </div>\n </div>\n </div>\n )\n}\n",
|
|
15
15
|
"/src/routes/demo/start.ssr.data-only.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/data-only')({\n ssr: 'data-only',\n component: RouteComponent,\n loader: async () => await getPunkSongs(),\n})\n\nfunction RouteComponent() {\n const punkSongs = Route.useLoaderData()\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-pink-400\">\n Data Only SSR - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
16
16
|
"/src/routes/demo/start.ssr.full-ssr.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/full-ssr')({\n component: RouteComponent,\n loader: async () => await getPunkSongs(),\n})\n\nfunction RouteComponent() {\n const punkSongs = Route.useLoaderData()\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-purple-400\">\n Full SSR - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
17
17
|
"/src/routes/demo/start.ssr.index.tsx": "import { createFileRoute, Link } from '@tanstack/react-router'\n\nexport const Route = createFileRoute('/demo/start/ssr/')({\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-900 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-4xl font-bold mb-8 text-center bg-gradient-to-r from-pink-500 via-purple-500 to-green-400 bg-clip-text text-transparent\">\n SSR Demos\n </h1>\n <div className=\"flex flex-col gap-4\">\n <Link\n to=\"/demo/start/ssr/spa-mode\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-pink-600 to-pink-500 hover:from-pink-700 hover:to-pink-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-pink-500/50 border-2 border-pink-400\"\n >\n SPA Mode\n </Link>\n <Link\n to=\"/demo/start/ssr/full-ssr\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-purple-600 to-purple-500 hover:from-purple-700 hover:to-purple-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-purple-500/50 border-2 border-purple-400\"\n >\n Full SSR\n </Link>\n <Link\n to=\"/demo/start/ssr/data-only\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-green-500/50 border-2 border-green-400\"\n >\n Data Only\n </Link>\n </div>\n </div>\n </div>\n )\n}\n",
|
|
18
18
|
"/src/routes/demo/start.ssr.spa-mode.tsx": "import { useEffect, useState } from 'react'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/spa-mode')({\n ssr: false,\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const [punkSongs, setPunkSongs] = useState<\n Awaited<ReturnType<typeof getPunkSongs>>\n >([])\n\n useEffect(() => {\n getPunkSongs().then(setPunkSongs)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-green-400\">\n SPA Mode - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
19
|
-
"/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\
|
|
19
|
+
"/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport {\n Zap,\n Server,\n Route as RouteIcon,\n Shield,\n Waves,\n Sparkles,\n} from 'lucide-react'\n\nexport const Route = createFileRoute('/')({ component: App })\n\nfunction App() {\n const features = [\n {\n icon: <Zap className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Powerful Server Functions',\n description:\n 'Write server-side code that seamlessly integrates with your client components. Type-safe, secure, and simple.',\n },\n {\n icon: <Server className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Flexible Server Side Rendering',\n description:\n 'Full-document SSR, streaming, and progressive enhancement out of the box. Control exactly what renders where.',\n },\n {\n icon: <RouteIcon className=\"w-12 h-12 text-cyan-400\" />,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: <Shield className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Strongly Typed Everything',\n description:\n 'End-to-end type safety from server to client. Catch errors before they reach production.',\n },\n {\n icon: <Waves className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Full Streaming Support',\n description:\n 'Stream data from server to client progressively. Perfect for AI applications and real-time updates.',\n },\n {\n icon: <Sparkles className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Next Generation Ready',\n description:\n 'Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.',\n },\n ]\n\n return (\n <div className=\"min-h-screen bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900\">\n <section className=\"relative py-20 px-6 text-center overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10\"></div>\n <div className=\"relative max-w-5xl mx-auto\">\n <div className=\"flex items-center justify-center gap-6 mb-6\">\n <img\n src=\"/tanstack-circle-logo.png\"\n alt=\"TanStack Logo\"\n className=\"w-24 h-24 md:w-32 md:h-32\"\n />\n <h1 className=\"text-6xl md:text-7xl font-black text-white [letter-spacing:-0.08em]\">\n <span className=\"text-gray-300\">TANSTACK</span>{' '}\n <span className=\"bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent\">\n START\n </span>\n </h1>\n </div>\n <p className=\"text-2xl md:text-3xl text-gray-300 mb-4 font-light\">\n The framework for next generation AI applications\n </p>\n <p className=\"text-lg text-gray-400 max-w-3xl mx-auto mb-8\">\n Full-stack framework powered by TanStack Router for React and Solid.\n Build modern applications with server functions, streaming, and type\n safety.\n </p>\n <div className=\"flex flex-col items-center gap-4\">\n <a\n href=\"https://tanstack.com/start\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50\"\n >\n Documentation\n </a>\n <p className=\"text-gray-400 text-sm mt-2\">\n Begin your TanStack Start journey by editing{' '}\n <code className=\"px-2 py-1 bg-slate-700 rounded text-cyan-400\">\n /src/routes/index.tsx\n </code>\n </p>\n </div>\n </div>\n </section>\n\n <section className=\"py-16 px-6 max-w-7xl mx-auto\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {features.map((feature, index) => (\n <div\n key=\"{index}\"\n className=\"bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10\"\n >\n <div className=\"mb-4\">{feature.icon}</div>\n <h3 className=\"text-xl font-semibold text-white mb-3\">\n {feature.title}\n </h3>\n <p className=\"text-gray-400 leading-relaxed\">\n {feature.description}\n </p>\n </div>\n ))}\n </div>\n </section>\n </div>\n )\n}\n",
|
|
20
20
|
"/src/styles.css": "@import \"tailwindcss\";\n\nbody {\n @apply m-0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
|
|
21
21
|
"README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run start\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses [Tailwind CSS](https://tailwindcss.com/) for styling.\n\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.tsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results as { name: string }[]),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.tsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
|
|
22
22
|
"package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite dev --port 3000\",\n \"build\": \"vite build\",\n \"serve\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/react-router-ssr-query\": \"^1.131.7\",\n \"@tanstack/react-start\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"lucide-react\": \"^0.544.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^5.1.4\"\n },\n \"devDependencies\": {\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.0.8\",\n \"@types/react-dom\": \"^19.0.3\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": true,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": true,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": [\n \"start\",\n \"tanstack-query\"\n ]\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.output\n.vinxi\ntodos.json\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n.output\n.vinxi\ntodos.json\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
"/src/routes/__root.tsx": "import {\n HeadContent,\n Scripts,\n createRootRouteWithContext,\n} from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nimport Header from '../components/Header'\n\nimport TanStackQueryDevtools from '../integrations/tanstack-query/devtools'\n\nimport appCss from '../styles.css?url'\n\nimport type { QueryClient } from '@tanstack/react-query'\n\ninterface MyRouterContext {\n queryClient: QueryClient\n}\n\nexport const Route = createRootRouteWithContext<MyRouterContext>()({\n head: () => ({\n meta: [\n {\n charSet: 'utf-8',\n },\n {\n name: 'viewport',\n content: 'width=device-width, initial-scale=1',\n },\n {\n title: 'TanStack Start Starter',\n },\n ],\n links: [\n {\n rel: 'stylesheet',\n href: appCss,\n },\n ],\n }),\n\n shellComponent: RootDocument,\n})\n\nfunction RootDocument({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\">\n <head>\n <HeadContent />\n </head>\n <body>\n <Header />\n {children}\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n TanStackQueryDevtools,\n ]}\n />\n <Scripts />\n </body>\n </html>\n )\n}\n",
|
|
14
14
|
"/src/routes/demo/api.names.ts": "import { createFileRoute } from '@tanstack/react-router'\nimport { json } from '@tanstack/react-start'\n\nexport const Route = createFileRoute('/demo/api/names')({\n server: {\n handlers: {\n GET: () => json(['Alice', 'Bob', 'Charlie']),\n },\n },\n})\n",
|
|
15
15
|
"/src/routes/demo/api.tq-todos.ts": "import { createFileRoute } from '@tanstack/react-router'\n\nconst todos = [\n {\n id: 1,\n name: 'Buy groceries',\n },\n {\n id: 2,\n name: 'Buy mobile phone',\n },\n {\n id: 3,\n name: 'Buy laptop',\n },\n]\n\nexport const Route = createFileRoute('/demo/api/tq-todos')({\n server: {\n handlers: {\n GET: () => {\n return Response.json(todos)\n },\n POST: async ({ request }) => {\n const name = await request.json()\n const todo = {\n id: todos.length + 1,\n name,\n }\n todos.push(todo)\n return Response.json(todo)\n },\n },\n },\n})\n",
|
|
16
|
-
"/src/routes/demo/start.api-request.tsx": "import { useQuery } from '@tanstack/react-query'\n\nimport { createFileRoute } from '@tanstack/react-router'\n\nfunction getNames() {\n return fetch('/demo/api/names').then((res) => res.json())\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const { data: names = [] } = useQuery({\n queryKey: ['names'],\n queryFn: getNames,\n })\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen p-4 text-white\"\n style={{\n backgroundColor: '#000',\n backgroundImage:\n 'radial-gradient(ellipse 60% 60% at 0% 100%, #444 0%, #222 60%, #000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start API Request Demo - Names List</h1>\n <ul className=\"mb-4 space-y-2\">\n {names.map((name) => (\n <li\n key={name}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{name}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
16
|
+
"/src/routes/demo/start.api-request.tsx": "import { useQuery } from '@tanstack/react-query'\n\nimport { createFileRoute } from '@tanstack/react-router'\n\nfunction getNames() {\n return fetch('/demo/api/names').then((res) => res.json() as Promise<string[]>)\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const { data: names = [] } = useQuery({\n queryKey: ['names'],\n queryFn: getNames,\n })\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen p-4 text-white\"\n style={{\n backgroundColor: '#000',\n backgroundImage:\n 'radial-gradient(ellipse 60% 60% at 0% 100%, #444 0%, #222 60%, #000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start API Request Demo - Names List</h1>\n <ul className=\"mb-4 space-y-2\">\n {names.map((name) => (\n <li\n key={name}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{name}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
17
17
|
"/src/routes/demo/start.server-funcs.tsx": "import fs from 'node:fs'\nimport { useCallback, useState } from 'react'\nimport { createFileRoute, useRouter } from '@tanstack/react-router'\nimport { createServerFn } from '@tanstack/react-start'\n\n/*\nconst loggingMiddleware = createMiddleware().server(\n async ({ next, request }) => {\n console.log(\"Request:\", request.url);\n return next();\n }\n);\nconst loggedServerFunction = createServerFn({ method: \"GET\" }).middleware([\n loggingMiddleware,\n]);\n*/\n\nconst TODOS_FILE = 'todos.json'\n\nasync function readTodos() {\n return JSON.parse(\n await fs.promises.readFile(TODOS_FILE, 'utf-8').catch(() =>\n JSON.stringify(\n [\n { id: 1, name: 'Get groceries' },\n { id: 2, name: 'Buy a new phone' },\n ],\n null,\n 2,\n ),\n ),\n )\n}\n\nconst getTodos = createServerFn({\n method: 'GET',\n}).handler(async () => await readTodos())\n\nconst addTodo = createServerFn({ method: 'POST' })\n .inputValidator((d: string) => d)\n .handler(async ({ data }) => {\n const todos = await readTodos()\n todos.push({ id: todos.length + 1, name: data })\n await fs.promises.writeFile(TODOS_FILE, JSON.stringify(todos, null, 2))\n return todos\n })\n\nexport const Route = createFileRoute('/demo/start/server-funcs')({\n component: Home,\n loader: async () => await getTodos(),\n})\n\nfunction Home() {\n const router = useRouter()\n let todos = Route.useLoaderData()\n\n const [todo, setTodo] = useState('')\n\n const submitTodo = useCallback(async () => {\n todos = await addTodo({ data: todo })\n setTodo('')\n router.invalidate()\n }, [addTodo, todo])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #23272a 0%, #18181b 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start Server Functions - Todo Example</h1>\n <ul className=\"mb-4 space-y-2\">\n {todos?.map((t) => (\n <li\n key={t.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{t.name}</span>\n </li>\n ))}\n </ul>\n <div className=\"flex flex-col gap-2\">\n <input\n type=\"text\"\n value={todo}\n onChange={(e) => setTodo(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n submitTodo()\n }\n }}\n placeholder=\"Enter a new todo...\"\n className=\"w-full px-4 py-3 rounded-lg border border-white/20 bg-white/10 backdrop-blur-sm text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent\"\n />\n <button\n disabled={todo.trim().length === 0}\n onClick={submitTodo}\n className=\"bg-blue-500 hover:bg-blue-600 disabled:bg-blue-500/50 disabled:cursor-not-allowed text-white font-bold py-3 px-4 rounded-lg transition-colors\"\n >\n Add todo\n </button>\n </div>\n </div>\n </div>\n )\n}\n",
|
|
18
18
|
"/src/routes/demo/start.ssr.data-only.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/data-only')({\n ssr: 'data-only',\n component: RouteComponent,\n loader: async () => await getPunkSongs(),\n})\n\nfunction RouteComponent() {\n const punkSongs = Route.useLoaderData()\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-pink-400\">\n Data Only SSR - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
19
19
|
"/src/routes/demo/start.ssr.full-ssr.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/full-ssr')({\n component: RouteComponent,\n loader: async () => await getPunkSongs(),\n})\n\nfunction RouteComponent() {\n const punkSongs = Route.useLoaderData()\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-purple-400\">\n Full SSR - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
20
20
|
"/src/routes/demo/start.ssr.index.tsx": "import { createFileRoute, Link } from '@tanstack/react-router'\n\nexport const Route = createFileRoute('/demo/start/ssr/')({\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-900 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-4xl font-bold mb-8 text-center bg-gradient-to-r from-pink-500 via-purple-500 to-green-400 bg-clip-text text-transparent\">\n SSR Demos\n </h1>\n <div className=\"flex flex-col gap-4\">\n <Link\n to=\"/demo/start/ssr/spa-mode\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-pink-600 to-pink-500 hover:from-pink-700 hover:to-pink-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-pink-500/50 border-2 border-pink-400\"\n >\n SPA Mode\n </Link>\n <Link\n to=\"/demo/start/ssr/full-ssr\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-purple-600 to-purple-500 hover:from-purple-700 hover:to-purple-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-purple-500/50 border-2 border-purple-400\"\n >\n Full SSR\n </Link>\n <Link\n to=\"/demo/start/ssr/data-only\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-green-500/50 border-2 border-green-400\"\n >\n Data Only\n </Link>\n </div>\n </div>\n </div>\n )\n}\n",
|
|
21
21
|
"/src/routes/demo/start.ssr.spa-mode.tsx": "import { useEffect, useState } from 'react'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/spa-mode')({\n ssr: false,\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const [punkSongs, setPunkSongs] = useState<\n Awaited<ReturnType<typeof getPunkSongs>>\n >([])\n\n useEffect(() => {\n getPunkSongs().then(setPunkSongs)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-green-400\">\n SPA Mode - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
|
|
22
22
|
"/src/routes/demo/tanstack-query.tsx": "import { useCallback, useState } from 'react'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { useQuery, useMutation } from '@tanstack/react-query'\n\nexport const Route = createFileRoute('/demo/tanstack-query')({\n component: TanStackQueryDemo,\n})\n\ntype Todo = {\n id: number\n name: string\n}\n\nfunction TanStackQueryDemo() {\n const { data, refetch } = useQuery<Todo[]>({\n queryKey: ['todos'],\n queryFn: () => fetch('/demo/api/tq-todos').then((res) => res.json()),\n initialData: [],\n })\n\n const { mutate: addTodo } = useMutation({\n mutationFn: (todo: string) =>\n fetch('/demo/api/tq-todos', {\n method: 'POST',\n body: JSON.stringify(todo),\n }).then((res) => res.json()),\n onSuccess: () => refetch(),\n })\n\n const [todo, setTodo] = useState('')\n\n const submitTodo = useCallback(async () => {\n await addTodo(todo)\n setTodo('')\n }, [addTodo, todo])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-red-900 via-red-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 80% 20%, #3B021F 0%, #7B1028 60%, #1A000A 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">TanStack Query Todos list</h1>\n <ul className=\"mb-4 space-y-2\">\n {data?.map((t) => (\n <li\n key={t.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{t.name}</span>\n </li>\n ))}\n </ul>\n <div className=\"flex flex-col gap-2\">\n <input\n type=\"text\"\n value={todo}\n onChange={(e) => setTodo(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n submitTodo()\n }\n }}\n placeholder=\"Enter a new todo...\"\n className=\"w-full px-4 py-3 rounded-lg border border-white/20 bg-white/10 backdrop-blur-sm text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent\"\n />\n <button\n disabled={todo.trim().length === 0}\n onClick={submitTodo}\n className=\"bg-blue-500 hover:bg-blue-600 disabled:bg-blue-500/50 disabled:cursor-not-allowed text-white font-bold py-3 px-4 rounded-lg transition-colors\"\n >\n Add todo\n </button>\n </div>\n </div>\n </div>\n )\n}\n",
|
|
23
|
-
"/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\
|
|
23
|
+
"/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport {\n Zap,\n Server,\n Route as RouteIcon,\n Shield,\n Waves,\n Sparkles,\n} from 'lucide-react'\n\nexport const Route = createFileRoute('/')({ component: App })\n\nfunction App() {\n const features = [\n {\n icon: <Zap className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Powerful Server Functions',\n description:\n 'Write server-side code that seamlessly integrates with your client components. Type-safe, secure, and simple.',\n },\n {\n icon: <Server className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Flexible Server Side Rendering',\n description:\n 'Full-document SSR, streaming, and progressive enhancement out of the box. Control exactly what renders where.',\n },\n {\n icon: <RouteIcon className=\"w-12 h-12 text-cyan-400\" />,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: <Shield className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Strongly Typed Everything',\n description:\n 'End-to-end type safety from server to client. Catch errors before they reach production.',\n },\n {\n icon: <Waves className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Full Streaming Support',\n description:\n 'Stream data from server to client progressively. Perfect for AI applications and real-time updates.',\n },\n {\n icon: <Sparkles className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Next Generation Ready',\n description:\n 'Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.',\n },\n ]\n\n return (\n <div className=\"min-h-screen bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900\">\n <section className=\"relative py-20 px-6 text-center overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10\"></div>\n <div className=\"relative max-w-5xl mx-auto\">\n <div className=\"flex items-center justify-center gap-6 mb-6\">\n <img\n src=\"/tanstack-circle-logo.png\"\n alt=\"TanStack Logo\"\n className=\"w-24 h-24 md:w-32 md:h-32\"\n />\n <h1 className=\"text-6xl md:text-7xl font-black text-white [letter-spacing:-0.08em]\">\n <span className=\"text-gray-300\">TANSTACK</span>{' '}\n <span className=\"bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent\">\n START\n </span>\n </h1>\n </div>\n <p className=\"text-2xl md:text-3xl text-gray-300 mb-4 font-light\">\n The framework for next generation AI applications\n </p>\n <p className=\"text-lg text-gray-400 max-w-3xl mx-auto mb-8\">\n Full-stack framework powered by TanStack Router for React and Solid.\n Build modern applications with server functions, streaming, and type\n safety.\n </p>\n <div className=\"flex flex-col items-center gap-4\">\n <a\n href=\"https://tanstack.com/start\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50\"\n >\n Documentation\n </a>\n <p className=\"text-gray-400 text-sm mt-2\">\n Begin your TanStack Start journey by editing{' '}\n <code className=\"px-2 py-1 bg-slate-700 rounded text-cyan-400\">\n /src/routes/index.tsx\n </code>\n </p>\n </div>\n </div>\n </section>\n\n <section className=\"py-16 px-6 max-w-7xl mx-auto\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {features.map((feature, index) => (\n <div\n key=\"{index}\"\n className=\"bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10\"\n >\n <div className=\"mb-4\">{feature.icon}</div>\n <h3 className=\"text-xl font-semibold text-white mb-3\">\n {feature.title}\n </h3>\n <p className=\"text-gray-400 leading-relaxed\">\n {feature.description}\n </p>\n </div>\n ))}\n </div>\n </section>\n </div>\n )\n}\n",
|
|
24
24
|
"/src/styles.css": "@import \"tailwindcss\";\n\nbody {\n @apply m-0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
|
|
25
25
|
"README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run start\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses [Tailwind CSS](https://tailwindcss.com/) for styling.\n\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.tsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results as { name: string }[]),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.tsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
|
|
26
26
|
"package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite dev --port 3000\",\n \"build\": \"vite build\",\n \"serve\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-query\": \"^5.66.5\",\n \"@tanstack/react-query-devtools\": \"^5.84.2\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/react-router-ssr-query\": \"^1.131.7\",\n \"@tanstack/react-start\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"lucide-react\": \"^0.544.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^5.1.4\"\n },\n \"devDependencies\": {\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.0.8\",\n \"@types/react-dom\": \"^19.0.3\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": true,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": false,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": [\n \"biome\"\n ]\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"[javascript]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[javascriptreact]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[typescript]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[typescriptreact]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[json]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[jsonc]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[css]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"editor.codeActionsOnSave\": {\n \"source.organizeImports.biome\": \"explicit\"\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport logo from '../logo.svg'\nimport '../App.css'\n\nexport const Route = createFileRoute('/')({\n component: App,\n})\n\nfunction App() {\n return (\n <div className=\"App\">\n <header className=\"App-header\">\n <img src={logo} className=\"App-logo\" alt=\"logo\" />\n <p>\n Edit <code>src/routes/index.tsx</code> and save to reload.\n </p>\n <a\n className=\"App-link\"\n href=\"https://reactjs.org\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn React\n </a>\n <a\n className=\"App-link\"\n href=\"https://tanstack.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn TanStack\n </a>\n </header>\n </div>\n )\n}\n",
|
|
14
14
|
"/src/styles.css": "\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
|
|
15
15
|
"README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run start\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses CSS for styling.\n\n\n## Linting & Formatting\n\nThis project uses [Biome](https://biomejs.dev/) for linting and formatting. The following scripts are available:\n\n\n```bash\nnpm run lint\nnpm run format\nnpm run check\n```\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.tsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results as { name: string }[]),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.tsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
|
|
16
|
-
"biome.json": "{\n\t\"$schema\": \"https://biomejs.dev/schemas/2.2.4/schema.json\",\n\t\"vcs\": {\n\t\t\"enabled\": false,\n\t\t\"clientKind\": \"git\",\n\t\t\"useIgnoreFile\": false\n\t},\n\t\"files\": {\n\t\t\"ignoreUnknown\": false,\n\t\t\"includes\": [\n\t\t\t\"**/src/**/*\",\n\t\t\t\"**/.vscode/**/*\",\n\t\t\t\"**/index.html\",\n\t\t\t\"**/vite.config.js\",\n\t\t\t\"!**/src/routeTree.gen.ts\"\n\t\t]\n\t},\n\t\"formatter\": {\n\t\t\"enabled\": true,\n\t\t\"indentStyle\": \"tab\"\n\t},\n\t\"assist\": { \"actions\": { \"source\": { \"organizeImports\": \"on\" } } },\n\t\"linter\": {\n\t\t\"enabled\": true,\n\t\t\"rules\": {\n\t\t\t\"recommended\": true\n\t\t}\n\t},\n\t\"javascript\": {\n\t\t\"formatter\": {\n\t\t\t\"quoteStyle\": \"double\"\n\t\t}\n\t}\n}\n",
|
|
16
|
+
"biome.json": "{\n\t\"$schema\": \"https://biomejs.dev/schemas/2.2.4/schema.json\",\n\t\"vcs\": {\n\t\t\"enabled\": false,\n\t\t\"clientKind\": \"git\",\n\t\t\"useIgnoreFile\": false\n\t},\n\t\"files\": {\n\t\t\"ignoreUnknown\": false,\n\t\t\"includes\": [\n\t\t\t\"**/src/**/*\",\n\t\t\t\"**/.vscode/**/*\",\n\t\t\t\"**/index.html\",\n\t\t\t\"**/vite.config.js\",\n\t\t\t\"!**/src/routeTree.gen.ts\",\n\t\t\t\"!**/src/styles.css\"\n\t\t]\n\t},\n\t\"formatter\": {\n\t\t\"enabled\": true,\n\t\t\"indentStyle\": \"tab\"\n\t},\n\t\"assist\": { \"actions\": { \"source\": { \"organizeImports\": \"on\" } } },\n\t\"linter\": {\n\t\t\"enabled\": true,\n\t\t\"rules\": {\n\t\t\t\"recommended\": true\n\t\t}\n\t},\n\t\"javascript\": {\n\t\t\"formatter\": {\n\t\t\t\"quoteStyle\": \"double\"\n\t\t}\n\t}\n}\n",
|
|
17
17
|
"index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>\n",
|
|
18
18
|
"package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"serve\": \"vite preview\",\n \"test\": \"vitest run\",\n \"format\": \"biome format\",\n \"lint\": \"biome lint\",\n \"check\": \"biome check\"\n },\n \"dependencies\": {\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.2.4\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.0.8\",\n \"@types/react-dom\": \"^19.0.3\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
|
|
19
19
|
"tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"],\n }\n }\n}\n",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": false,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": false,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": []\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
".cta.json": "{\n \"addOns\": false,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": true,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": []\n}",
|
|
4
|
-
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n",
|
|
4
|
+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n",
|
|
5
5
|
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
|
|
6
6
|
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
|
|
7
7
|
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
|