Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

const config = {
trailingComma: "es5",
plugins: [require.resolve("prettier-plugin-tailwindcss")],
// plugins: [require.resolve("prettier-plugin-tailwindcss")],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify Tailwind class ordering after disabling prettier-plugin-tailwindcss.

Commenting out the Prettier Tailwind plugin aligns with the migration to ESLint-based linting, but this removes automatic class ordering. Ensure that eslint-plugin-better-tailwindcss is properly configured to maintain consistent class ordering across the codebase.


🏁 Script executed:

#!/bin/bash
# Verify ESLint Tailwind configuration is properly set up
echo "Checking ESLint configuration for Tailwind CSS linting..."
cat eslint.config.mjs | grep -A 10 -B 5 "tailwind"

echo -e "\nChecking if better-tailwindcss plugin is installed..."
cat package.json | grep "better-tailwindcss"

Length of output: 3544


Ensure Tailwind CSS class ordering is enforced via ESLint plugin

We’ve confirmed that eslint-plugin-better-tailwindcss v3.7.1 is installed and pulled into your eslint.config.mjs with the recommended-warn and recommended-error rule sets. However, class‐order enforcement isn’t explicitly enabled (the better-tailwindcss/enforce-consistent-class-order rule is commented out), so you should turn it on to retain the same ordering behavior Prettier provided.

• File to update: eslint.config.mjs
• Location: inside the rules object for "better-tailwindcss"

Suggested diff:

   rules: {
-    // "better-tailwindcss/enforce-consistent-class-order": "off",
+    "better-tailwindcss/enforce-consistent-class-order": "error",
     "better-tailwindcss/enforce-consistent-line-wrapping": [
       "warn",
       { printWidth: 100 },
     ],
   },

This guarantees consistent Tailwind class ordering across your TS/TSX files.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// plugins: [require.resolve("prettier-plugin-tailwindcss")],
rules: {
"better-tailwindcss/enforce-consistent-class-order": "error",
"better-tailwindcss/enforce-consistent-line-wrapping": [
"warn",
{ printWidth: 100 },
],
},
🤖 Prompt for AI Agents
In eslint.config.mjs, locate the rules object for "better-tailwindcss" and
explicitly enable the "better-tailwindcss/enforce-consistent-class-order" rule
by setting it to "error" or "warn". This will enforce consistent Tailwind CSS
class ordering as previously handled by Prettier, ensuring uniform styling
across your TS/TSX files.

};

module.exports = config;
8 changes: 7 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"tailwindCSS.lint.cssConflict": "ignore",
"css.lint.unknownAtRules": "ignore",
// enable ESLint to fix tailwind classes on save
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
4 changes: 2 additions & 2 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"config": "",
"css": "src/globals.css",
Comment on lines +7 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Empty tailwind.config path may break the shadcn CLI.

The generator (shadcn-ui@latest init / add) expects a valid Tailwind config file to read theme tokens.
"config": "" will be interpreted as “file not found” and the CLI may bail out or silently fall back to the default theme.

Consider either:

-    "config": "",
+    // point to the actual file if you keep one
+    "config": "tailwind.config.js",

or drop the key entirely if you really want the default theme:

-    "config": "",

🏁 Script executed:

#!/usr/bin/env bash
# Verify whether a Tailwind config file still exists anywhere in the repo.
fd '^tailwind\.config\.(js|cjs|mjs|ts)$' .

Length of output: 44


Ensure a valid Tailwind config or remove the config key

It looks like there isn’t a tailwind.config.js (or .cjs/.mjs/.ts) file in the repo. An empty "config": "" entry in components.json can cause the shadcn CLI to error out or silently fall back to the default theme. To address this, choose one of the following:

  • If you need custom theme tokens, add a Tailwind config file at the project root and point to it:
      // components.json
    - "config": "",
    + "config": "tailwind.config.js",
  • If you don’t require any custom theme and prefer the default, simply remove the key:
    - "config": "",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"config": "",
"css": "src/globals.css",
// components.json
- "config": "",
+ "config": "tailwind.config.js",
"css": "src/globals.css",
🤖 Prompt for AI Agents
In components.json at lines 7 to 8, the "config" key is set to an empty string,
which can cause errors or fallback issues with the shadcn CLI. To fix this,
either add a valid Tailwind config file (e.g., tailwind.config.js) at the
project root and update the "config" value to point to it, or if no custom theme
is needed, remove the "config" key entirely from components.json.

"baseColor": "slate",
"cssVariables": false,
"prefix": ""
Expand Down
130 changes: 118 additions & 12 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
// @ts-check
import { FlatCompat } from "@eslint/eslintrc";
// import { FlatCompat } from "@eslint/eslintrc";
import tseslint from "typescript-eslint";
import playwright from "eslint-plugin-playwright";
import youMightNotNeedAnEffect from "eslint-plugin-react-you-might-not-need-an-effect";
// import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
// import eslintParserTypeScript from "@typescript-eslint/parser";

