Setting up the perfect React + TypeScript project takes forever — TypeScript config, ESLint, path aliases, state management, routing, auth, UI components. Most developers waste 1-2 days on boilerplate before writing a single real feature.
I've packaged 5 production-ready React + TypeScript starter templates that cover every common use case.
The 5 Templates
1. Minimal React + TypeScript (Vite)
The zero-opinion baseline. Vite 5 + React 18 + TypeScript 5.4 strict mode + ESLint/Prettier + path aliases. Nothing more, nothing less.
npm create vite@latest my-app -- --template react-ts
# Then add these in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"paths": { "@/*": ["src/*"] }
}
}
Use this when: Quick prototyping, simple tools, personal projects.
2. React + TypeScript + React Query + Zustand
For data-heavy dashboards and apps with complex async state.
// Typed API hook — React Query v5
export function useUsers() {
return useQuery<User[], ApiError>({
queryKey: ['users'],
queryFn: () => apiClient.get<User[]>('/users').then(r => r.data),
staleTime: 5 * 60 * 1000, // 5 minutes cache
});
}
// Zustand auth store with TypeScript
interface AuthStore {
user: User | null;
token: string | null;
login: (user: User, token: string) => void;
logout: () => void;
}
export const useAuthStore = create<AuthStore>()((set) => ({
user: null,
token: localStorage.getItem('token'),
login: (user, token) => {
localStorage.setItem('token', token);
set({ user, token });
},
logout: () => {
localStorage.removeItem('token');
set({ user: null, token: null });
},
}));
Use this when: Admin panels, analytics dashboards, apps with lots of API calls.
3. React + TypeScript + React Router v6 + Auth
Multi-page apps with protected routes and login flows.
// Protected route with redirect-after-login
export const ProtectedRoute = ({ children }: { children: ReactNode }) => {
const { isAuthenticated } = useAuth();
const location = useLocation();
if (!isAuthenticated) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return <>{children}</>;
};
// Typed route params — no more unsafe casting
const UserPage = () => {
const { userId } = useParams<{ userId: string }>();
// userId is string | undefined — properly typed
};
Use this when: Any app with authentication and multiple pages.
4. React + TypeScript + Tailwind CSS + shadcn/ui
Design-ready component system for shipping polished UIs fast.
// Typed component with cn() utility
interface DataCardProps {
title: string;
value: string | number;
trend?: 'up' | 'down' | 'neutral';
className?: string;
}
export const DataCard = ({ title, value, trend, className }: DataCardProps) => (
<Card className={cn("p-6", className)}>
<CardTitle className="text-sm font-medium text-muted-foreground">
{title}
</CardTitle>
<div className="text-2xl font-bold">{value}</div>
{trend && (
<Badge variant={trend === 'up' ? 'default' : 'destructive'}>
{trend === 'up' ? '↑' : '↓'} {trend}
</Badge>
)}
</Card>
);
Use this when: Any product that needs to look good without a dedicated designer.
5. Full SaaS React App
Feature-based architecture with auth, dashboard, billing (Stripe), and settings pages.
react-ts-saas/
├── src/features/
│ ├── auth/ # Login, register, forgot password
│ ├── dashboard/ # Stats, activity, charts
│ ├── billing/ # Pricing table, Stripe checkout
│ └── settings/ # Profile, security, notifications
└── src/layouts/
├── SidebarLayout.tsx # Main app layout
└── MarketingLayout.tsx # Landing page layout
Use this when: Launching a SaaS product or complex web app.
5 TypeScript Patterns Every React Developer Needs
Pattern 1: Type your props, always
// ❌ Loses all type safety
const Button = ({ onClick, label }: any) => ...
// ✅ Full autocomplete + compile-time errors
interface ButtonProps {
onClick: () => void;
label: string;
variant?: 'primary' | 'secondary' | 'danger';
}
Pattern 2: Typed refs
// ❌ No type info
const inputRef = useRef(null);
// ✅ Fully typed DOM ref
const inputRef = useRef<HTMLInputElement>(null);
// inputRef.current?.value — properly typed
Pattern 3: Generic components
function DataTable<T extends { id: string | number }>({
data,
columns,
}: DataTableProps<T>) {
// Works for any typed data shape
}
// Usage — TypeScript validates column keys
<DataTable<User>
data={users}
columns={[{ key: 'name', header: 'Name' }]}
/>
Pattern 4: Discriminated unions for fetch state
type FetchState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: string };
// TypeScript narrows automatically in JSX
{state.status === 'success' && <UserList users={state.data} />}
{state.status === 'error' && <ErrorBanner message={state.error} />}
Pattern 5: Typed API responses
interface ApiResponse<T> {
data: T;
message: string;
success: boolean;
}
async function fetchUsers(): Promise<ApiResponse<User[]>> {
const res = await fetch('/api/users');
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
}
Choosing the Right Template
| Project Type | Template |
|---|---|
| Quick prototype | Minimal (Template 1) |
| Data dashboard | React Query + Zustand (Template 2) |
| Multi-page with auth | React Router (Template 3) |
| UI-heavy product | Tailwind + shadcn (Template 4) |
| Full SaaS | SaaS All-in-One (Template 5) |
Quick Deploy (All Templates)
Vercel (15 seconds):
npx vercel --prod
Netlify:
npm run build
# Drop dist/ on netlify.com/drop
All 5 templates are included in the React + TypeScript Production Starter Kit — pre-configured, documented, and ready to clone. Each template includes TypeScript strict config, ESLint/Prettier setup, path aliases, and example components showing real-world patterns.
Stop setting up boilerplate. Start shipping.
Top comments (0)