Photo by Mathew Schwartz on Unsplash
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
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;