Skip to content

A production-ready template for React + Vite + TypeScript. Includes Tailwind CSS v4, Vitest for unit testing, ESLint, and Prettier pre-configured.

Notifications You must be signed in to change notification settings

architg564/production-react-template

Repository files navigation

🚀 Production React Template

A robust, enterprise-ready starter template for modern React development. Pre-configured with Vite, TypeScript, Tailwind CSS, Vitest, ESLint, and Prettier.

🛠️ Features

  • ⚡ Framework: Vite + React (Fast HMR & Bundling)
  • 🟦 Language: TypeScript (Strict Mode + Solution Style Configuration)
  • 🎨 Styling: Tailwind CSS v4 (Zero-runtime styling)
  • 🧪 Testing: Vitest + React Testing Library
  • 📏 Linting: ESLint (Flat Config) + Prettier
  • 🤖 CI/CD Ready: Dedicated scripts for validation and testing

🚀 Quick Start

Use degit to scaffold a new project using this template without downloading the git history.

1. Create a new project

Run the following command, replacing my-app with your desired project name:

npx degit architg564/production-react-template my-app
cd my-app
pnpm install
pnpm run dev

React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.

Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...

      // Remove tseslint.configs.recommended and replace with this
      tseslint.configs.recommendedTypeChecked,
      // Alternatively, use this for stricter rules
      tseslint.configs.strictTypeChecked,
      // Optionally, add this for stylistic rules
      tseslint.configs.stylisticTypeChecked,

      // Other configs...
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
]);

You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:

// eslint.config.js
import reactX from 'eslint-plugin-react-x';
import reactDom from 'eslint-plugin-react-dom';

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
]);

🛠️ Prettier Setup

This project uses Prettier for code formatting to ensure consistent code style.

1. Installation

Install Prettier as a dev dependency using pnpm:

pnpm add --save-dev --save-exact prettier

2. Configuration Files

Create a .prettierrc file in the root directory with the following standard rules:

{
  'trailingComma': 'es5',
  'tabWidth': 2,
  'semi': true,
  'singleQuote': true,
  'bracketSameLine': false,
  'printWidth': 100,
  'singleAttributePerLine': false,
  'endOfLine': 'lf',
}

Create a .prettierignore file to prevent formatting of build outputs or system files:

dist
node_modules

3. Scripts

Add these scripts to your package.json to format all files or check for issues in CI pipelines:

"scripts": {
    "format:fix": "prettier --write .",
    "format:check": "prettier --check ."
}

4. usage

To format your entire codebase, run:

    pnpm run format:fix

To check for formatting issues without making changes, run:

    pnpm run format:check

5. Tailwind Class Sorting (Highly Recommended)

To automatically sort Tailwind CSS classes, install the Prettier plugin for Tailwind CSS:

Command:

pnpm add -D prettier-plugin-tailwindcss

Update .prettierrc:

{ ? // existing rules...
    "plugins"
  : ['prettier-plugin-tailwindcss'], 'semi': true }

6. VS Code "Format on Save" (optional)

To enable automatic formatting on save in VS Code, add the following settings to your settings.json:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

🎨 Tailwind CSS v4 Setup

This project uses Tailwind CSS v4 with the native Vite plugin for high-performance builds.

1. Dependencies

Install the main package and the Vite integration:

pnpm add tailwindcss @tailwindcss/vite --save-dev

2. Vite Configuration

Enable the Tailwind plugin in vite.config.ts:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
  plugins: [react(), tailwindcss()],
});

3. CSS Entry Point

In your main CSS file (e.g., src/index.css), replace the old directives with the single import:

@import 'tailwindcss';

4. Customizing the Theme (Optional)

Tailwind v4 uses CSS variables for configuration instead of a JavaScript file. You can extend the theme directly in your CSS:

@import "tailwindcss";

@theme {
  --color-brand: #3b82f6;
  --font-display: "Satoshi", "sans-serif";
}

5. Prettier Integration

Install the official plugin (v0.6+ is required for v4 support) to sort classes automatically:

pnpm add -D prettier-plugin-tailwindcss

Add it to your .prettierrc:

{
  "plugins": ["prettier-plugin-tailwindcss"]
}

🛡️ Linting & Code Quality

This project uses ESLint with the modern Flat Config system to strictly enforce code quality, best practices, and TypeScript safety.

1. Dependencies

The setup relies on the following packages for React, TypeScript, and standard JavaScript linting:

pnpm add -D eslint @eslint/js globals typescript-eslint eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-refresh

2. Configuration (eslint.config.js)

The configuration is modular and "Type-Checked," meaning it understands your TypeScript types to catch subtle bugs (like floating promises).

Key Features:

  • Strict TypeScript: Uses recommendedTypeChecked to prevent unsafe any usage and unchecked errors.
  • React Best Practices: Includes eslint-plugin-react (JSX rules), react-hooks (Rules of Hooks), and react-refresh.
  • Prettier Compatible: Formatting rules are explicitly removed to prevent conflicts with Prettier.
  • Performance: Uses projectService for faster type-checking in the editor.

