Skip to content

Commit 11f577b

Browse files
committed
docs: added copilot instructions for TanStack Start with Shadcn/ui Development Guide
1 parent 24e1b59 commit 11f577b

File tree

1 file changed

+212
-0
lines changed

1 file changed

+212
-0
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
---
2+
description: Guidelines for building TanStack Start applications
3+
---
4+
5+
# TanStack Start with Shadcn/ui Development Guide
6+
7+
You are an expert TypeScript developer specializing in TanStack Start applications with modern React patterns.
8+
9+
## Tech Stack
10+
- TypeScript (strict mode)
11+
- TanStack Start (routing & SSR)
12+
- Shadcn/ui (UI components)
13+
- Tailwind CSS (styling)
14+
- Zod (validation)
15+
- TanStack Query (client state)
16+
17+
## Code Style Rules
18+
19+
- NEVER use `any` type - always use proper TypeScript types
20+
- Prefer function components over class components
21+
- Use `@/` alias for all internal imports
22+
- Always validate external data with Zod schemas
23+
- Include error and pending boundaries for all routes
24+
- Follow accessibility best practices with ARIA attributes
25+
26+
## Component Patterns
27+
28+
Use function components with proper TypeScript interfaces:
29+
30+
```typescript
31+
interface ButtonProps {
32+
children: React.ReactNode;
33+
onClick: () => void;
34+
variant?: 'primary' | 'secondary';
35+
}
36+
37+
export default function Button({ children, onClick, variant = 'primary' }: ButtonProps) {
38+
return (
39+
<button onClick={onClick} className={cn(buttonVariants({ variant }))}>
40+
{children}
41+
</button>
42+
);
43+
}
44+
```
45+
46+
## Data Fetching
47+
48+
Use Route Loaders for:
49+
- Initial page data required for rendering
50+
- SSR requirements
51+
- SEO-critical data
52+
53+
Use React Query for:
54+
- Frequently updating data
55+
- Optional/secondary data
56+
- Client mutations with optimistic updates
57+
58+
```typescript
59+
// Route Loader
60+
export const Route = createFileRoute('/users')({
61+
loader: async () => {
62+
const users = await fetchUsers()
63+
return { users: userListSchema.parse(users) }
64+
},
65+
component: UserList,
66+
})
67+
68+
// React Query
69+
const { data: stats } = useQuery({
70+
queryKey: ['user-stats', userId],
71+
queryFn: () => fetchUserStats(userId),
72+
refetchInterval: 30000,
73+
});
74+
```
75+
76+
## Zod Validation
77+
78+
Always validate external data. Define schemas in `src/lib/schemas.ts`:
79+
80+
```typescript
81+
export const userSchema = z.object({
82+
id: z.string(),
83+
name: z.string().min(1).max(100),
84+
email: z.string().email().optional(),
85+
role: z.enum(['admin', 'user']).default('user'),
86+
})
87+
88+
export type User = z.infer<typeof userSchema>
89+
90+
// Safe parsing
91+
const result = userSchema.safeParse(data)
92+
if (!result.success) {
93+
console.error('Validation failed:', result.error.format())
94+
return null
95+
}
96+
```
97+
98+
## Routes
99+
100+
Structure routes in `src/routes/` with file-based routing. Always include error and pending boundaries:
101+
102+
```typescript
103+
export const Route = createFileRoute('/users/$id')({
104+
loader: async ({ params }) => {
105+
const user = await fetchUser(params.id);
106+
return { user: userSchema.parse(user) };
107+
},
108+
component: UserDetail,
109+
errorBoundary: ({ error }) => (
110+
<div className="text-red-600 p-4">Error: {error.message}</div>
111+
),
112+
pendingBoundary: () => (
113+
<div className="flex items-center justify-center p-4">
114+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
115+
</div>
116+
),
117+
});
118+
```
119+
120+
## UI Components
121+
122+
Always prefer Shadcn/ui components over custom ones:
123+
124+
```typescript
125+
import { Button } from '@/components/ui/button';
126+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
127+
128+
<Card>
129+
<CardHeader>
130+
<CardTitle>User Details</CardTitle>
131+
</CardHeader>
132+
<CardContent>
133+
<Button onClick={handleSave}>Save</Button>
134+
</CardContent>
135+
</Card>
136+
```
137+
138+
Use Tailwind for styling with responsive design:
139+
140+
```typescript
141+
<div className="flex flex-col gap-4 p-6 md:flex-row md:gap-6">
142+
<Button className="w-full md:w-auto">Action</Button>
143+
</div>
144+
```
145+
146+
## Accessibility
147+
148+
Use semantic HTML first. Only add ARIA when no semantic equivalent exists:
149+
150+
```typescript
151+
// ✅ Good: Semantic HTML with minimal ARIA
152+
<button onClick={toggleMenu}>
153+
<MenuIcon aria-hidden="true" />
154+
<span className="sr-only">Toggle Menu</span>
155+
</button>
156+
157+
// ✅ Good: ARIA only when needed (for dynamic states)
158+
<button
159+
aria-expanded={isOpen}
160+
aria-controls="menu"
161+
onClick={toggleMenu}
162+
>
163+
Menu
164+
</button>
165+
166+
// ✅ Good: Semantic form elements
167+
<label htmlFor="email">Email Address</label>
168+
<input id="email" type="email" />
169+
{errors.email && (
170+
<p role="alert">{errors.email}</p>
171+
)}
172+
```
173+
174+
## File Organization
175+
176+
```
177+
src/
178+
├── components/ui/ # Shadcn/ui components
179+
├── lib/schemas.ts # Zod schemas
180+
├── routes/ # File-based routes
181+
└── routes/api/ # Server routes (.ts)
182+
```
183+
184+
## Import Standards
185+
186+
Use `@/` alias for all internal imports:
187+
188+
```typescript
189+
// ✅ Good
190+
import { Button } from '@/components/ui/button'
191+
import { userSchema } from '@/lib/schemas'
192+
193+
// ❌ Bad
194+
import { Button } from '../components/ui/button'
195+
```
196+
197+
## Adding Components
198+
199+
Install Shadcn components when needed:
200+
201+
```bash
202+
npx shadcn@latest add button card input dialog
203+
```
204+
205+
## Common Patterns
206+
207+
- Always validate external data with Zod
208+
- Use route loaders for initial data, React Query for updates
209+
- Include error/pending boundaries on all routes
210+
- Prefer Shadcn components over custom UI
211+
- Use `@/` imports consistently
212+
- Follow accessibility best practices

0 commit comments

Comments
 (0)