ui icon indicating copy to clipboard operation
ui copied to clipboard

Project initialization puts folder in incorrect place

Open ryanbrwr opened this issue 2 years ago • 32 comments

Hi there, just initialized a project, and for some reason, my whole tailwind custom theme breaks when using shadcn UI. Here is my configuration file

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": false,
  "tailwind": {
    "config": "tailwind.config.js",
    "css": "src/styles/globals.css",
    "baseColor": "gray",
    "cssVariables": false
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

Also project structure,

--| components.json
--| tailwind.config.js
--| src
----| styles
------| globals.css

ryanbrwr avatar Jul 01 '23 03:07 ryanbrwr

Hi @ryanbrwr, what do you mean with “breaks”? Can you provide a better explanation of your problem?

dan5py avatar Jul 01 '23 08:07 dan5py

Apologies for the weak explanation, was late at night haha. Basically, I have a monorepo with about 8 packages, each with its own package.json. While inside one of these, I ran the initialization script, and instead of creating the ui, and utils folders inside of the package, it created an "@/" folder inside of the base level of my monorepo. This made me believe that I had some sort of path wrong in the aliases.

Also, as soon as I did this, my tailwind theme stopped applying my custom colors to my next.js app. And as soon as I removed the files associated with shadcn/ui, my theme starts applying again.

Hopefully, this is a little better explanation. Thanks again for making this package, can't wait to use it

ryanbrwr avatar Jul 01 '23 14:07 ryanbrwr

Did you add the paths in the tsconfig.json?

dan5py avatar Jul 01 '23 14:07 dan5py

Must have missed that step, would you be able to send a link to an explanation of that part if one exists?

ryanbrwr avatar Jul 01 '23 14:07 ryanbrwr

Sure, this is from the manual installation guide. https://ui.shadcn.com/docs/installation/manual#configure-path-aliases

dan5py avatar Jul 01 '23 14:07 dan5py

I ran into this issue too where the CLI tool creates an @/ directory... The tsconfig.json looks like

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/assets/*": ["./assets/*"],
      "@/components/*": ["./components/*"],
      "@/lib/*": ["./lib/*"],
      "@/styles/*": ["./styles/*"]
    },
    ...
}

Using Next.js 12 if that helps

mattreid1 avatar Jul 03 '23 14:07 mattreid1

I've been having the same issue. I was running: $ npx shadcn-ui@latest init

and when using Configure the import alias for components: › @/components it created an @ folder in my root directory.

My solution was:

In my project root, I opened the tsconfig.json and found that my "paths" key was set differently than shadcn expected. I corrected it to:

    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }

and now it's working.

bennik88 avatar Jul 07 '23 06:07 bennik88

Experiencing same issue when using components.json, it breaks all imports in project and I have to rename it to something else (_components.json) to build project without import errors.

reza-ebrahimi avatar Jul 11 '23 14:07 reza-ebrahimi

Even if your component paths in tsconfig contains "@/components/": ["./components/"], you still need to add "@/": ["./"]. That should solve your issue.

RRed avatar Jul 14 '23 20:07 RRed

I've had the same issue, and after struggling for 1 hour, this is what works for me.

My folder structure looks like this:

| public | src -> | app -> | components | component.json | (other cofig files)

changes made in the tsconfig.json file:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@/components/*": ["./src/components/*"],
      "@/*": ["./*"],
    },

0xatulpatil avatar Oct 16 '23 17:10 0xatulpatil

This is not ideal. It would be better if we could just have one alias to match whatever TSConfig path.

I have a lot of paths:

      "@repo/components/*": ["./src/components/*"],
      "@repo/layouts/*": ["./src/layouts/*"],
      "@repo/pages/*": ["./src/pages/*"],
      "@repo/styles/*": ["./src/styles/*"],
      "@repo/types/*": ["./src/types/*"],
      "@repo/utils/*": ["./src/utils/*"],
      "@repo/views/*": ["./src/views/*"],

Organizing my repo.

Brian-McBride avatar Oct 18 '23 04:10 Brian-McBride

Even if your component paths in tsconfig contains "@/components/": ["./components/"], you still need to add "@/": ["./"]. That should solve your issue.

Unfortunately, that's not the outcome I'm expecting. My configuration in tsconfig.json looks like this:

"paths": {
  "~/*": ["./src/*"],
  "@/components/*": ["./src/components/*"],
  "@/lib/*": ["./src/lib/*"]
}

This configuration correctly places lib/utils (for cn) in ./src. I expected the same behavior for components. However, due to the current alias/path configuration, the components alias doesn't seem to map correctly in components.json. The files are being created in the root directory, even though we have a specific path set for components in tsconfig.json.

Therefore, the issue appears in the alias mapping in components.json. The alias for @/components doesn't map with @/components/* as it should. Instead, it seems to only map with @/components. I'm considering adding the following to my tsconfig.json:

"paths": {
  "~/*": ["./src/*"],
  "@/components/*": ["./src/components/*"],
  "@/components": ["./src/components"],
  "@/lib/*": ["./src/lib/*"]
}

jevgenijsblaus avatar Jan 16 '24 13:01 jevgenijsblaus

For me its working for both tsconfig.json OR jsconfig.json

{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }

Arish-018 avatar Feb 10 '24 20:02 Arish-018

For me, it installs correctly to the when I do what @Arish-018 suggested, but my import statements do not resolve correctly.

Haffi112 avatar Feb 27 '24 10:02 Haffi112

I've been having the same issue. I was running: $ npx shadcn-ui@latest init

and when using Configure the import alias for components: › @/components it created an @ folder in my root directory.

My solution was:

In my project root, I opened the tsconfig.json and found that my "paths" key was set differently than shadcn expected. I corrected it to:

    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }

and now it's working.

This worked for me 😅

joshua-singer avatar Jun 12 '24 18:06 joshua-singer

I was getting the same issue with the shadcn dropping its folders in a root level "@" folder. The issue I finally realized to resolve it was that I was adding the "baseUrl" and "paths" outside of the "compilerOptions".

Here is a tsconfig though that is working for me:

"compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, "lib": [ "ES2020", "DOM", "DOM.Iterable" ], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "baseUrl": ".", "paths": { "@/*": [ "./src/*" ] } }, "include": [ "src" ], "references": [ { "path": "./tsconfig.node.json" } ]

AaxellD avatar Jun 14 '24 15:06 AaxellD

I'm having the same issue, tried everything in the comments and nothing works. If I configure the aliases as "src/components" it works, but if I configure as "@/components" it creates de @ folder at the base level of my project.

Don't work:

{
  "aliases": {
      "components": "@/components",
      "utils": "@/lib/utils"
  }
}

Works:

{
  "aliases": {
      "components": "src/components",
      "utils": "src/lib/utils"
  }
}

My tsconfig files:

tsconfig.json

{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

tsconfig.app.json

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
    },
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "noEmit": true
  },
  "include": ["vite.config.ts"]
}

vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
})

components.js

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "src/index.css",
    "baseColor": "zinc",
    "cssVariables": false,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

tailwind.config.ts

import type { Config } from "tailwindcss"

const config = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
  prefix: "",
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      keyframes: {
        "accordion-down": {
          from: { height: "0" },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: "0" },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
} satisfies Config

export default config

Can someone spot the problem? FYI I'm using WSL

Terule avatar Jun 25 '24 11:06 Terule

For me its working for both tsconfig.json OR jsconfig.json

{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }

if you are using react, vite and typescript this should work

Chucks1093 avatar Jun 25 '24 13:06 Chucks1093

For me its working for both tsconfig.json OR jsconfig.json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }

if you are using react, vite and typescript this should work

not working, you can see my tsconfig file in my comment

Terule avatar Jun 25 '24 22:06 Terule

This answer (6th step) on SO resolved the problem for me.

Simply adding the following to vite.config.ts since they were apparently undefined Be sure to also follow the steps mentioned in shadcn's UI documentation

// vite.config.ts
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

Note: I did have to grab lib/utils.tsx manually afterward since it was not being generated. Manual installation, step 7

shoodey avatar Jun 27 '24 01:06 shoodey

I've had the same issue, and after struggling for 1 hour, this is what works for me.

My folder structure looks like this:

| public | src -> | app -> | components | component.json | (other cofig files)

changes made in the tsconfig.json file:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@/components/*": ["./src/components/*"],
      "@/*": ["./*"],
    },

This is the only solution that worked for me. Thanks a ton!

KaziMdMehediHasan avatar Jun 27 '24 13:06 KaziMdMehediHasan

Just to clarify, the custom paths work for import statements. So, my "@components/" path (or @/components depending on the base URL) works fine, but Shad is not picking it and creates a @ folder or @components at the root directory

Terule avatar Jun 29 '24 13:06 Terule

The new tsconfig files generated by vite (e.g. when I did pnpm create vite) outputs a different tsconfig layout, and it looks like the CLI doesn't handle it properly.

  • Previously: tsconfig.json and tsconfig.json (shadcn ui generates files correctly, in the src folder)
  • Now: tsconfig.app.json, tsconfig.node.json and tsconfig.json (shadcn ui wrongly generates files to the root folder)

For a quicker workaround, you could just use my tsconfig from an open source project:

  • https://github.com/ben-xD/geojsons/blob/main/frontend/tsconfig.node.json
  • https://github.com/ben-xD/geojsons/blob/main/frontend/tsconfig.json
  • Delete tsconfig.app.json
  • Re run npx shadcn-ui@latest init

ben-xD avatar Jun 29 '24 19:06 ben-xD

I'm having the same issue, tried everything in the comments and nothing works. If I configure the aliases as "src/components" it works, but if I configure as "@/components" it creates de @ folder at the base level of my project.

Don't work:

{
  "aliases": {
      "components": "@/components",
      "utils": "@/lib/utils"
  }
}

Works:

{
  "aliases": {
      "components": "src/components",
      "utils": "src/lib/utils"
  }
}

My tsconfig files:

tsconfig.json

{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

tsconfig.app.json

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
    },
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "noEmit": true
  },
  "include": ["vite.config.ts"]
}

vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
})

components.js

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "src/index.css",
    "baseColor": "zinc",
    "cssVariables": false,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

tailwind.config.ts

import type { Config } from "tailwindcss"

const config = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
  prefix: "",
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      keyframes: {
        "accordion-down": {
          from: { height: "0" },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: "0" },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
} satisfies Config

export default config

Can someone spot the problem? FYI I'm using WSL

I also face the same issue here 🫡

forhadmia1 avatar Jun 30 '24 16:06 forhadmia1

I'm having the same issue, tried everything in the comments and nothing works. If I configure the aliases as "src/components" it works, but if I configure as "@/components" it creates de @ folder at the base level of my project.

Don't work:

{
  "aliases": {
      "components": "@/components",
      "utils": "@/lib/utils"
  }
}

Works:

{
  "aliases": {
      "components": "src/components",
      "utils": "src/lib/utils"
  }
}

My tsconfig files:

tsconfig.json

{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

tsconfig.app.json

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
    },
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "noEmit": true
  },
  "include": ["vite.config.ts"]
}

vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
})

components.js

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "src/index.css",
    "baseColor": "zinc",
    "cssVariables": false,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

tailwind.config.ts

import type { Config } from "tailwindcss"

const config = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
  prefix: "",
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      keyframes: {
        "accordion-down": {
          from: { height: "0" },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: "0" },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
} satisfies Config

export default config

Can someone spot the problem? FYI I'm using WSL

I solved the issue doing this changes in tsconfig.json file

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "files": [],
  "references": [
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

this work for me now 😊😊

forhadmia1 avatar Jun 30 '24 17:06 forhadmia1

Thank you!! @forhadmia1

Adding compilerOptions to tsconfig.json instead of tsconfig.app.json worked for me too.

muditchoudhary avatar Jul 01 '24 08:07 muditchoudhary

The new tsconfig files generated by vite (e.g. when I did pnpm create vite) outputs a different tsconfig layout, and it looks like the CLI doesn't handle it properly.

  • Previously: tsconfig.json and tsconfig.json (shadcn ui generates files correctly, in the src folder)
  • Now: tsconfig.app.json, tsconfig.node.json and tsconfig.json (shadcn ui wrongly generates files to the root folder)

For a quicker workaround, you could just use my tsconfig from an open source project:

  • https://github.com/ben-xD/geojsons/blob/main/frontend/tsconfig.node.json
  • https://github.com/ben-xD/geojsons/blob/main/frontend/tsconfig.json
  • Delete tsconfig.app.json
  • Re run npx shadcn-ui@latest init

You are a good man. Thank you for this solution, it solved my problem!

duhnunes avatar Jul 01 '24 20:07 duhnunes

Thank you!! @forhadmia1

Adding compilerOptions to tsconfig.json instead of tsconfig.app.json worked for me too.

Yes it's also working for me. Thanks @forhadmia1

prayag2002 avatar Jul 05 '24 13:07 prayag2002

I have written a detailed blog how I setup the my react project and I have written a detailed explanation with code how to configure shadcn with vite+react.

Check it out here

Arghyahub avatar Jul 06 '24 06:07 Arghyahub

I found a simpler solution than my original one,

  • add paths to tsconfig.json's compilerOptions, so that the shadcn ui tool will find the compilerOptions.paths and output it's code to the right folder (instead of the @ in the root):
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  • add the same block to the existing compilerOptions in tsconfig.app.json, so that our code can also import from @. This is required because some of the code from shadcn has @ imports to:
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  • run npx shadcn-ui@latest add button
  • add any components (e.g. npx shadcn-ui@latest add button

Without debugging/reading the shadcn code, I believe the shadcn init tool is expecting to read tsconfig.json's compilerOptions.paths, but it's no longer there. See https://github.com/shadcn-ui/ui/issues/797#issuecomment-2198316058 for more info

ben-xD avatar Jul 07 '24 16:07 ben-xD