Add Tooling and Deployment

In this section, you will add Tailwind CSS for styling, configure Prettier and ESLint for code quality, and set up automated deployment to GitHub Pages.

The process is similar to how we set up these tools in the ToDo App, but for completeness, we will go through the steps again.

Adding Tailwind CSS

Install the packages:

pnpm install tailwindcss @tailwindcss/vite

Update vite.config.ts to include the plugin:

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

// https://vite.dev/config/
export default defineConfig({
  plugins: [react(), tailwindcss()],
});

Notice the react plugin is already included. This is how vite scaffolds React projects. If we were to use a different framework, it would be a different plugin.

Add the following import to src/index.css:

@import "tailwindcss";

Update src/App.tsx to verify Tailwind is working:

function App() {
  return (
    <div className="flex min-h-screen items-center justify-center text-3xl">
      Dice Roller
    </div>
  );
}

export default App;

Check the browser. The text should be centered on screen.

Screenshot of the Dice Roller

Setting Up Prettier

Install Prettier as a dev dependency:

pnpm install --save-dev --save-exact prettier

Create .prettierrc.json:

{
  "semi": true,
  "trailingComma": "all",
  "singleQuote": false,
  "printWidth": 80,
  "tabWidth": 2,
  "endOfLine": "auto"
}

Create .prettierignore:

dist

Add this script to package.json:

"format": "prettier --write \"**/*.{js,ts,jsx,tsx}\" --config \".prettierrc.json\"",

The format script runs Prettier on all JavaScript and TypeScript files in the project, using the configuration specified in .prettierrc.json. It ignores files in the dist (and node_modules) directory.

Integrating ESLint and Prettier

Vite scaffolds React projects with ESLint support. ESLint finds problems in your code and can fix some of them. In general, “linting” means analyzing code for potential errors, and “formatting” means enforcing a consistent style. You would notice a lint script in package.json:

"lint": "eslint .",

This runs ESLint on all files in the project. Prettier only handles formatting, but ESLint can be configured to enforce both code quality rules and style rules. So the two tools overlap, and that overlap can produce conflicts. To make them work together, we need to install some additional packages and update our ESLint configuration.

Install the packages to make ESLint and Prettier work together:

pnpm install --save-dev eslint-plugin-prettier eslint-config-prettier

Update eslint.config.js:

  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";
  import { defineConfig, globalIgnores } from "eslint/config";
+ import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";

  export default defineConfig([
    globalIgnores(["dist"]),
    {
      files: ["**/*.{ts,tsx}"],
      extends: [
        js.configs.recommended,
        tseslint.configs.recommended,
        reactHooks.configs.flat.recommended,
        reactRefresh.configs.vite,
      ],
      languageOptions: {
        ecmaVersion: 2020,
        globals: globals.browser,
      },
    },
+   eslintPluginPrettierRecommended,
  ]);

Format and lint your code:

pnpm format
pnpm lint

Deploying to GitHub Pages

Update vite.config.ts to include the base property:

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

// https://vite.dev/config/
export default defineConfig({
  base: "/REPO_NAME/",  // TODO: Replace REPO_NAME with the name of your repository
  plugins: [react(), tailwindcss()],
});

Create .github/workflows/deploy.yml:

name: Deploy Vite app to GitHub Pages

on:
  push:
    branches:
      - master

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install pnpm
        run: npm install -g pnpm

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: pnpm

      - name: Configure GitHub Pages
        uses: actions/configure-pages@v5

      - name: Install dependencies
        run: pnpm install

      - name: Build with Vite
        run: pnpm run build

      - name: Upload GitHub Pages artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy GitHub Pages site
        id: deployment
        uses: actions/deploy-pages@v4

Before pushing, update your GitHub repository settings to use “GitHub Actions” for deploying to GitHub Pages. Then push. Every push to master automatically deploys the app.

Checkpoint: Commit your progress.

git add .
git commit -m "dice-02: Add Tailwind, Prettier, ESLint, and GitHub Pages deployment"
git push