import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
import eslintParserTypeScript from "@typescript-eslint/parser";
import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
baseDirectory: import.meta.dirname,
baseDirectory: __dirname,
});
// const compat = new FlatCompat({
// baseDirectory: import.meta.dirname,
// });

export default tseslint.config(
{
ignores: [".next", "playwright-output"],
},
{
linterOptions: {
reportUnusedDisableDirectives: true,
},
languageOptions: {
parserOptions: {
projectService: true,
},
},
},
// next config
...compat.extends("next/core-web-vitals"),
{
Expand Down Expand Up @@ -64,6 +88,98 @@ export default tseslint.config(
],
},
},
{
files: ["src/**/*.{ts,tsx,cts,mts}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
},
},
},
{
files: ["src/**/*.{jsx,tsx}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
"better-tailwindcss": eslintPluginBetterTailwindcss,
},
rules: {
// enable all recommended rules to report a warning
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
// enable all recommended rules to report an error
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules,

// or configure rules individually
"better-tailwindcss/enforce-consistent-line-wrapping": [
"warn",
{ printWidth: 100 },
],
},
settings: {
"better-tailwindcss": {
// tailwindcss 3: the path to the tailwind config file (eg: `tailwind.config.js`)
// tailwindConfig: "tailwind.config.js",
// tsconfig: "tsconfig.json",
entryPoint: "src/globals.css",
},
},
},

// for better-tailwindcss plugin
{
files: ["src/**/*.{ts,tsx,cts,mts}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
},
},
},
{
files: ["src/**/*.{jsx,tsx}"],
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
// https://github.com/schoero/eslint-plugin-better-tailwindcss
"better-tailwindcss": eslintPluginBetterTailwindcss,
},
rules: {
// enable all recommended rules to report a warning
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
// enable all recommended rules to report an error
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules,

// or configure rules individually
"better-tailwindcss/enforce-consistent-line-wrapping": [
"warn",
{ printWidth: 100 },
],
// "better-tailwindcss/enforce-consistent-class-order": "off",
},
settings: {
"better-tailwindcss": {
// tailwindcss 4: the path to the entry file of the css based tailwind config (eg: `src/global.css`)
// entryPoint: "src/global.css",
// tailwindcss 3: the path to the tailwind config file (eg: `tailwind.config.js`)
// tailwindConfig: "tailwind.config.js",
entryPoint: "src/globals.css",
},
},
},
Comment on lines +91 to +181
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate better-tailwindcss configuration.

There are two identical configuration blocks for the better-tailwindcss plugin (lines 91-134 and 136-181). This duplication should be removed to avoid confusion and potential conflicts.

  },
