DEV Community

Manoj Swami
Manoj Swami

Posted on

17 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!

💡 One last tip before you go

Tired of spending so much on your side projects? 😒

We have created a membership program that helps cap your costs so you can build and experiment for less. And we currently have early-bird pricing which makes it an even better value! 🐥

Check out DEV++

Top comments (2)

Collapse
 
perisicnikola37 profile image
Nikola Perišić
Comment hidden by post author
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

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay