Expert guidance for React 4Prop CRM development with TanStack Router, React Query, Zustand, Radix UI, and React Hook Form. Enforces architectural patterns and API validation.
Expert guidance for developing the React 4Prop CRM application built with TanStack Router, TanStack Query, Zustand, Radix UI, and React Hook Form.
**NEVER assume API request or response JSON shapes.** Before using any API endpoint:
1. Ask the user to confirm all field names, types, and nesting
2. If a shape isn't clearly defined in the codebase, request clarification
3. Consistency between frontend and backend is critical
All forms in the frontend **must** use React Hook Form with Yup/Zod validation. Never use `useState` or custom input handlers for managing form data.
When working on tasks, use these commands:
```bash
npm run dev:crm # CRM only (frontend development)
npm run dev # Full stack with backend services
npm run build # Production build
npm run lint # Code linting
npm run deploy # Deploy to GitHub Pages
npm run generate # Generate TanStack Router routes
```
1. **Starting development**: Use `npm run dev:crm` for frontend-only work
2. **After adding/modifying routes**: Run `npm run generate` to update TanStack Router
3. **Before committing**: Run `npm run lint` to catch issues
4. **Testing production build**: Run `npm run build` and verify output
**File-based routing conventions:**
**Data preloading pattern** (use this for optimal loading UX):
1. **In route file**, use `beforeLoad` to create query options and add to context:
```javascript
beforeLoad: async ({ context }) => {
const queryOptions = {
queryKey: ['data-key'],
queryFn: () => fetchData(),
};
return { ...context, queryOptions };
}
```
2. **Use `loader`** to preload data:
```javascript
loader: ({ context }) => {
return context.queryClient.ensureQueryData(context.queryOptions);
}
```
3. **In components**, access preloaded data with the same query key:
```javascript
const { data } = useQuery({ queryKey: ['data-key'], queryFn: fetchData });
```
4. **Implement loading overlays** at the route level for refetch states
This ensures data is preloaded, cached, and components get immediate access with proper loading states.
**Server state:** Always use TanStack Query (`useQuery`, `useMutation`)
**Client state:** Use Zustand stores
**Organize by feature:**
```
/src/components/
├── ui/ # Radix UI base components
├── ui-custom/ # Custom UI variants
└── [feature]/ # Feature-specific components
├── index.js # Exports
└── Component.jsx
```
**Always:**
The Magazine module uses a **week-based scheduling system**:
**Key components:**
When modifying Magazine features, maintain the week-based scheduling pattern.
When implementing features:
1. **Clarify API contracts** - Confirm all JSON shapes with the user first
2. **Check routing** - Verify if new routes needed and their naming convention
3. **Identify state layer** - Determine if server state (Query) or client state (Zustand)
4. **Choose components** - Use existing Radix UI components from `/ui/` or `/ui-custom/`
5. **Implement forms** - Use React Hook Form with validation schema
6. **Add data preloading** - Use TanStack Router's `beforeLoad` and `loader` pattern
7. **Create example files** - Add `*.example.jsx` for form components
8. **Test and lint** - Run `npm run lint` before completing
9. **Update routes** - Run `npm run generate` if routes were added/modified
```javascript
// MyForm.jsx
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
const schema = yup.object({
field: yup.string().required(),
});
export function MyForm({ onSubmit }) {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: yupResolver(schema),
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('field')} />
{errors.field && <span>{errors.field.message}</span>}
<button type="submit">Submit</button>
</form>
);
}
```
Then create `MyForm.example.jsx` to demonstrate usage.
```javascript
// routes/_auth/my-route.jsx
export const Route = createFileRoute('/_auth/my-route')({
beforeLoad: async ({ context }) => {
const queryOptions = {
queryKey: ['my-data'],
queryFn: fetchMyData,
};
return { ...context, queryOptions };
},
loader: ({ context }) => {
return context.queryClient.ensureQueryData(context.queryOptions);
},
component: MyRouteComponent,
});
```
```javascript
import create from 'zustand';
const useMyStore = create((set) => ({
value: '',
setValue: (value) => set({ value }),
}));
```
When receiving a task:
1. Ask about any unclear API endpoints or data structures
2. Confirm which commands to run (dev:crm vs dev)
3. Check if new routes are needed and verify naming conventions
4. Identify if Magazine module is involved (requires week-based scheduling)
5. Verify if form validation schema exists or needs creation
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/react-4prop-crm-expert/raw