A modern React app template with Vite, TypeScript, ESLint, Prettier, Tailwind CSS, Zustand, and optional shadcn/ui.
Inspired by this guide.
See React docs.
With TypeScript:
npm create vite@latest my-app -- --template react-tsWithout TypeScript:
npm create vite@latest my-app -- --template reactNote: Make sure ESLint does not do Prettier's work.
See ESLint docs.
npm init @eslint/config@latestSee Prettier docs.
npm install --save-dev eslint-config-prettier eslint-plugin-prettiereslint-config-prettierdisables ESLint rules that might conflict with Prettier.eslint-plugin-prettierruns Prettier as an ESLint rule.
Edit your eslint.config.js to include Prettier:
import js from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
import pluginReact from 'eslint-plugin-react';
import pluginPrettier from 'eslint-plugin-prettier';
import prettierConfig from 'eslint-config-prettier';
import { defineConfig } from 'eslint/config';
export default defineConfig([
js.configs.recommended,
tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
{ ignores: ['node_modules', 'dist', 'build', 'coverage'] },
{
...pluginReact.configs.flat['jsx-runtime'],
files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
settings: { react: { version: 'detect' } },
languageOptions: { globals: { ...globals.browser } },
},
{
plugins: { prettier: pluginPrettier },
rules: { 'prettier/prettier': 'warn' },
},
prettierConfig,
]);You already have a .prettierrc file. Example:
{
"singleQuote": true,
"trailingComma": "all"
}You already have a .prettierignore file. Make sure it lists files/folders you want Prettier to skip.
Your package.json already has:
"format": "prettier --write ."- Run
npm run lintto check both ESLint and Prettier issues. - Run
npm run formatto auto-format with Prettier.
npm install tailwindcss @tailwindcss/viteSee Tailwind + Vite docs for the rest of the setup.
See shadcn/ui Vite installation.
npx shadcn@latest initnpm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event jest ts-jest @types/jestCreate a jest.config.ts file:
import type { Config } from 'jest';
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
moduleNameMapper: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
};
export default config;Create a jest.setup.ts file:
import '@testing-library/jest-dom';In your package.json:
"scripts": {
// ...existing scripts...
"test": "jest"
}Create src/App.test.tsx:
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders Counter heading', () => {
render(<App />);
expect(screen.getByText(/Counter/i)).toBeInTheDocument();
});npm test