Development guide for React + TypeScript + Vite project using Feature-Sliced Design architecture
A comprehensive guide for working with a React + TypeScript + Vite frontend application following Feature-Sliced Design principles.
When working with this project, use these commands:
**Development:**
**Code Quality:**
**Pages Layer** (`pages/[page-name]/`)
**Entities Layer** (`entities/[entity]/`)
- File: `api/[entity].queries.ts`
- Example: `entities/user/api/user.queries.ts`
- Pattern: `ui/[component-name]/index.tsx` + `index.css.ts`
- Example: `entities/user/ui/user-list/`
- `mocks/[entity].fixtures.ts` - Mock data
- `mocks/[entity].handlers.ts` - GET handlers
**Features Layer** (`features/[action-verb]/`)
- File: `api/[feature].mutation.ts`
- Example: `features/create-user/api/create-user.mutation.ts`
- File: `mocks/[feature].handlers.ts`
**App Layer** (`app/`)
- `providers/query.tsx` - React Query provider
- `providers/router.tsx` - React Router
- `providers/index.tsx` - Combined providers
- `mocks/browser.ts` - Worker setup
- `mocks/init.ts` - Initialization
**Shared Layer** (`shared/`)
- `lib/axios.ts` - API client
- `lib/msw.ts` - MSW factory functions
**CRITICAL: Always use Vanilla Extract - NEVER use inline styles**
```
component-name/
├── index.tsx # Component logic
└── index.css.ts # Vanilla Extract styles
```
```typescript
// user-list/index.css.ts
import { style } from "@vanilla-extract/css";
export const container = style({
padding: "20px",
});
export const title = style({
fontSize: "24px",
fontWeight: "600",
});
// user-list/index.tsx
import * as styles from "./index.css";
export const UserList = () => {
return (
<div className={styles.container}>
<h2 className={styles.title}>Users</h2>
</div>
);
};
```
**Always use arrow functions for ALL functions:**
```typescript
// API functions
const fetchUsers = async (): Promise<User[]> => {
const { data } = await api.get<User[]>("/users");
return data;
};
// Components
export const UserList = () => {
return <div>...</div>;
};
// Custom Hooks
export const useUsers = () => {
return useSuspenseQuery(userQueries.list());
};
// Event Handlers
const handleSubmit = (event: FormEvent) => {
event.preventDefault();
};
```
**API Files:**
**Mock Files:**
```typescript
// Use interface for object shapes
interface User {
id: number;
name: string;
}
// Use type for unions, intersections, primitives
type UserRole = "admin" | "user" | "guest";
```
1. **Create feature folder:**
```
features/create-user/
├── api/
│ └── create-user.mutation.ts
└── mocks/
└── create-user.handlers.ts
```
2. **Implement mutation:**
```typescript
// features/create-user/api/create-user.mutation.ts
export const useCreateUser = () => {
return useMutation({
mutationFn: async (userData: CreateUserData) => {
const { data } = await api.post("/users", userData);
return data;
},
});
};
```
3. **Add mock handler:**
```typescript
// features/create-user/mocks/create-user.handlers.ts
import { createHandler } from "@/shared/lib/msw";
export const createUserHandlers = createHandlers([
createHandler("post", "/users", async ({ request }) => {
const body = await request.json();
return { id: 1, ...body };
}),
]);
```
4. **Register handler in app/mocks/browser.ts**
1. **Create entity structure:**
```
entities/user/
├── api/
│ └── user.queries.ts
├── ui/
│ └── user-list/
│ ├── index.tsx
│ └── index.css.ts
└── mocks/
├── user.fixtures.ts
└── user.handlers.ts
```
2. **Implement query:**
```typescript
// entities/user/api/user.queries.ts
export const userQueries = {
list: () => ({
queryKey: ["users"],
queryFn: async () => {
const { data } = await api.get<User[]>("/users");
return data;
},
}),
};
```
3. **Create UI component with Vanilla Extract styling**
4. **Add mock fixtures and handlers**
1. **Using inline styles instead of Vanilla Extract**
- ❌ `<div style={{ padding: "20px" }}>`
- ✅ `<div className={styles.container}>`
2. **Wrong function declaration**
- ❌ `function handleClick() { ... }`
- ✅ `const handleClick = () => { ... }`
3. **Misplacing mutations in entities**
- ❌ `entities/user/api/create-user.ts`
- ✅ `features/create-user/api/create-user.mutation.ts`
4. **Wrong folder naming**
- ❌ `features/createUser/`
- ✅ `features/create-user/`
5. **Mixing GET and POST in same layer**
- Keep GET requests in `entities/[entity]/api/`
- Keep mutations in `features/[action-verb]/api/`
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/airoad-frontend-guide/raw