React Velocity Starter: Building the Modern React Template I Wish I Had
Creating a feature-driven React starter template with modern tooling, comprehensive testing, and developer experience optimization.
Learn how to build a production-ready React starter template from scratch, following the exact methodology I used to create React Velocity Starter. This comprehensive tutorial will guide you through creating a modern, scalable React application foundation with the latest tools and best practices.
๐ฏ What You'll Build
By the end of this tutorial, you'll have created:
Feature | Description |
---|---|
Feature-Based Architecture | Scalable project structure that grows with complexity |
Modern Tooling | React 19, TypeScript 5.8+, Vite 6+ for optimal DX |
Comprehensive Testing | Vitest, Playwright, MSW for reliable testing |
Internationalization | Type-safe translations with react-i18next |
Code Generation | Plop.js templates for consistent development |
Production Ready | Optimized builds and deployment configuration |
๐ Prerequisites
Before we start, ensure you have:
Requirement | Version | Purpose |
---|---|---|
Node.js | 18+ (22+ recommended) | JavaScript runtime |
pnpm | 9+ | Package manager (preferred) |
Git | Latest | Version control |
Knowledge | React, TypeScript, modern JS | Development foundation |
๐ Step 1: Project Initialization and Basic Setup
Let's start by creating our project structure:
# Create the project directory
mkdir react-velocity-starter
cd react-velocity-starter
# Initialize the project
npm init -y
# Install pnpm globally if you haven't already
npm install -g pnpm
Update your package.json
:
{
"name": "react-velocity-starter",
"private": true,
"version": "0.1.0",
"type": "module",
"description": "Modern React starter template with TypeScript, Vite, and comprehensive tooling",
"keywords": [
"react",
"typescript",
"vite",
"starter",
"template"
],
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test": "vitest",
"test:ui": "vitest --ui",
"test:e2e": "playwright test",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --ext ts,tsx --fix",
"type-check": "tsc --noEmit",
"generate": "plop"
}
}
๐๏ธ Step 2: Feature-Based Architecture
Create a scalable folder structure:
# Create the folder structure
mkdir -p src/{features,shared,app,pages}
mkdir -p src/shared/{components,hooks,utils,types,constants}
mkdir -p src/features/{auth,dashboard}
mkdir -p src/features/auth/{components,hooks,services,types}
mkdir -p public/{icons,images}
mkdir -p docs
mkdir -p tests/{e2e,fixtures,mocks}
๐ Folder Structure Benefits
Directory | Purpose | Benefits |
---|---|---|
src/features/ | Domain-specific code | Better code organization, easier to maintain |
src/shared/ | Reusable components and utilities | Promotes code reuse and consistency |
src/app/ | Application-level configuration | Centralized app setup and providers |
tests/ | Testing utilities and fixtures | Organized testing infrastructure |
โก Step 3: Modern Tooling Configuration
๐ง Vite Configuration
Create vite.config.ts
:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { resolve } from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': resolve(__dirname, './src'),
'@/features': resolve(__dirname, './src/features'),
'@/shared': resolve(__dirname, './src/shared'),
'@/app': resolve(__dirname, './src/app'),
'@/tests': resolve(__dirname, './tests')
}
},
server: {
port: 3000,
open: true
},
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
utils: ['date-fns', 'clsx']
}
}
}
},
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./tests/setup.ts']
}
})
๐ TypeScript Configuration
Create tsconfig.json
:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/features/*": ["./src/features/*"],
"@/shared/*": ["./src/shared/*"],
"@/app/*": ["./src/app/*"],
"@/tests/*": ["./tests/*"]
}
},
"include": ["src", "tests"],
"exclude": ["node_modules", "dist"]
}
๐งช Step 4: Comprehensive Testing Setup
โ๏ธ Testing Stack Overview
Tool | Purpose | Benefits |
---|---|---|
Vitest | Unit and integration tests | Fast, Vite-native, ESM support |
Testing Library | Component testing utilities | User-centric testing approach |
Playwright | End-to-end testing | Cross-browser, reliable, fast |
MSW | API mocking | Realistic network layer mocking |
๐ฌ Test Setup Configuration
Create tests/setup.ts
:
import '@testing-library/jest-dom'
import { beforeAll, afterEach, afterAll } from 'vitest'
import { cleanup } from '@testing-library/react'
import { server } from './mocks/server'
// Start the MSW server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
// Clean up after each test
afterEach(() => {
cleanup()
server.resetHandlers()
})
// Close the server after all tests
afterAll(() => server.close())
// Mock IntersectionObserver
global.IntersectionObserver = class IntersectionObserver {
observe() {
return null
}
disconnect() {
return null
}
unobserve() {
return null
}
}
๐ญ Playwright Configuration
Create playwright.config.ts
:
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './tests/e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure'
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] }
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] }
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] }
}
],
webServer: {
command: 'pnpm dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI
}
})
๐จ Step 5: Code Generation with Plop.js
Automate component and feature creation:
// plopfile.js
export default function (plop) {
// Component generator
plop.setGenerator('component', {
description: 'Create a new React component',
prompts: [
{
type: 'input',
name: 'name',
message: 'Component name:'
},
{
type: 'list',
name: 'type',
message: 'Component type:',
choices: ['shared', 'feature']
},
{
type: 'input',
name: 'feature',
message: 'Feature name (if feature component):',
when: (answers) => answers.type === 'feature'
}
],
actions: (data) => {
const basePath = data.type === 'shared'
? 'src/shared/components'
: `src/features/${data.feature}/components`
return [
{
type: 'add',
path: `${basePath}/{{pascalCase name}}/{{pascalCase name}}.tsx`,
templateFile: 'plop-templates/component.hbs'
},
{
type: 'add',
path: `${basePath}/{{pascalCase name}}/{{pascalCase name}}.test.tsx`,
templateFile: 'plop-templates/component.test.hbs'
},
{
type: 'add',
path: `${basePath}/{{pascalCase name}}/index.ts`,
templateFile: 'plop-templates/index.hbs'
}
]
}
})
// Feature generator
plop.setGenerator('feature', {
description: 'Create a new feature module',
prompts: [
{
type: 'input',
name: 'name',
message: 'Feature name:'
}
],
actions: [
{
type: 'add',
path: 'src/features/{{kebabCase name}}/index.ts',
template: 'export * from "./components"\nexport * from "./hooks"\nexport * from "./services"'
},
{
type: 'add',
path: 'src/features/{{kebabCase name}}/components/index.ts',
template: '// Export components here'
},
{
type: 'add',
path: 'src/features/{{kebabCase name}}/hooks/index.ts',
template: '// Export hooks here'
},
{
type: 'add',
path: 'src/features/{{kebabCase name}}/services/index.ts',
template: '// Export services here'
},
{
type: 'add',
path: 'src/features/{{kebabCase name}}/types/index.ts',
template: '// Export types here'
}
]
})
}
๐ฏ Key Benefits of This Starter Template
๐ Developer Experience
- โข Hot module reloading with Vite
- โข TypeScript for type safety
- โข Code generation for consistency
- โข Comprehensive linting and formatting
๐งช Testing Excellence
- โข Unit tests with Vitest
- โข Component tests with Testing Library
- โข E2E tests with Playwright
- โข API mocking with MSW
๐๏ธ Scalable Architecture
- โข Feature-based organization
- โข Clear separation of concerns
- โข Reusable shared components
- โข Consistent code structure
๐ข Production Ready
- โข Optimized build configuration
- โข Bundle analysis and splitting
- โข Performance monitoring setup
- โข Deployment-ready scripts
๐ฆ Installation and Setup Commands
Install all necessary dependencies:
# Core dependencies
pnpm add react react-dom react-router-dom
pnpm add @tanstack/react-query axios
pnpm add react-i18next i18next i18next-browser-languagedetector
pnpm add clsx tailwind-merge lucide-react
# Development dependencies
pnpm add -D typescript @types/react @types/react-dom
pnpm add -D vite @vitejs/plugin-react-swc
pnpm add -D vitest @vitest/ui jsdom
pnpm add -D @testing-library/react @testing-library/jest-dom
pnpm add -D @testing-library/user-event
pnpm add -D @playwright/test
pnpm add -D msw
pnpm add -D eslint @typescript-eslint/eslint-plugin
pnpm add -D prettier eslint-config-prettier
pnpm add -D plop
pnpm add -D tailwindcss postcss autoprefixer
๐โโ๏ธ Getting Started
# Clone or create your project
git clone <your-repo> my-app
cd my-app
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Run tests
pnpm test
# Generate new component
pnpm generate
# Build for production
pnpm build
๐ What You've Accomplished
Congratulations! You've created a modern, scalable React starter template that includes:
- โ Feature-based architecture for scalable code organization
- โ Modern tooling with Vite, TypeScript, and React 19
- โ Comprehensive testing setup with Vitest, Playwright, and MSW
- โ Code generation for consistent development patterns
- โ Production-ready build and deployment configuration
- โ Developer experience optimizations for maximum productivity
This template provides a solid foundation for building modern React applications while maintaining flexibility for customization based on your specific project needs.