# frontend > export interface Post { id: number; title: string; content: string; author: User; created_at: string; } - Author: Selvashankar Palanisamy - Repository: pselvashankar/AI_FullStack_Development_Kit - Version: 20251227215020 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/pselvashankar/AI_FullStack_Development_Kit - Web: https://mule.run/skillshub/@@pselvashankar/AI_FullStack_Development_Kit~frontend:20251227215020 --- # React Frontend Skill ## Purpose Build modern React applications with TypeScript, proper component architecture, and state management. ## Project Setup ```bash npm create vite@latest frontend -- --template react-ts cd frontend npm install axios react-router-dom @tanstack/react-query tailwindcss ``` ## Project Structure ``` src/ ├── components/ │ ├── ui/ # Button, Input, Card │ ├── forms/ # LoginForm, RegisterForm │ └── layout/ # Header, Footer, Sidebar ├── pages/ # Route pages ├── hooks/ # Custom hooks ├── services/ # API client ├── context/ # React context ├── types/ # TypeScript interfaces ├── utils/ # Helper functions └── App.tsx ``` ## Type Definitions ```typescript // types/index.ts export interface User { id: number; email: string; full_name: string | null; avatar_url: string | null; is_active: boolean; } export interface Post { id: number; title: string; content: string; author: User; created_at: string; } export interface PaginatedResponse { items: T[]; total: number; page: number; pages: number; } ``` ## Auth Context ```typescript // context/AuthContext.tsx import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import { User } from '../types'; import { authService } from '../services/auth'; interface AuthContextType { user: User | null; isLoading: boolean; isAuthenticated: boolean; login: (email: string, password: string) => Promise; logout: () => void; googleLogin: () => void; } const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const init = async () => { const token = localStorage.getItem('access_token'); if (token) { try { const userData = await authService.getCurrentUser(); setUser(userData); } catch { authService.clearTokens(); } } setIsLoading(false); }; init(); }, []); const login = async (email: string, password: string) => { await authService.login(email, password); const userData = await authService.getCurrentUser(); setUser(userData); }; const logout = () => { authService.clearTokens(); setUser(null); }; return ( {children} ); } export const useAuth = () => { const context = useContext(AuthContext); if (!context) throw new Error('useAuth must be used within AuthProvider'); return context; }; ``` ## Base UI Components ```typescript // components/ui/Button.tsx import { ButtonHTMLAttributes, forwardRef } from 'react'; interface ButtonProps extends ButtonHTMLAttributes { variant?: 'primary' | 'secondary' | 'outline'; isLoading?: boolean; } export const Button = forwardRef( ({ variant = 'primary', isLoading, children, className, ...props }, ref) => { const variants = { primary: 'bg-blue-600 text-white hover:bg-blue-700', secondary: 'bg-gray-600 text-white hover:bg-gray-700', outline: 'border border-gray-300 hover:bg-gray-50', }; return ( ); } ); // components/ui/Input.tsx import { InputHTMLAttributes, forwardRef } from 'react'; interface InputProps extends InputHTMLAttributes { label?: string; error?: string; } export const Input = forwardRef( ({ label, error, className, ...props }, ref) => (
{label && } {error &&

{error}

}
) ); ``` ## Protected Route ```typescript // components/ProtectedRoute.tsx import { Navigate, useLocation } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; export function ProtectedRoute({ children }: { children: React.ReactNode }) { const { isAuthenticated, isLoading } = useAuth(); const location = useLocation(); if (isLoading) { return
Loading...
; } if (!isAuthenticated) { return ; } return <>{children}; } ``` ## App Router ```typescript // App.tsx import { BrowserRouter, Routes, Route } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { AuthProvider } from './context/AuthContext'; import { ProtectedRoute } from './components/ProtectedRoute'; import { LoginPage } from './pages/LoginPage'; import { DashboardPage } from './pages/DashboardPage'; const queryClient = new QueryClient(); export default function App() { return ( } /> } /> ); } ``` ## Custom Hooks with React Query ```typescript // hooks/usePosts.ts import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import api from '../services/api'; export function usePosts(page = 1) { return useQuery({ queryKey: ['posts', page], queryFn: () => api.get(`/posts?page=${page}`).then(r => r.data), }); } export function useCreatePost() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: any) => api.post('/posts', data), onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }), }); } ``` ## Best Practices - Use TypeScript for all components - Implement error boundaries - Add loading states - Use React Query for server state - Implement form validation - Add accessibility attributes