DEV Community

Manoj Swami
Manoj Swami

Posted on

21 2 2 2 2

Creating a Modern React App: Vite + TypeScript + ESLint + Tailwind + shadcn/ui and Zustand

In this guide, we'll walk through the process of setting up a React application with the latest features and popular libraries. We'll be using React 19, React Router, Tailwind CSS, shadcn/ui, ESLint with Prettier, and Zustand for state management. By the end of this tutorial, you'll have a fully configured project ready for development.

Setting Up the Project

Let's start by creating a new React project using Vite, which provides a faster and leaner development experience.

npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
Enter fullscreen mode Exit fullscreen mode

This command creates a new React project with TypeScript support. Now, let's install the necessary dependencies:

npm install react@19 react-dom@19 react-router-dom@6 zustand@4 @types/react@19 @types/react-dom@19
npm install -D tailwindcss postcss autoprefixer eslint prettier eslint-config-prettier eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser
Enter fullscreen mode Exit fullscreen mode

Configuring Tailwind CSS

To set up Tailwind CSS, run the following command:

npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

This creates a tailwind.config.js file. Update it with the following content:

module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode

Now, add the Tailwind directives to your src/index.css file:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Setting Up ESLint and Prettier

Create .eslintrc.js and .prettierrc files in the root of your project:

touch .eslintrc.js .prettierrc
Enter fullscreen mode Exit fullscreen mode

Add the following content to .eslintrc.js:

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: ['react', '@typescript-eslint'],
  rules: {
    'react/react-in-jsx-scope': 'off',
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

And to .prettierrc:

{
  "semi": true,
  "tabWidth": 2,
  "printWidth": 100,
  "singleQuote": true,
  "trailingComma": "all",
  "jsxSingleQuote": true,
  "bracketSpacing": true
}
Enter fullscreen mode Exit fullscreen mode

Installing and Configuring shadcn/ui

To use shadcn/ui, we need to set it up in our project:

npx shadcn-ui@latest init
Enter fullscreen mode Exit fullscreen mode

Follow the prompts to configure shadcn/ui for your project. This will set up the necessary files and configurations.

Setting Up Zustand

Create a new file src/store.ts for our Zustand store:

import create from 'zustand';

interface AppState {
  count: number;
  increment: () => void;
  decrement: () => void;
}

export const useAppStore = create<AppState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));
Enter fullscreen mode Exit fullscreen mode

Updating package.json Scripts

Add the following scripts to your package.json:

"scripts": {
  "dev": "vite",
  "build": "tsc && vite build",
  "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
  "preview": "vite preview",
  "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
  "lint:fix": "eslint src --ext ts,tsx --fix"
}
Enter fullscreen mode Exit fullscreen mode

Creating a Sample App

Let's create a simple app to demonstrate the usage of our setup. Update src/App.tsx:

import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import { Button } from './components/ui/button';
import { useAppStore } from './store';

function Home() {
  const { count, increment, decrement } = useAppStore();

  return (
    <div className='p-4'>
      <h1 className='text-2xl font-bold mb-4'>Home</h1>
      <p className='mb-4'>Count: {count}</p>
      <Button onClick={increment} className='mr-2'>Increment</Button>
      <Button onClick={decrement}>Decrement</Button>
    </div>
  );
}

function About() {
  return <div className='p-4'>
    <h1 className='text-2xl font-bold'>About</h1>
  </div>;
}

function App() {
  return (
    <Router>
      <div className='p-4'>
        <nav className='mb-4'>
          <Link to='/' className='mr-4'>Home</Link>
          <Link to='/about'>About</Link>
        </nav>
        <Routes>
          <Route path='/' element={<Home />} />
          <Route path='/about' element={<About />} />
        </Routes>
      </div>
    </Router>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Running the Application

Now you can run your application using the following command:

npm run dev
Enter fullscreen mode Exit fullscreen mode

This will start the development server, and you can view your app at http://localhost:5173.

Conclusion

You now have a modern React application set up with React 19, React Router, Tailwind CSS, shadcn/ui, ESLint with Prettier, and Zustand. This setup provides a solid foundation for building scalable and maintainable React applications.

Happy coding!

Top comments (4)

Collapse
 
perisicnikola37 profile image
Nikola Perišić
Comment hidden by post author
Collapse
 
vlad_potylitsyn_0ec56b9e4 profile image
Vlad Potylitsyn

the guide was getting old, namely tailwindcss 4. as I know now, the npx tailwindcss init -p command does not work here is the documentation tailwindcss.com/docs/installation/...

Collapse
 
mer_salihdeniz_4ebb9c6f profile image
Ömer Salih Deniz

Hello, can you recommend an up-to-date guide?

Collapse
 
joanny_bernardeau_ac67521 profile image
Joanny Bernardeau
Comment hidden by post author

Some comments have been hidden by the post's author - find out more

This post blew up on DEV in 2020:

js visualized

🚀⚙️ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! 🥳

Happy coding!