Skip to content
frontend-dev-guidelines logo

frontend-dev-guidelines

Frontend development guidelines for React/TypeScript applications. Modern patterns including Suspense, lazy loading, useSuspenseQuery, file organization with features directory, shadcn/ui components, Tailwind CSS styling, TanStack Router, performance optimization, and TypeScript best practices. U...

SKILL.md

Full skill instructions

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 shadcn/​ui and Tailwind CSS
  • 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
  • Use shadcn/​ui components from @/​components/​ui
  • Style with Tailwind CSS classes and cn() utility
  • Use useCallback for event handlers passed to children
  • Default export at bottom
  • No early returns with loading spinners
  • Use sonner toast 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

AliasResolves ToExample
@/src/import { apiClient } from '@/​lib/​apiClient'
~typessrc/​typesimport type { User } from '~types/​user'
~componentssrc/​componentsimport { SuspenseLoader } from '~components/​SuspenseLoader'
~featuressrc/​featuresimport { 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'));

// shadcn/​ui Components
import { Button } from '@/​components/​ui/​button';
import { Card, CardContent, CardHeader, CardTitle } from '@/​components/​ui/​card';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/​components/​ui/​dialog';
import { Input } from '@/​components/​ui/​input';
import { cn } from '@/​lib/​utils';

// 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 { toast } from 'sonner';

// 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

Tailwind CSS with shadcn/​ui:

  • Use Tailwind utility classes directly
  • Use cn() utility for conditional classes
  • Use CSS variables for theming

Primary Method:

  • Tailwind classes in className prop
  • cn() for merging classes conditionally
  • shadcn/​ui components handle base styling

Example:

<div className="flex flex-col gap-4 p-6">
  <Card className={cn("w-full", isActive && "border-primary")}>
    <CardContent className="grid grid-cols-1 md:grid-cols-2 gap-4">
      {/​* Content */​}
    </​CardContent>
  </​Card>
</​div>

📖 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 sonner toast 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 componentcomponent-patterns.md
Fetch datadata-fetching.md
Organize files/​foldersfile-organization.md
Style componentsstyling-guide.md
Set up routingrouting-guide.md
Handle loading/​errorsloading-and-error-states.md
Optimize performanceperformance.md
TypeScript typestypescript-standards.md
Forms/​Auth/​DataGridcommon-patterns.md
See full examplescomplete-examples.md

Core Principles

  1. Lazy Load Everything Heavy: Routes, DataGrid, charts, editors
  2. Suspense for Loading: Use SuspenseLoader, not early returns
  3. useSuspenseQuery: Primary data fetching pattern for new code
  4. Features are Organized: api/, components/, hooks/, helpers/ subdirs
  5. shadcn/​ui + Tailwind: Use shadcn components with Tailwind classes
  6. Import Aliases: Use @/, ~types, ~components, ~features
  7. No Early Returns: Prevents layout shift
  8. sonner toast: 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 { useSuspenseQuery } from '@tanstack/​react-query';
import { Card, CardContent } from '@/​components/​ui/​card';
import { Button } from '@/​components/​ui/​button';
import { cn } from '@/​lib/​utils';
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 (
        <div className="p-4">
            <Card className="p-6">
                <CardContent className="space-y-4">
                    {/​* Content */​}
                </​CardContent>
            </​Card>
        </​div>
    );
};

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 management