DEV Community

Edward-Fedoruk
Edward-Fedoruk

Posted on

How to set up modern React App (SPA)

Image description

Defining Our Core Frontend Stack

Here's the core stack we'll be using:

  • React - as the view library
  • Zustand - for global state management
  • Vite - as the bundler
  • Tailwind CSS - for styling

Setting Up the Frontend App

Let's get started with the frontend setup. Begin by creating the project folder and initializing a Vite project:

cd ./project
npm create vite@latest
 Project name:  ./
 Select a framework:  React
 Select a variant:  TypeScript + SWC
npm install
Enter fullscreen mode Exit fullscreen mode

Cool! We have App with the following structure (or similar one if in the future templae changes)

project-root/

├── node_modules/

├── public/

├── src/
   ├── assets/
      ├── App.css
      ├── App.tsx
      ├── index.css
      ├── main.tsx
      └── vite-env.d.ts

├── .gitignore

├── README.md

├── eslint.config.js

├── index.html

├── package-lock.json

├── package.json

├── tsconfig.app.json

├── tsconfig.json

├── tsconfig.node.json

├── vite.config.ts
Enter fullscreen mode Exit fullscreen mode

Let’s add port config so our app runs every time with the same

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";

// https://vitejs.dev/config/
export default defineConfig({
    server: {
        port: 3000,
    },
    plugins: [react()],
});
Enter fullscreen mode Exit fullscreen mode

Tweaking ESLint

Firstly, we need to tweak ESLint. The default template sets recommended settings, which do not enforce a specific code style strictly. So let's improve this by updating the eslint.config.js file with:

import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
    { ignores: ["dist"] },
    {
        extends: [js.configs.recommended, ...tseslint.configs.recommended],
        files: ["**/*.{ts,tsx}"],
        languageOptions: {
            ecmaVersion: 2020,
            globals: globals.browser,
        },
        plugins: {
            "react-hooks": reactHooks,
            "react-refresh": reactRefresh,
        },
        rules: {
            ...reactHooks.configs.recommended.rules,
            "react-refresh/only-export-components": [
                "warn",
                { allowConstantExport: true },
            ],
            "@typescript-eslint/no-explicit-any": "error"
        },
    }
);
Enter fullscreen mode Exit fullscreen mode

Adding Prettier

To ensure a consistent code style, let's add prettier. Create a .prettierrc file with the following contents:

{
    "tabWidth": 4,
    "useTabs": false,
    "jsxSingleQuote": false,
    "bracketSpacing": true,
    "jsxBracketSameLine": false
}
Enter fullscreen mode Exit fullscreen mode

Now after you run the project npm run dev you should see starting screen like this one

Image description

Configuring Tailwind CSS

Here comes tailwind configurations. Firstly Install tailwind:

npm install -D tailwindcss postcss autoprefixer
npm install @heroicons/react
npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

You should see a couple new configurational files in the root not

tailwind.config.js
postcss.config.js
Enter fullscreen mode Exit fullscreen mode

to the index.html we will add link to tailwind font:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Money manager</title>

        <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
    </head>

    <body>
        <div id="root"></div>
        <script type="module" src="/src/main.tsx"></script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Secondly, add configurations inside tailwind.config.js so that the library knows where is our code place

const defaultTheme = require('tailwindcss/defaultTheme')

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter var', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode

Thirdly, import tailwind library in index.css to have styles availiable in our bundle

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

Finally we are going to test our changes. Inside of the App.tsx write a hello world with tailwind classes

function App() {
    return (
        <>
            <h1 className="text-3xl font-bold underline">Hello world!</h1>
        </>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

If you see screen like this after reloading the project you’ve done everything right!

Image description

Clean Up

Delete any predefined template files and folders you don't need. Your final folder structure should look like this:

node_modules
public
src
  ├─ App.tsx
  ├─ index.css
  ├─ main.tsx
  ├─ vite-env.d.ts
.gitignore
.prettierignore
.prettierrc
README.md
eslint.config.js
index.html
package-lock.json
package.json
postcss config.js
tailwind.config.js
tsconfig.app.json
tsconfig.json
tsconfig.node.json
vite.config.ts
Enter fullscreen mode Exit fullscreen mode

In case you face some issues or bugs you can copy code for this first lessong from this link:

This concludes the setup for our frontend app.
Happy coding!

Top comments (0)