3. Scripts

The following scripts are included in package.json for manual execution or CI pipelines:

"scripts": {
  "lint": "eslint .",
  "lint:fix": "eslint . --fix",
  "type-check": "tsc --noEmit",
  "validate": "pnpm lint:fix && pnpm format:fix && pnpm type-check"
}

4. VS Code Setup

To ensure ESLint highlights errors directly in your editor, install the VS Code ESLint Extension and add this to your .vscode/settings.json:

{
  "eslint.experimental.useFlatConfig": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"]
}

5. Usage

  • Fix all auto-fixable issues: pnpm lint:fix
  • Run full project validation (Lint + Format + Types): pnpm validate

Unit Testing Documentation

This document outlines the configuration, installation, and usage of the testing stack for this project.

1. Installation

To set up the testing environment, install the following dependencies:

pnpm add -D vitest jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom @testing-library/user-event @vitest/ui @vitest/coverage-v8

2. Configuration Files Setup

Ensure your project files match the following configurations to enable the testing pipeline.

File: vite.config.ts

This is the main configuration file. Note that we import defineConfig from vitest/config to support the test property.

import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; import { defineConfig } from 'vitest/config';

export default defineConfig({ plugins: [react(), tailwindcss()], resolve: { alias: { '@': '/src', }, }, test: { globals: true, environment: 'jsdom', setupFiles: './vitest.setup.ts', css: true, coverage: { provider: 'v8', reporter: ['text', 'json', 'html', 'lcov'], exclude: ['node_modules/', 'dist/', '.vite/', '/.config.', '/*.d.ts'], }, }, });

File: vitest.setup.ts

Create this file in your project root. It handles global mocks and DOM cleanup.

import '@testing-library/jest-dom'; import { cleanup } from '@testing-library/react'; import { afterEach, vi } from 'vitest';

// Automatically cleanup DOM after each test afterEach(() => { cleanup(); });

// Mock matchMedia for JSDOM Object.defineProperty(window, 'matchMedia', { writable: true, value: vi.fn().mockImplementation((query) => ({ matches: false, media: query, onchange: null, addListener: vi.fn(), removeListener: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), dispatchEvent: vi.fn(), })), });

File: tsconfig.json

This file acts as a reference manager for your solution.

{ "files": [], "references": [ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ] }

File: tsconfig.app.json

This configures the source code and includes testing types.

{ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, "strict": true, "noEmit": true, "jsx": "react-jsx", "baseUrl": ".", "paths": { "@/": ["src/"] }, "types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"] }, "include": ["src", "vitest.setup.ts"] }

File: tsconfig.node.json

This configures build tools and configuration files.

{ "compilerOptions": { "composite": true, "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2023", "lib": ["ES2023"], "module": "ESNext", "skipLibCheck": true, "moduleResolution": "bundler", "allowSyntheticDefaultImports": true, "allowImportingTsExtensions": true, "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noEmit": true, "types": ["vitest", "node"] }, "include": ["vite.config.ts", "eslint.config.js"] }

3. Scripts

Add these scripts to your package.json to run tests:

"scripts": { "test": "vitest", "test:run": "vitest run", "test:ui": "vitest --ui", "test:coverage": "vitest run --coverage" }

4. Example Test File

Create src/components/Example.test.tsx to verify the setup:

import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { describe, it, expect } from 'vitest';

describe('Example Test', () => { it('should render a button and click it', async () => { const user = userEvent.setup(); render(Click Me);

const button = screen.getByRole('button', { name: /click me/i });
expect(button).toBeInTheDocument();

await user.click(button);

}); });

5. Troubleshooting

  • If ESLint complains about screen or expect, ensure parserOptions.project in eslint.config.js includes './tsconfig.app.json'.
  • If tests fail with "No test files found", ensure you have created at least one file ending in .test.tsx.
  • Always use pnpm test:run for CI/CD pipelines to avoid hanging processes.

🛡️ Error Handling (Error Boundaries)

This template includes a pre-configured Error Boundary to prevent the "White Screen of Death" when the application crashes.

1. Overview

In React, if a JavaScript error occurs inside a component, it unmounts the entire component tree. This leaves the user with a blank white screen.

We use react-error-boundary to catch these errors and display a friendly "Fallback UI" instead, allowing the user to recover without refreshing the page.

2. Installation

The dependency is already installed in this template:

pnpm add react-error-boundary

3. Configuration

Global Protection

The entire application is wrapped at the entry point to ensure any crash is caught.

  • File Location: src/main.tsx
  • Implementation: The App component is wrapped with <ErrorBoundary> before being rendered to the DOM.

4. Customizing the Fallback UI

The fallback component determines what the user sees when an error occurs. You should customize this component to match your application's branding.

  • File Location: src/components/ErrorFallback.tsx
  • Props: It receives error (the error message) and resetErrorBoundary (function to retry) as props.

About

A production-ready template for React + Vite + TypeScript. Includes Tailwind CSS v4, Vitest for unit testing, ESLint, and Prettier pre-configured.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published