back
loading skill details...
Frontend development guidelines for React/TypeScript applications. Modern patterns including Suspense, lazy loading, useSuspenseQuery, file organization with…
Frontend Development Guidelines
Purpose
Comprehensive guide for modern React development, emphasizing Suspense-based data fetching, lazy loading, proper file organization, and performance optimization.
When to Use This Skill
Creating new components or pages
Building new features
Fetching data with TanStack Query
Setting up routing with TanStack Router
Styling components with MUI v7
Performance optimization
Organizing frontend code
TypeScript best practices
Quick Start
New Component Checklist
Creating a component? Follow this checklist:
Use React.FC<Props> pattern with TypeScript
Lazy load if heavy component: React.lazy(() => import())
Wrap in <SuspenseLoader> for loading states
Use useSuspenseQuery for data fetching
Import aliases: @/, ~types, ~components, ~features
Styles: Inline if <100 lines, separate file if >100 lines
Use useCallback for event handlers passed to children
Default export at bottom
No early returns with loading spinners
Use useMuiSnackbar for user notifications
New Feature Checklist
Creating a feature? Set up this structure:
Create features/{feature-name}/ directory
Create subdirectories: api/, components/, hooks/, helpers/, types/
Create API service file: api/{feature}Api.ts
Set up TypeScript types in types/
Create route in routes/{feature-name}/index.tsx
Lazy load feature components
Use Suspense boundaries
Export public API from feature index.ts
Import Aliases Quick Reference
Alias
Resolves To
Example
@/
src/
import { apiClient } from '@/lib/apiClient'
~types
src/types
import type { User } from '~types/user'
~components
src/components
import { SuspenseLoader } from '~components/SuspenseLoader'
~features
src/features
import { authApi } from '~features/auth'
Defined in: vite.config.ts lines 180-185
Common Imports Cheatsheet
// React & Lazy Loading
import React, { useState, useCallback, useMemo } from 'react';
const Heavy = React.lazy(() => import('./Heavy'));
// MUI Components
import { Box, Paper, Typography, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
// TanStack Query (Suspense)
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
// TanStack Router
import { createFileRoute } from '@tanstack/react-router';
// Project Components
import { SuspenseLoader } from '~components/SuspenseLoader';
// Hooks
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
// Types
import type { Post } from '~types/post';
Topic Guides
🎨 Component Patterns
Modern React components use:
React.FC<Props> for type safety
React.lazy() for code splitting
SuspenseLoader for loading states
Named const + default export pattern
Key Concepts:
Lazy load heavy components (DataGrid, charts, editors)
Always wrap lazy components in Suspense
Use SuspenseLoader component (with fade animation)
Component structure: Props → Hooks → Handlers → Render → Export
📖 Complete Guide: resources/component-patterns.md
📊 Data Fetching
PRIMARY PATTERN: useSuspenseQuery
Use with Suspense boundaries
Cache-first strategy (check grid cache before API)
Replaces isLoading checks
Type-safe with generics
API Service Layer:
Create features/{feature}/api/{feature}Api.ts
Use apiClient axios instance
Centralized methods per feature
Route format: /form/route (NOT /api/form/route)
📖 Complete Guide: resources/data-fetching.md
📁 File Organization
features/ vs components/:
features/: Domain-specific (posts, comments, auth)
components/: Truly reusable (SuspenseLoader, CustomAppBar)
Feature Subdirectories:
features/
my-feature/
api/ # API service layer
components/ # Feature components
hooks/ # Custom hooks
helpers/ # Utility functions
types/ # TypeScript types
📖 Complete Guide: resources/file-organization.md
🎨 Styling
Inline vs Separate:
<100 lines: Inline const styles: Record<string, SxProps<Theme>>
100 lines: Separate .styles.ts file
Primary Method:
Use sx prop for MUI components
Type-safe with SxProps<Theme>
Theme access: (theme) => theme.palette.primary.main
MUI v7 Grid:
<Grid size={{ xs: 12, md: 6 }}> // ✅ v7 syntax
<Grid xs={12} md={6}> // ❌ Old syntax
📖 Complete Guide: resources/styling-guide.md
🛣️ Routing
TanStack Router - Folder-Based:
Directory: routes/my-route/index.tsx
Lazy load components
Use createFileRoute
Breadcrumb data in loader
Example:
import { createFileRoute } from '@tanstack/react-router';
import { lazy } from 'react';
const MyPage = lazy(() => import('@/features/my-feature/components/MyPage'));
export const Route = createFileRoute('/my-route/')({
component: MyPage,
loader: () => ({ crumb: 'My Route' }),
});
📖 Complete Guide: resources/routing-guide.md
⏳ Loading & Error States
CRITICAL RULE: No Early Returns
// ❌ NEVER - Causes layout shift
if (isLoading) {
return <LoadingSpinner />;
}
// ✅ ALWAYS - Consistent layout
<SuspenseLoader>
<Content />
</SuspenseLoader>
Why: Prevents Cumulative Layout Shift (CLS), better UX
Error Handling:
Use useMuiSnackbar for user feedback
NEVER react-toastify
TanStack Query onError callbacks
📖 Complete Guide: resources/loading-and-error-states.md
⚡ Performance
Optimization Patterns:
useMemo: Expensive computations (filter, sort, map)
useCallback: Event handlers passed to children
React.memo: Expensive components
Debounced search (300-500ms)
Memory leak prevention (cleanup in useEffect)
📖 Complete Guide: resources/performance.md
📘 TypeScript
Standards:
Strict mode, no any type
Explicit return types on functions
Type imports: import type { User } from '~types/user'
Component prop interfaces with JSDoc
📖 Complete Guide: resources/typescript-standards.md
🔧 Common Patterns
Covered Topics:
React Hook Form with Zod validation
DataGrid wrapper contracts
Dialog component standards
useAuth hook for current user
Mutation patterns with cache invalidation
📖 Complete Guide: resources/common-patterns.md
📚 Complete Examples
Full working examples:
Modern component with all patterns
Complete feature structure
API service layer
Route with lazy loading
Suspense + useSuspenseQuery
Form with validation
📖 Complete Guide: resources/complete-examples.md
Navigation Guide
Need to...
Read this resource
Create a component
component-patterns.md
Fetch data
data-fetching.md
Organize files/folders
file-organization.md
Style components
styling-guide.md
Set up routing
routing-guide.md
Handle loading/errors
loading-and-error-states.md
Optimize performance
performance.md
TypeScript types
typescript-standards.md
Forms/Auth/DataGrid
common-patterns.md
See full examples
complete-examples.md
Core Principles
Lazy Load Everything Heavy: Routes, DataGrid, charts, editors
Suspense for Loading: Use SuspenseLoader, not early returns
useSuspenseQuery: Primary data fetching pattern for new code
Features are Organized: api/, components/, hooks/, helpers/ subdirs
Styles Based on Size: <100 inline, >100 separate
Import Aliases: Use @/, ~types, ~components, ~features
No Early Returns: Prevents layout shift
useMuiSnackbar: For all user notifications
Quick Reference: File Structure
src/
features/
my-feature/
api/
myFeatureApi.ts # API service
components/
MyFeature.tsx # Main component
SubComponent.tsx # Related components
hooks/
useMyFeature.ts # Custom hooks
useSuspenseMyFeature.ts # Suspense hooks
helpers/
myFeatureHelpers.ts # Utilities
types/
index.ts # TypeScript types
index.ts # Public exports
components/
SuspenseLoader/
SuspenseLoader.tsx # Reusable loader
CustomAppBar/
CustomAppBar.tsx # Reusable app bar
routes/
my-route/
index.tsx # Route component
create/
index.tsx # Nested route
Modern Component Template (Quick Copy)
import React, { useState, useCallback } from 'react';
import { Box, Paper } from '@mui/material';
import { useSuspenseQuery } from '@tanstack/react-query';
import { featureApi } from '../api/featureApi';
import type { FeatureData } from '~types/feature';
interface MyComponentProps {
id: number;
onAction?: () => void;
}
export const MyComponent: React.FC<MyComponentProps> = ({ id, onAction }) => {
const [state, setState] = useState<string>('');
const { data } = useSuspenseQuery({
queryKey: ['feature', id],
queryFn: () => featureApi.getFeature(id),
});
const handleAction = useCallback(() => {
setState('updated');
onAction?.();
}, [onAction]);
return (
<Box sx={{ p: 2 }}>
<Paper sx={{ p: 3 }}>
{/* Content */}
</Paper>
</Box>
);
};
export default MyComponent;
For complete examples, see resources/complete-examples.md
Related Skills
error-tracking: Error tracking with Sentry (applies to frontend too)
backend-dev-guidelines: Backend API patterns that frontend consumes
Skill Status: Modular structure with progressive loading for optimal context managementdon't have the plugin yet? install it then click "run inline in claude" again.