Create a simple calculator using Jotai, Tailwind CSS, and Vitest (Part 1)

In the first part, I will help you set up a new application inside a monorepo. Link to the project repository: Github

Configuration Eslint

I will create a new application in my monorepo, I will go to apps and use these commands to create a vite application.

pnpx create-vite@latest jotai-calculator 
cd jotai-calculator
pnpm install

image.png

eslint-config-custom is used for next projects. So, we will set up a new eslint configuration for vite projects. I will change from eslint-config-custom to eslint-config-next. It will be needed to change the name inside the package.json. Then, you may uninstall this package at the root directory and reinstall it to update pnpm-lock.yaml. Remember to use the flag -w or --workspace-root to adding at the workspace root. Otherwise, use the flag --filter to point to the workspace. This flag also helps to run a specific workspace rather than all of them.

pnpm remove eslint-config-custom -w
pnpm add eslint-config-next -w
// packages/eslint-config-next/package.json
{
  "name": "eslint-config-next",
  "version": "0.0.0",
  "main": "index.js",
  "license": "MIT",
  ...
}

I will create a new folder named eslint-config-vite and create a new .eslintrc.cjs. It will help to lint the vite applications correctly. It is necessary to install this package at the root and application directory.

// packages/eslint-config-vite/package.json
{
  "name": "eslint-config-vite",
  "version": "0.0.0",
  "main": "index.js",
  "license": "ISC",
  "dependencies": {
    "@typescript-eslint/eslint-plugin": "^5.43.0",
    "@typescript-eslint/parser": "^5.43.0",
    "eslint": "^8.27.0",
    "eslint-plugin-react": "^7.31.10"
  },
  "publishConfig": {
    "access": "public"
  }
}
// packages/eslint-config-vite/index.js
module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
  ],
  overrides: [],
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
  },
  plugins: ["react", "@typescript-eslint"],
  rules: {
    "react/react-in-jsx-scope": "off"
  },
};
// apps/jotai-calculator/.eslintrc.cjs
module.exports = {
  root: true,
  extends: ["vite"]
}
pnpm add eslint-config-vite -w
pnpm add eslint-config-vite --filter jotai-calculator --workspace

Installing packages

After finishing the configuration with eslint, I will add tailwindcss, jotai, and vitest to our application directory. We also may add a shared ui package to our application. It will help us to get the shared components between applications.

pnpm add -D tailwindcss postcss autoprefixer vitest --filter jotai-calculator
pnpm add jotai --filter jotai-calculator
pnpm add ui --filter jotai-calculator --workspace
// apps/jotai-calculator/package.json
{
  "name": "jotai-calculator",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "jotai": "^1.10.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "ui": "workspace:^0.0.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.24",
    "@types/react-dom": "^18.0.8",
    "@vitejs/plugin-react": "^2.2.0",
    "autoprefixer": "^10.4.13",
    "eslint-config-vite": "workspace:^0.0.0",
    "postcss": "^8.4.19",
    "tailwindcss": "^3.2.4",
    "typescript": "^4.6.4",
    "vite": "^3.2.3",
    "vitest": "^0.25.2"
  }
}

Configuration Tailwind CSS

The idea is to create a global configuration such as eslint so that we can use it in any application that uses tailwind css. I will create a new directory named tailwind-config inside packages and set it up just like ts-config. Then I will install this package to jotai-calculator.

// packages/tailwind-config/postcss.config.cjs
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};
// packages/tailwind-config/tailwind.config.cjs
module.exports = {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};
// packages/tailwind-config/package.json
{
  "name": "tailwind-config",
  "version": "0.0.0",
  "private": true,
  "files": [
    "tailwind.config.cjs",
    "postcss.config.cjs"
  ]
}
pnpm add -D tailwind-config --filter jotai-calculator --workspace

Let's config to apply tailwind css inside our application and run to try out if it displays correctly.

// apps/jotai-calculator/postcss.config.cjs
module.exports = require("tailwind-config/postcss.config.cjs");

/*
Or you can config like this without creating tailwind.config.css
const config = require('tailwind-config/tailwind.config.cjs')

module.exports = {
    plugins:{
        tailwindcss: { config },
        autoprefixer: {}
    }
}
*/
// apps/jotai-calculator/src/index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
// apps/jotai-calculator/src/App.tsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="flex flex-col justify-center">
      <div className="flex justify-center">
        <a href="https://vitejs.dev" target="_blank">
          <img src="/vite.svg" className="logo" alt="Vite logo" />
        </a>
        <a href="https://reactjs.org" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1 className="text-3xl text-blue-600 underline">Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </div>
  );
}

export default App;

Screenshot 2022-11-21 at 13-36-20 Vite React TS.png

References

[1] blog.nrwl.io/setup-a-monorepo-with-pnpm-wor..

[2] shubhamverma.me/blog/setup-tailwind-css-wit..