@smicolon/ai-kit 0.0.1 → 0.1.1
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/.claude-plugin/CLAUDE.md +7 -0
- package/.claude-plugin/marketplace.json +373 -0
- package/README.md +132 -0
- package/package.json +13 -3
- package/packs/architect/CHANGELOG.md +17 -0
- package/packs/architect/README.md +58 -0
- package/packs/architect/agents/system-architect.md +768 -0
- package/packs/architect/commands/diagram-create.md +300 -0
- package/packs/better-auth/.claude-plugin/plugin.json +14 -0
- package/packs/better-auth/.mcp.json +14 -0
- package/packs/better-auth/CHANGELOG.md +26 -0
- package/packs/better-auth/README.md +125 -0
- package/packs/better-auth/agents/auth-architect.md +278 -0
- package/packs/better-auth/commands/auth-provider-add.md +265 -0
- package/packs/better-auth/commands/auth-setup.md +298 -0
- package/packs/better-auth/skills/auth-security/SKILL.md +425 -0
- package/packs/better-auth/skills/better-auth-patterns/SKILL.md +455 -0
- package/packs/dev-loop/.claude-plugin/plugin.json +10 -0
- package/packs/dev-loop/CHANGELOG.md +69 -0
- package/packs/dev-loop/README.md +155 -0
- package/packs/dev-loop/commands/cancel-dev.md +21 -0
- package/packs/dev-loop/commands/dev-loop.md +72 -0
- package/packs/dev-loop/commands/dev-plan.md +351 -0
- package/packs/dev-loop/hooks/hooks.json +15 -0
- package/packs/dev-loop/hooks/stop-hook.sh +178 -0
- package/packs/dev-loop/scripts/setup-dev-loop.sh +194 -0
- package/packs/dev-loop/skills/tdd-planner/SKILL.md +249 -0
- package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +874 -0
- package/packs/dev-loop/skills/tdd-planner/references/good-example.md +260 -0
- package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +275 -0
- package/packs/django/CHANGELOG.md +39 -0
- package/packs/django/README.md +92 -0
- package/packs/django/agents/django-architect.md +182 -0
- package/packs/django/agents/django-builder.md +250 -0
- package/packs/django/agents/django-feature-based.md +420 -0
- package/packs/django/agents/django-reviewer.md +253 -0
- package/packs/django/agents/django-tester.md +230 -0
- package/packs/django/commands/api-endpoint.md +285 -0
- package/packs/django/commands/model-create.md +178 -0
- package/packs/django/commands/test-generate.md +325 -0
- package/packs/django/rules/migrations.md +138 -0
- package/packs/django/rules/models.md +167 -0
- package/packs/django/rules/serializers.md +126 -0
- package/packs/django/rules/services.md +131 -0
- package/packs/django/rules/tests.md +140 -0
- package/packs/django/rules/views.md +102 -0
- package/packs/django/skills/import-convention-enforcer/SKILL.md +226 -0
- package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +343 -0
- package/packs/django/skills/migration-safety-checker/SKILL.md +375 -0
- package/packs/django/skills/model-entity-validator/SKILL.md +298 -0
- package/packs/django/skills/performance-optimizer/SKILL.md +447 -0
- package/packs/django/skills/red-phase-verifier/SKILL.md +180 -0
- package/packs/django/skills/security-first-validator/SKILL.md +435 -0
- package/packs/django/skills/test-coverage-advisor/SKILL.md +394 -0
- package/packs/django/skills/test-validity-checker/SKILL.md +194 -0
- package/packs/failure-log/.claude-plugin/plugin.json +14 -0
- package/packs/failure-log/CHANGELOG.md +20 -0
- package/packs/failure-log/README.md +168 -0
- package/packs/failure-log/commands/failure-add.md +106 -0
- package/packs/failure-log/commands/failure-list.md +89 -0
- package/packs/failure-log/hooks/hooks.json +16 -0
- package/packs/failure-log/hooks/scripts/inject-failures.sh +64 -0
- package/packs/failure-log/skills/failure-log-manager/SKILL.md +164 -0
- package/packs/flutter/.claude-plugin/plugin.json +10 -0
- package/packs/flutter/CHANGELOG.md +19 -0
- package/packs/flutter/README.md +170 -0
- package/packs/flutter/agents/flutter-architect.md +166 -0
- package/packs/flutter/agents/flutter-builder.md +303 -0
- package/packs/flutter/agents/release-manager.md +355 -0
- package/packs/flutter/commands/fastlane-setup.md +188 -0
- package/packs/flutter/commands/flutter-build.md +90 -0
- package/packs/flutter/commands/flutter-deploy.md +133 -0
- package/packs/flutter/commands/flutter-test.md +117 -0
- package/packs/flutter/commands/signing-setup.md +209 -0
- package/packs/flutter/hooks/hooks.json +17 -0
- package/packs/flutter/skills/fastlane-knowledge/SKILL.md +193 -0
- package/packs/flutter/skills/flutter-architecture/SKILL.md +127 -0
- package/packs/flutter/skills/store-publishing/SKILL.md +163 -0
- package/packs/hono/.claude-plugin/plugin.json +19 -0
- package/packs/hono/CHANGELOG.md +19 -0
- package/packs/hono/README.md +143 -0
- package/packs/hono/agents/hono-architect.md +240 -0
- package/packs/hono/agents/hono-builder.md +285 -0
- package/packs/hono/agents/hono-reviewer.md +279 -0
- package/packs/hono/agents/hono-tester.md +346 -0
- package/packs/hono/commands/middleware-create.md +223 -0
- package/packs/hono/commands/project-init.md +306 -0
- package/packs/hono/commands/route-create.md +153 -0
- package/packs/hono/commands/rpc-client.md +263 -0
- package/packs/hono/hooks/hooks.json +4 -0
- package/packs/hono/skills/cloudflare-bindings/SKILL.md +408 -0
- package/packs/hono/skills/hono-patterns/SKILL.md +309 -0
- package/packs/hono/skills/rpc-typesafe/SKILL.md +388 -0
- package/packs/hono/skills/zod-validation/SKILL.md +332 -0
- package/packs/nestjs/CHANGELOG.md +29 -0
- package/packs/nestjs/README.md +75 -0
- package/packs/nestjs/agents/nestjs-architect.md +402 -0
- package/packs/nestjs/agents/nestjs-builder.md +301 -0
- package/packs/nestjs/agents/nestjs-tester.md +437 -0
- package/packs/nestjs/commands/module-create.md +369 -0
- package/packs/nestjs/rules/controllers.md +92 -0
- package/packs/nestjs/rules/dto.md +124 -0
- package/packs/nestjs/rules/entities.md +102 -0
- package/packs/nestjs/rules/services.md +106 -0
- package/packs/nestjs/skills/barrel-export-manager/SKILL.md +389 -0
- package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +365 -0
- package/packs/nextjs/CHANGELOG.md +36 -0
- package/packs/nextjs/README.md +76 -0
- package/packs/nextjs/agents/frontend-tester.md +680 -0
- package/packs/nextjs/agents/frontend-visual.md +820 -0
- package/packs/nextjs/agents/nextjs-architect.md +331 -0
- package/packs/nextjs/agents/nextjs-modular.md +433 -0
- package/packs/nextjs/commands/component-create.md +398 -0
- package/packs/nextjs/rules/api-routes.md +129 -0
- package/packs/nextjs/rules/components.md +106 -0
- package/packs/nextjs/rules/hooks.md +132 -0
- package/packs/nextjs/skills/accessibility-validator/SKILL.md +445 -0
- package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +399 -0
- package/packs/nextjs/skills/react-form-validator/SKILL.md +569 -0
- package/packs/nuxtjs/CHANGELOG.md +30 -0
- package/packs/nuxtjs/README.md +56 -0
- package/packs/nuxtjs/agents/frontend-tester.md +680 -0
- package/packs/nuxtjs/agents/frontend-visual.md +820 -0
- package/packs/nuxtjs/agents/nuxtjs-architect.md +537 -0
- package/packs/nuxtjs/commands/component-create.md +223 -0
- package/packs/nuxtjs/rules/components.md +101 -0
- package/packs/nuxtjs/rules/composables.md +118 -0
- package/packs/nuxtjs/rules/server-routes.md +127 -0
- package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +183 -0
- package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +196 -0
- package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +190 -0
- package/packs/onboard/CHANGELOG.md +22 -0
- package/packs/onboard/README.md +103 -0
- package/packs/onboard/agents/onboard-guide.md +118 -0
- package/packs/onboard/commands/onboard.md +313 -0
- package/packs/onboard/skills/onboard-context-provider/SKILL.md +98 -0
- package/packs/tanstack-router/.claude-plugin/plugin.json +14 -0
- package/packs/tanstack-router/CHANGELOG.md +30 -0
- package/packs/tanstack-router/README.md +113 -0
- package/packs/tanstack-router/agents/tanstack-architect.md +173 -0
- package/packs/tanstack-router/agents/tanstack-builder.md +360 -0
- package/packs/tanstack-router/agents/tanstack-tester.md +454 -0
- package/packs/tanstack-router/commands/form-create.md +313 -0
- package/packs/tanstack-router/commands/query-create.md +263 -0
- package/packs/tanstack-router/commands/route-create.md +190 -0
- package/packs/tanstack-router/commands/table-create.md +413 -0
- package/packs/tanstack-router/skills/ai-patterns/SKILL.md +370 -0
- package/packs/tanstack-router/skills/db-patterns/SKILL.md +346 -0
- package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +415 -0
- package/packs/tanstack-router/skills/form-patterns/SKILL.md +425 -0
- package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +341 -0
- package/packs/tanstack-router/skills/query-patterns/SKILL.md +359 -0
- package/packs/tanstack-router/skills/router-patterns/SKILL.md +285 -0
- package/packs/tanstack-router/skills/store-patterns/SKILL.md +351 -0
- package/packs/tanstack-router/skills/table-patterns/SKILL.md +531 -0
- package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +428 -0
- package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +490 -0
- package/packs/worktree/.claude-plugin/plugin.json +19 -0
- package/packs/worktree/CHANGELOG.md +24 -0
- package/packs/worktree/README.md +110 -0
- package/packs/worktree/commands/wt.md +73 -0
- package/packs/worktree/scripts/wt.sh +396 -0
- package/packs/worktree/skills/worktree-manager/SKILL.md +68 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: TanStack Conventions
|
|
3
|
+
description: >-
|
|
4
|
+
Auto-enforce cross-cutting TanStack conventions and import patterns. Activates
|
|
5
|
+
on all TanStack development to ensure consistent project structure, imports,
|
|
6
|
+
and integration patterns across Router, Query, Form, Table, and Virtual.
|
|
7
|
+
version: 1.0.0
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# TanStack Conventions
|
|
11
|
+
|
|
12
|
+
This skill enforces cross-cutting conventions across all TanStack libraries for consistent, maintainable React SPA development.
|
|
13
|
+
|
|
14
|
+
## Project Structure
|
|
15
|
+
|
|
16
|
+
### Feature-Based Organization
|
|
17
|
+
```
|
|
18
|
+
src/
|
|
19
|
+
├── features/
|
|
20
|
+
│ ├── posts/
|
|
21
|
+
│ │ ├── components/
|
|
22
|
+
│ │ │ ├── PostList.tsx
|
|
23
|
+
│ │ │ ├── PostCard.tsx
|
|
24
|
+
│ │ │ ├── PostForm.tsx
|
|
25
|
+
│ │ │ └── index.ts # Barrel export
|
|
26
|
+
│ │ ├── hooks/
|
|
27
|
+
│ │ │ ├── useCreatePost.ts
|
|
28
|
+
│ │ │ ├── useUpdatePost.ts
|
|
29
|
+
│ │ │ ├── useDeletePost.ts
|
|
30
|
+
│ │ │ └── index.ts
|
|
31
|
+
│ │ ├── queries/
|
|
32
|
+
│ │ │ ├── postQueries.ts # Query options factories
|
|
33
|
+
│ │ │ └── index.ts
|
|
34
|
+
│ │ ├── api/
|
|
35
|
+
│ │ │ └── postApi.ts # API client functions
|
|
36
|
+
│ │ ├── types.ts # Feature-specific types
|
|
37
|
+
│ │ └── index.ts # Feature barrel export
|
|
38
|
+
│ └── users/
|
|
39
|
+
│ └── ...
|
|
40
|
+
├── routes/
|
|
41
|
+
│ ├── __root.tsx
|
|
42
|
+
│ ├── index.tsx
|
|
43
|
+
│ ├── posts.tsx
|
|
44
|
+
│ ├── posts.index.tsx
|
|
45
|
+
│ └── posts.$postId.tsx
|
|
46
|
+
├── lib/
|
|
47
|
+
│ ├── query-client.ts # Query client setup
|
|
48
|
+
│ ├── query-keys.ts # Query key factory
|
|
49
|
+
│ └── router.ts # Router setup
|
|
50
|
+
├── components/
|
|
51
|
+
│ └── ui/ # Shared UI components
|
|
52
|
+
├── hooks/ # Shared hooks
|
|
53
|
+
├── types/ # Global types
|
|
54
|
+
└── main.tsx
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Import Conventions
|
|
58
|
+
|
|
59
|
+
### Always Use Path Aliases
|
|
60
|
+
```typescript
|
|
61
|
+
// ✅ CORRECT: Path aliases
|
|
62
|
+
import { PostList } from '@/features/posts/components'
|
|
63
|
+
import { useCreatePost } from '@/features/posts/hooks'
|
|
64
|
+
import { postQueryOptions } from '@/features/posts/queries'
|
|
65
|
+
import { queryKeys } from '@/lib/query-keys'
|
|
66
|
+
import { Button } from '@/components/ui'
|
|
67
|
+
|
|
68
|
+
// ❌ WRONG: Relative imports across features
|
|
69
|
+
import { User } from '../../users/types'
|
|
70
|
+
import { queryClient } from '../../../lib/query-client'
|
|
71
|
+
|
|
72
|
+
// ❌ WRONG: Deep imports bypassing barrels
|
|
73
|
+
import { PostCard } from '@/features/posts/components/PostCard'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Barrel Export Pattern
|
|
77
|
+
```typescript
|
|
78
|
+
// features/posts/components/index.ts
|
|
79
|
+
export { PostList } from './PostList'
|
|
80
|
+
export { PostCard } from './PostCard'
|
|
81
|
+
export { PostForm } from './PostForm'
|
|
82
|
+
|
|
83
|
+
// features/posts/index.ts
|
|
84
|
+
export * from './components'
|
|
85
|
+
export * from './hooks'
|
|
86
|
+
export * from './queries'
|
|
87
|
+
export * from './types'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Import Order
|
|
91
|
+
```typescript
|
|
92
|
+
// 1. React and external libraries
|
|
93
|
+
import { useState, useRef } from 'react'
|
|
94
|
+
import { useQuery, useMutation } from '@tanstack/react-query'
|
|
95
|
+
import { Link, useNavigate } from '@tanstack/react-router'
|
|
96
|
+
|
|
97
|
+
// 2. Internal aliases (@/)
|
|
98
|
+
import { PostCard } from '@/features/posts/components'
|
|
99
|
+
import { queryKeys } from '@/lib/query-keys'
|
|
100
|
+
import { Button } from '@/components/ui'
|
|
101
|
+
|
|
102
|
+
// 3. Relative imports (same feature only)
|
|
103
|
+
import { postSchema } from './schemas'
|
|
104
|
+
import type { PostFormData } from './types'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## TypeScript Configuration
|
|
108
|
+
|
|
109
|
+
### tsconfig.json Path Aliases
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"compilerOptions": {
|
|
113
|
+
"strict": true,
|
|
114
|
+
"noUncheckedIndexedAccess": true,
|
|
115
|
+
"baseUrl": ".",
|
|
116
|
+
"paths": {
|
|
117
|
+
"@/*": ["./src/*"]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Vite Configuration
|
|
124
|
+
```typescript
|
|
125
|
+
// vite.config.ts
|
|
126
|
+
import { defineConfig } from 'vite'
|
|
127
|
+
import react from '@vitejs/plugin-react'
|
|
128
|
+
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
|
|
129
|
+
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
130
|
+
|
|
131
|
+
export default defineConfig({
|
|
132
|
+
plugins: [
|
|
133
|
+
TanStackRouterVite(),
|
|
134
|
+
react(),
|
|
135
|
+
tsconfigPaths(),
|
|
136
|
+
],
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## App Setup
|
|
141
|
+
|
|
142
|
+
### Main Entry Point
|
|
143
|
+
```typescript
|
|
144
|
+
// main.tsx
|
|
145
|
+
import { StrictMode } from 'react'
|
|
146
|
+
import { createRoot } from 'react-dom/client'
|
|
147
|
+
import { QueryClientProvider } from '@tanstack/react-query'
|
|
148
|
+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
|
|
149
|
+
import { RouterProvider } from '@tanstack/react-router'
|
|
150
|
+
import { createQueryClient } from '@/lib/query-client'
|
|
151
|
+
import { router } from '@/lib/router'
|
|
152
|
+
|
|
153
|
+
const queryClient = createQueryClient()
|
|
154
|
+
|
|
155
|
+
createRoot(document.getElementById('root')!).render(
|
|
156
|
+
<StrictMode>
|
|
157
|
+
<QueryClientProvider client={queryClient}>
|
|
158
|
+
<RouterProvider router={router} context={{ queryClient }} />
|
|
159
|
+
<ReactQueryDevtools />
|
|
160
|
+
</QueryClientProvider>
|
|
161
|
+
</StrictMode>
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Router Setup
|
|
166
|
+
```typescript
|
|
167
|
+
// lib/router.ts
|
|
168
|
+
import { createRouter } from '@tanstack/react-router'
|
|
169
|
+
import { routeTree } from '@/routeTree.gen'
|
|
170
|
+
import type { QueryClient } from '@tanstack/react-query'
|
|
171
|
+
|
|
172
|
+
export interface RouterContext {
|
|
173
|
+
queryClient: QueryClient
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const router = createRouter({
|
|
177
|
+
routeTree,
|
|
178
|
+
context: {
|
|
179
|
+
queryClient: undefined!, // Set in main.tsx
|
|
180
|
+
},
|
|
181
|
+
defaultPreload: 'intent',
|
|
182
|
+
defaultPreloadStaleTime: 0,
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
declare module '@tanstack/react-router' {
|
|
186
|
+
interface Register {
|
|
187
|
+
router: typeof router
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Query Client Setup
|
|
193
|
+
```typescript
|
|
194
|
+
// lib/query-client.ts
|
|
195
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
196
|
+
|
|
197
|
+
export function createQueryClient() {
|
|
198
|
+
return new QueryClient({
|
|
199
|
+
defaultOptions: {
|
|
200
|
+
queries: {
|
|
201
|
+
staleTime: 60 * 1000,
|
|
202
|
+
gcTime: 5 * 60 * 1000,
|
|
203
|
+
retry: 1,
|
|
204
|
+
refetchOnWindowFocus: false,
|
|
205
|
+
},
|
|
206
|
+
mutations: {
|
|
207
|
+
retry: 0,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Error Handling
|
|
215
|
+
|
|
216
|
+
### API Error Type
|
|
217
|
+
```typescript
|
|
218
|
+
// types/api.ts
|
|
219
|
+
export interface ApiError {
|
|
220
|
+
message: string
|
|
221
|
+
code: string
|
|
222
|
+
status: number
|
|
223
|
+
details?: Record<string, string[]>
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function isApiError(error: unknown): error is ApiError {
|
|
227
|
+
return (
|
|
228
|
+
typeof error === 'object' &&
|
|
229
|
+
error !== null &&
|
|
230
|
+
'message' in error &&
|
|
231
|
+
'status' in error
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Query Error Handler
|
|
237
|
+
```typescript
|
|
238
|
+
// lib/query-client.ts
|
|
239
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
240
|
+
import { toast } from '@/components/ui/toast'
|
|
241
|
+
|
|
242
|
+
export function createQueryClient() {
|
|
243
|
+
return new QueryClient({
|
|
244
|
+
defaultOptions: {
|
|
245
|
+
queries: {
|
|
246
|
+
retry: (failureCount, error) => {
|
|
247
|
+
if (isApiError(error) && error.status === 404) return false
|
|
248
|
+
return failureCount < 2
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
mutations: {
|
|
252
|
+
onError: (error) => {
|
|
253
|
+
if (isApiError(error)) {
|
|
254
|
+
toast.error(error.message)
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Route Error Boundaries
|
|
264
|
+
```typescript
|
|
265
|
+
// routes/__root.tsx
|
|
266
|
+
export const Route = createRootRouteWithContext<RouterContext>()({
|
|
267
|
+
component: RootComponent,
|
|
268
|
+
errorComponent: ({ error }) => (
|
|
269
|
+
<div className="error-page">
|
|
270
|
+
<h1>Something went wrong</h1>
|
|
271
|
+
<p>{error.message}</p>
|
|
272
|
+
<Link to="/">Go home</Link>
|
|
273
|
+
</div>
|
|
274
|
+
),
|
|
275
|
+
notFoundComponent: () => (
|
|
276
|
+
<div className="not-found-page">
|
|
277
|
+
<h1>404 - Page not found</h1>
|
|
278
|
+
<Link to="/">Go home</Link>
|
|
279
|
+
</div>
|
|
280
|
+
),
|
|
281
|
+
})
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Loading States
|
|
285
|
+
|
|
286
|
+
### Route Pending
|
|
287
|
+
```typescript
|
|
288
|
+
export const Route = createFileRoute('/posts/$postId')({
|
|
289
|
+
loader: ({ context: { queryClient }, params }) =>
|
|
290
|
+
queryClient.ensureQueryData(postQueryOptions(params.postId)),
|
|
291
|
+
pendingComponent: () => <PostDetailSkeleton />,
|
|
292
|
+
pendingMinMs: 200,
|
|
293
|
+
component: PostDetailPage,
|
|
294
|
+
})
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Query Loading
|
|
298
|
+
```typescript
|
|
299
|
+
function PostList() {
|
|
300
|
+
const { data, isLoading, error } = useQuery(postsQueryOptions())
|
|
301
|
+
|
|
302
|
+
if (isLoading) return <PostListSkeleton />
|
|
303
|
+
if (error) return <ErrorMessage error={error} />
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<ul>
|
|
307
|
+
{data.map((post) => (
|
|
308
|
+
<PostCard key={post.id} post={post} />
|
|
309
|
+
))}
|
|
310
|
+
</ul>
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## API Client Pattern
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// features/posts/api/postApi.ts
|
|
319
|
+
import { apiClient } from '@/lib/api-client'
|
|
320
|
+
import type { Post, CreatePostInput, UpdatePostInput } from '../types'
|
|
321
|
+
|
|
322
|
+
export const postApi = {
|
|
323
|
+
getPosts: async (filters?: PostFilters): Promise<Post[]> => {
|
|
324
|
+
const response = await apiClient.get('/posts', { params: filters })
|
|
325
|
+
return response.data
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
getPost: async (id: string): Promise<Post> => {
|
|
329
|
+
const response = await apiClient.get(`/posts/${id}`)
|
|
330
|
+
return response.data
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
createPost: async (input: CreatePostInput): Promise<Post> => {
|
|
334
|
+
const response = await apiClient.post('/posts', input)
|
|
335
|
+
return response.data
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
updatePost: async ({ id, ...input }: UpdatePostInput): Promise<Post> => {
|
|
339
|
+
const response = await apiClient.patch(`/posts/${id}`, input)
|
|
340
|
+
return response.data
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
deletePost: async (id: string): Promise<void> => {
|
|
344
|
+
await apiClient.delete(`/posts/${id}`)
|
|
345
|
+
},
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Type Definitions
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
// features/posts/types.ts
|
|
353
|
+
export interface Post {
|
|
354
|
+
id: string
|
|
355
|
+
title: string
|
|
356
|
+
content: string
|
|
357
|
+
authorId: string
|
|
358
|
+
published: boolean
|
|
359
|
+
createdAt: string
|
|
360
|
+
updatedAt: string
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface CreatePostInput {
|
|
364
|
+
title: string
|
|
365
|
+
content: string
|
|
366
|
+
published?: boolean
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export interface UpdatePostInput extends Partial<CreatePostInput> {
|
|
370
|
+
id: string
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export interface PostFilters {
|
|
374
|
+
page?: number
|
|
375
|
+
pageSize?: number
|
|
376
|
+
search?: string
|
|
377
|
+
authorId?: string
|
|
378
|
+
published?: boolean
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Bun Commands
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
# Install dependencies
|
|
386
|
+
bun install
|
|
387
|
+
|
|
388
|
+
# Add TanStack packages
|
|
389
|
+
bun add @tanstack/react-router @tanstack/react-query @tanstack/react-form @tanstack/react-table @tanstack/react-virtual
|
|
390
|
+
bun add -D @tanstack/router-plugin @tanstack/react-query-devtools
|
|
391
|
+
|
|
392
|
+
# Dev server
|
|
393
|
+
bun run dev
|
|
394
|
+
|
|
395
|
+
# Build
|
|
396
|
+
bun run build
|
|
397
|
+
|
|
398
|
+
# Type check
|
|
399
|
+
bun run typecheck
|
|
400
|
+
|
|
401
|
+
# Generate routes
|
|
402
|
+
bun run routes:generate
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Package Scripts
|
|
406
|
+
|
|
407
|
+
```json
|
|
408
|
+
{
|
|
409
|
+
"scripts": {
|
|
410
|
+
"dev": "vite",
|
|
411
|
+
"build": "tsc -b && vite build",
|
|
412
|
+
"preview": "vite preview",
|
|
413
|
+
"typecheck": "tsc --noEmit",
|
|
414
|
+
"routes:generate": "tsr generate"
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Conventions Summary
|
|
420
|
+
|
|
421
|
+
1. **Feature-based structure** - Group by feature, not by type
|
|
422
|
+
2. **Path aliases** - Always use `@/` for imports
|
|
423
|
+
3. **Barrel exports** - Export through index.ts files
|
|
424
|
+
4. **Query key factory** - Centralized in `lib/query-keys.ts`
|
|
425
|
+
5. **Type safety** - Strict TypeScript, no `any`
|
|
426
|
+
6. **Error boundaries** - Route and component level
|
|
427
|
+
7. **Loading states** - Skeletons, not spinners
|
|
428
|
+
8. **Bun runtime** - Use bun for all commands
|