A modern, production-ready React + Redux + Tailwind CSS boilerplate with best practices, feature-rich setup, and comprehensive tooling.
- React 19 - Latest React with hooks support
- Redux Toolkit - Simplified Redux state management with Redux Toolkit
- Tailwind CSS 4 - Utility-first CSS framework for rapid UI development
- Vite - Lightning-fast build tool and development server
- React Router v7 - Client-side routing with latest React Router
- ESLint & Prettier - Code quality and formatting tools
- Axios - Promise-based HTTP client with interceptors
- React Toastify - Toast notifications
- Lucide React - Beautiful and consistent icon library
- Responsive Design - Mobile-first responsive components
- TypeScript Ready - Pre-configured for TypeScript projects
- Node.js 16+
- npm or yarn
- Clone the repository:
git clone <repository-url>
cd react-boilerplate- Install dependencies:
npm install- Create environment file:
cp .env.example .env- Configure your environment variables:
VITE_API_BASE_URL=http://localhost:3000/api
VITE_APP_NAME=React Boilerplate- Start the development server:
npm run devThe application will be available at http://localhost:5173
npm run dev- Start development server with Vitenpm run build- Build for productionnpm run preview- Preview production build locallynpm run lint- Run ESLint to check code qualitynpm run format- Format code with Prettier
src/
βββ components/
β βββ common/ # Shared components across features
β βββ ui/ # Basic UI components (Button, Input, etc.)
βββ config/
β βββ constants.js # Application constants
β βββ env.js # Environment variable validation
βββ features/
β βββ store.js # Redux store configuration
β βββ auth/ # Authentication feature
β βββ counter/ # Counter example feature
β βββ products/ # Products feature with API
β βββ productsAPI.js
β βββ productsSlice.js
βββ pages/
β βββ admin/ # Admin-only pages
β βββ auth/ # Authentication pages
β βββ error/ # Error pages (404, 500, etc.)
β β βββ NotFound.jsx
β βββ public/ # Public pages
β βββ public_about/
β β βββ AboutView.jsx
β βββ public_contact/
β β βββ ContactView.jsx
β βββ public_Home/
β βββ HomeView.jsx
βββ router/
β βββ router.jsx # Main router configuration
β βββ guard/ # Route guards for authentication
β βββ layout/ # Layout components
β βββ FooterLayout.jsx
β βββ NavbarLayout.jsx
β βββ RootLayout.jsx
βββ services/
β βββ axiosInstance.js # Configured Axios instance
β βββ httpEndpoint.js # API endpoint definitions
β βββ httpMethods.js # HTTP method helpers
βββ utils/
βββ errorHandler.js # Global error handling
βββ Helper.js # General helper functions
βββ storage.js # LocalStorage/SessionStorage helpers
βββ validators.js # Form validation functions
Create a .env file in the root directory:
# API Configuration
VITE_API_BASE_URL=http://localhost:3000/api
# App Configuration
VITE_APP_NAME=React BoilerplateTailwind CSS 4 is configured with the @tailwindcss/vite plugin. Customize your design in the CSS file:
@import 'tailwindcss';
@theme {
/* Your custom theme configuration */
}The store is configured in src/features/store.js. Add new features by creating slices:
// src/features/myFeature/myFeatureSlice.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
data: [],
loading: false,
error: null,
};
export const myFeatureSlice = createSlice({
name: 'myFeature',
initialState,
reducers: {
setData: (state, action) => {
state.data = action.payload;
},
setLoading: (state, action) => {
state.loading = action.payload;
},
setError: (state, action) => {
state.error = action.payload;
},
},
});
export const { setData, setLoading, setError } = myFeatureSlice.actions;
export default myFeatureSlice.reducer;Then add it to the store:
// src/features/store.js
import { configureStore } from '@reduxjs/toolkit';
import myFeatureReducer from './myFeature/myFeatureSlice';
const store = configureStore({
reducer: {
myFeature: myFeatureReducer,
// ... other reducers
},
});
export default store;- Clone and Setup: Follow the Quick Start guide above
- Configure Environment: Update
.envwith your API endpoints - Customize Branding: Update app name, logo, and colors
- Clean Example Code: Remove example features you don't need
- Create a new folder in
src/pages/public/(oradmin/for admin pages) - Create your component file (e.g.,
MyPageView.jsx) - Add the route in
src/router/router.jsx
// src/pages/public/my_page/MyPageView.jsx
import React from 'react';
const MyPageView = () => {
return (
<div className="container mx-auto px-4 py-8">
<h1>My New Page</h1>
</div>
);
};
export default MyPageView;// src/router/router.jsx
import MyPageView from '../pages/public/my_page/MyPageView';
// Add to your routes
<Route path="my-page" element={<MyPageView />} />;- Create a new folder in
src/features/ - Create your slice file following the pattern in
src/features/products/ - Add API functions if needed
- Connect to the store
The boilerplate includes a configured Axios instance in src/services/axiosInstance.js:
// Example API call
import { createAsyncThunk } from '@reduxjs/toolkit';
import axiosInstance from '../../services/axiosInstance';
export const fetchMyData = createAsyncThunk(
'myFeature/fetchMyData',
async (params, { rejectWithValue }) => {
try {
const response = await axiosInstance.get('/my-endpoint', { params });
return response.data;
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);Use Tailwind CSS utility classes for styling:
const MyComponent = () => {
return (
<div className="rounded-lg bg-white p-6 shadow-md transition-shadow hover:shadow-lg">
<h2 className="mb-4 text-2xl font-bold text-gray-900">Title</h2>
<p className="leading-relaxed text-gray-600">Content</p>
<button className="mt-4 rounded-md bg-blue-600 px-4 py-2 text-white transition-colors hover:bg-blue-700">
Action
</button>
</div>
);
};Example form with validation:
import React, { useState } from 'react';
const MyForm = () => {
const [formData, setFormData] = useState({ name: '', email: '' });
const [errors, setErrors] = useState({});
const validate = () => {
const newErrors = {};
if (!formData.name.trim()) newErrors.name = 'Name is required';
if (!formData.email.includes('@')) newErrors.email = 'Valid email is required';
return newErrors;
};
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = validate();
if (Object.keys(newErrors).length === 0) {
// Handle successful submission
console.log('Form submitted:', formData);
} else {
setErrors(newErrors);
}
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<input
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full rounded-md border border-gray-300 px-3 py-2 focus:ring-2 focus:ring-blue-500"
placeholder="Name"
/>
{errors.name && <p className="mt-1 text-sm text-red-500">{errors.name}</p>}
</div>
{/* More form fields... */}
<button type="submit" className="rounded-md bg-blue-600 px-4 py-2 text-white">
Submit
</button>
</form>
);
};To add authentication to your app:
- Create Auth Slice in
src/features/auth/authSlice.js - Add Auth API functions in
src/features/auth/authAPI.js - Create Route Guards in
src/router/guard/ - Update Axios Interceptors to handle tokens
Example auth slice:
// src/features/auth/authSlice.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
user: null,
token: localStorage.getItem('token'),
isAuthenticated: false,
loading: false,
error: null,
};
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
loginStart: (state) => {
state.loading = true;
state.error = null;
},
loginSuccess: (state, action) => {
state.loading = false;
state.user = action.payload.user;
state.token = action.payload.token;
state.isAuthenticated = true;
localStorage.setItem('token', action.payload.token);
},
loginFailure: (state, action) => {
state.loading = false;
state.error = action.payload;
state.isAuthenticated = false;
},
logout: (state) => {
state.user = null;
state.token = null;
state.isAuthenticated = false;
localStorage.removeItem('token');
},
},
});
export const { loginStart, loginSuccess, loginFailure, logout } = authSlice.actions;
export default authSlice.reducer;Update your Tailwind theme by modifying the CSS:
@theme {
--color-primary-50: #eff6ff;
--color-primary-500: #3b82f6;
--color-primary-900: #1e3a8a;
}Create reusable components in src/components/:
// src/components/ui/Card.jsx
const Card = ({ children, className = '', ...props }) => {
return (
<div className={`rounded-lg bg-white p-6 shadow-md ${className}`} {...props}>
{children}
</div>
);
};
export default Card;npm run build- Connect your repository to Vercel
- Set environment variables in Vercel dashboard
- Deploy automatically on push to main branch
- Build the project:
npm run build - Deploy the
distfolder to Netlify - Configure redirects for SPA in
_redirectsfile
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- React - The web framework used
- Redux Toolkit - State management
- Tailwind CSS - Styling framework
- Vite - Build tool
- Lucide - Icon library
If you have any questions or need help getting started:
- π§ Email: hello@reactboilerplate.dev
- π¬ Discord: Join our community
- π Issues: GitHub Issues
- π Docs: Documentation
Happy Coding! π
npm run lint- Run ESLint to check code qualitynpm run format- Format code with Prettier
src/
βββ api/
β βββ apiClient.js
β βββ endpoints/
β βββ exampleApi.js
βββ app/
β βββ store.js
β βββ rootReducer.js
βββ components/
β βββ common/
β β βββ Button/
β β β βββ Button.jsx
β β β βββ index.js
β β βββ Input/
β β β βββ Input.jsx
β β β βββ index.js
β β βββ LoadingSpinner/
β β βββ LoadingSpinner.jsx
β β βββ index.js
β βββ layout/
β βββ Header/
β β βββ Header.jsx
β β βββ index.js
β βββ Footer/
β βββ Footer.jsx
β βββ index.js
βββ features/
β βββ auth/
β β βββ components/
β β βββ hooks/
β β βββ authSlice.js
β β βββ authApi.js
β βββ todos/
β β βββ components/
β β βββ hooks/
β β βββ todosSlice.js
β β βββ todosApi.js
β βββ counter/
β βββ components/
β βββ hooks/
β βββ counterSlice.js
β βββ counterApi.js
βββ hooks/
β βββ useDebounce.js
β βββ useLocalStorage.js
β βββ useMediaQuery.js
βββ utils/
β βββ constants.js
β βββ helpers.js
β βββ validators.js
βββ styles/
β βββ globals.css
βββ routes/
β βββ PrivateRoute.jsx
β βββ AppRoutes.jsx
βββ App.jsx
The Tailwind CSS configuration is located in tailwind.config.js. Customize your design tokens here:
export default {
content: ['./index.html', './src/**/*.{js,jsx}'],
theme: {
extend: {
colors: {
/* ... */
},
spacing: {
/* ... */
},
},
},
darkMode: 'class',
};Redux slices are located in src/store/slices/. Create new slices for different features:
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
/* ... */
};
export const featureSlice = createSlice({
name: 'feature',
initialState,
reducers: {
// Add your reducers here
},
});
export const {
/* actions */
} = featureSlice.actions;
export default featureSlice.reducer;Then register the slice in src/store/store.js:
import featureReducer from './slices/featureSlice';
export const store = configureStore({
reducer: {
// ... other reducers
feature: featureReducer,
},
});import { useDispatch, useSelector } from 'react-redux';
import { toggleTheme } from '../store/slices/appSlice';
export default function Component() {
const dispatch = useDispatch();
const theme = useSelector((state) => state.app.theme);
return <button onClick={() => dispatch(toggleTheme())}>Current theme: {theme}</button>;
}import Button from '../components/ui/Button';
import Card from '../components/ui/Card';
export default function Example() {
return (
<Card>
<h2 className="text-xl font-bold">Welcome</h2>
<p className="mt-2 text-gray-600">Hello, World!</p>
<Button variant="primary" size="md" className="mt-4">
Click Me
</Button>
</Card>
);
}export default function Component() {
return (
<div className="flex items-center justify-center rounded-lg bg-blue-500 px-6 py-4 text-white shadow-lg hover:bg-blue-600 dark:bg-blue-900">
Tailwind styled component
</div>
);
}Versatile button component with multiple variants and sizes.
<Button variant="primary" size="md">
Primary Button
</Button>
<Button variant="secondary" size="sm">
Secondary Button
</Button>
<Button variant="danger" size="lg">
Danger Button
</Button>Props:
variant:'primary'|'secondary'|'danger'(default:'primary')size:'sm'|'md'|'lg'(default:'md')className: Additional CSS classes- All standard HTML button attributes
Container component for grouping content.
<Card className="max-w-md">
<h3 className="font-bold">Card Title</h3>
<p>Card content goes here</p>
</Card>Props:
children: Card contentclassName: Additional CSS classes
Component to switch between light and dark modes.
<ThemeToggle />Dark mode is built-in using Tailwind's class-based dark mode. To enable dark mode:
// In your component
<div className="bg-white text-gray-900 dark:bg-gray-900 dark:text-white">Content</div>The ThemeToggle component is already integrated and manages the theme state via Redux.
- react - UI library
- react-dom - DOM rendering
- react-redux - Redux bindings for React
- @reduxjs/toolkit - Redux state management
- tailwindcss - Utility-first CSS framework
- @tailwindcss/vite - Vite plugin for Tailwind CSS
- clsx - Utility for constructing className strings
- react-router-dom - Client-side routing
- axios - HTTP client
- react-toastify - Toast notifications
- vite - Build tool
- eslint - Code quality
- prettier - Code formatter
- prettier-plugin-tailwindcss - Tailwind CSS class sorting
- Component Organization - Keep components modular and focused on single responsibility
- Redux Slices - Use Redux Toolkit slices for cleaner state management
- Styling - Prefer Tailwind CSS utility classes over custom CSS
- Type Safety - Consider using TypeScript for larger projects
- Performance - Use React.memo and useMemo for performance optimization
- Testing - Add tests using Jest and React Testing Library
- Code Quality - Run ESLint and Prettier regularly
- Environment Variables - Use
.envfiles for sensitive data
npm run buildThis generates an optimized build in the dist/ directory.
npm run preview- Install Vercel CLI:
npm i -g vercel - Run:
vercel - Follow the prompts
- Push code to GitHub
- Connect repository to Netlify
- Set build command:
npm run build - Set publish directory:
dist
- React Documentation
- Redux Toolkit Documentation
- Tailwind CSS Documentation
- Vite Documentation
- React Router Documentation
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Use the Redux DevTools browser extension for better state debugging
- Leverage Tailwind's responsive prefixes (sm:, md:, lg:) for responsive design
- Create custom Tailwind components using
@applyin your CSS - Keep your Redux slices small and focused
- Consider using Redux Thunk or Redux Saga for async operations
If port 5173 is already in use, Vite will automatically use the next available port.
- Ensure content paths in
tailwind.config.jsare correct - Clear Tailwind cache:
rm -rf node_modules/.vite - Restart the dev server
Ensure Provider wraps your app in main.jsx and the store is properly configured.
Built with β€οΈ using React, Redux, and Tailwind CSS