-  {
-    files: ["src/**/*.{ts,tsx,cts,mts}"],
-    languageOptions: {
-      parser: eslintParserTypeScript,
-      parserOptions: {
-        project: true,
-      },
-    },
-  },
-  {
-    files: ["src/**/*.{jsx,tsx}"],
-    languageOptions: {
-      parser: eslintParserTypeScript,
-      parserOptions: {
-        project: true,
-        ecmaFeatures: {
-          jsx: true,
-        },
-      },
-    },
-    plugins: {
-      "better-tailwindcss": eslintPluginBetterTailwindcss,
-    },
-    rules: {
-      // enable all recommended rules to report a warning
-      ...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
-      // enable all recommended rules to report an error
-      ...eslintPluginBetterTailwindcss.configs["recommended-error"].rules,
-
-      // or configure rules individually
-      "better-tailwindcss/enforce-consistent-line-wrapping": [
-        "warn",
-        { printWidth: 100 },
-      ],
-    },
-    settings: {
-      "better-tailwindcss": {
-        // tailwindcss 3: the path to the tailwind config file (eg: `tailwind.config.js`)
-        // tailwindConfig: "tailwind.config.js",
-        // tsconfig: "tsconfig.json",
-        entryPoint: "src/globals.css",
-      },
-    },
-  },
-
-  // for better-tailwindcss plugin
   {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
files: ["src/**/*.{ts,tsx,cts,mts}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
},
},
},
{
files: ["src/**/*.{jsx,tsx}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
"better-tailwindcss": eslintPluginBetterTailwindcss,
},
rules: {
// enable all recommended rules to report a warning
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
// enable all recommended rules to report an error
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules,
// or configure rules individually
"better-tailwindcss/enforce-consistent-line-wrapping": [
"warn",
{ printWidth: 100 },
],
},
settings: {
"better-tailwindcss": {
// tailwindcss 3: the path to the tailwind config file (eg: `tailwind.config.js`)
// tailwindConfig: "tailwind.config.js",
// tsconfig: "tsconfig.json",
entryPoint: "src/globals.css",
},
},
},
// for better-tailwindcss plugin
{
files: ["src/**/*.{ts,tsx,cts,mts}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
},
},
},
{
files: ["src/**/*.{jsx,tsx}"],
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
// https://github.com/schoero/eslint-plugin-better-tailwindcss
"better-tailwindcss": eslintPluginBetterTailwindcss,
},
rules: {
// enable all recommended rules to report a warning
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
// enable all recommended rules to report an error
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules,
// or configure rules individually
"better-tailwindcss/enforce-consistent-line-wrapping": [
"warn",
{ printWidth: 100 },
],
// "better-tailwindcss/enforce-consistent-class-order": "off",
},
settings: {
"better-tailwindcss": {
// tailwindcss 4: the path to the entry file of the css based tailwind config (eg: `src/global.css`)
// entryPoint: "src/global.css",
// tailwindcss 3: the path to the tailwind config file (eg: `tailwind.config.js`)
// tailwindConfig: "tailwind.config.js",
entryPoint: "src/globals.css",
},
},
},
{
files: ["src/**/*.{ts,tsx,cts,mts}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
},
},
},
{
files: ["src/**/*.{jsx,tsx}"],
languageOptions: {
parser: eslintParserTypeScript,
parserOptions: {
project: true,
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
"better-tailwindcss": eslintPluginBetterTailwindcss,
},
rules: {
// enable all recommended rules to report a warning
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
// enable all recommended rules to report an error
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules,
// or configure rules individually
"better-tailwindcss/enforce-consistent-line-wrapping": [
"warn",
{ printWidth: 100 },
],
},
settings: {
"better-tailwindcss": {
entryPoint: "src/globals.css",
},
},
},
🤖 Prompt for AI Agents
In eslint.config.mjs between lines 91 and 181, there are two duplicate
configuration blocks for the better-tailwindcss plugin with identical settings.
Remove one of these duplicate blocks entirely to avoid confusion and potential
conflicts, ensuring only a single configuration block for better-tailwindcss
remains.


{
rules: {
"no-console": ["warn", { allow: ["error"] }],
Expand All @@ -87,15 +203,5 @@ export default tseslint.config(
// Customize Playwright rules
// ...
},
},
{
linterOptions: {
reportUnusedDisableDirectives: true,
},
languageOptions: {
parserOptions: {
projectService: true,
},
},
}
);
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"sonner": "1.7.4",
"tailwind-merge": "2.6.0",
"tailwindcss-animate": "1.0.7",
"tw-animate-css": "1.3.5",
"ua-parser-js": "2.0.3",
"use-debounce": "10.0.4",
"zod": "3.24.4"
Expand All @@ -89,27 +90,30 @@
"@next/eslint-plugin-next": "15.2.3",
"@playwright/test": "1.52.0",
"@stagewise/toolbar-next": "0.1.2",
"@tailwindcss/postcss": "4.1.11",
"@types/file-saver": "2.0.7",
"@types/node": "22.8.1",
"@types/pdf-parse": "1.1.5",
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
"@typescript-eslint/parser": "8.38.0",
"@typescript/native-preview": "7.0.0-dev.20250525.1",
Comment on lines +93 to 100
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Version / package mismatch in TypeScript-ESLint tooling

@typescript-eslint/parser is declared at 8.38.0 while typescript-eslint meta-package is 8.32.0 and @typescript-eslint/eslint-plugin is missing entirely.
Mixing minor versions regularly breaks linting.

Action items:

  1. Pin all @typescript-eslint/* packages (parser + eslint-plugin) to the same version, e.g. 8.38.0.
  2. Remove the stray typescript-eslint entry – that package is unrelated.
  3. Add "@typescript-eslint/eslint-plugin": "8.38.0" if ESLint config expects it.

Optionally, remove prettier-plugin-tailwindcss if you’ve disabled it in Prettier to avoid unnecessary install time.

Also applies to: 116-119

🤖 Prompt for AI Agents
In package.json around lines 93 to 100 and 116 to 119, the @typescript-eslint
packages have version mismatches and missing entries. Ensure all
@typescript-eslint packages, including @typescript-eslint/parser and
@typescript-eslint/eslint-plugin, are pinned to the same version, such as
8.38.0. Remove the unrelated typescript-eslint package entry. Add
@typescript-eslint/eslint-plugin at version 8.38.0 if it is expected by the
ESLint configuration. Optionally, remove prettier-plugin-tailwindcss if it is
disabled in Prettier to reduce install time.

"autoprefixer": "10.4.21",
"eslint": "9.26.0",
"eslint-config-next": "15.2.3",
"eslint-config-next": "15.4.3",
"eslint-plugin-better-tailwindcss": "3.7.1",
"eslint-plugin-playwright": "2.2.0",
"eslint-plugin-react-you-might-not-need-an-effect": "0.0.39",
"husky": "9.1.7",
"knip": "5.55.1",
"knip": "5.62.0",
"lint-staged": "15.5.0",
"postcss": "^8",
"prettier": "3.5.3",
"prettier-plugin-tailwindcss": "0.6.11",
"prettier-plugin-tailwindcss": "0.6.14",
"react-email": "4.0.4",
"react-scan": "0.3.4",
"schema-dts": "1.1.5",
"tailwindcss": "3.4.14",
"tailwindcss": "4.1.11",
"typescript": "5.8.3",
"typescript-eslint": "8.32.0"
}
Expand Down
Loading
Loading