├── .npmrc ├── apps └── docs │ ├── tailwind.config.ts │ ├── postcss.config.mjs │ ├── app │ ├── favicon.ico │ ├── layout.tsx │ └── page.tsx │ ├── next.config.mjs │ ├── next-env.d.ts │ ├── .eslintrc.js │ ├── tsconfig.json │ ├── public │ ├── vercel.svg │ ├── circles.svg │ ├── next.svg │ └── turborepo.svg │ ├── package.json │ └── README.md ├── pnpm-workspace.yaml ├── tsconfig.json ├── packages ├── eslint-config │ ├── README.md │ ├── package.json │ ├── library.js │ ├── next.js │ └── react-internal.js ├── ui │ ├── turbo.json │ ├── postcss.config.mjs │ ├── src │ │ ├── lib │ │ │ └── utils.ts │ │ ├── components │ │ │ └── ui │ │ │ │ └── button.tsx │ │ └── styles │ │ │ └── globals.css │ ├── tsconfig.lint.json │ ├── .eslintrc.js │ ├── tsconfig.json │ ├── components.json │ ├── package.json │ └── tailwind.config.ts └── typescript-config │ ├── package.json │ ├── react-library.json │ ├── nextjs.json │ └── base.json ├── .eslintrc.js ├── turbo.json ├── .gitignore ├── package.json ├── LICENSE.txt └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/docs/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | export * from "ui/tailwind.config"; -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'apps/*' 3 | - 'packages/*' -------------------------------------------------------------------------------- /apps/docs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export { default } from "ui/postcss.config"; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/base.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # `@turbo/eslint-config` 2 | 3 | Collection of internal eslint configurations. 4 | -------------------------------------------------------------------------------- /apps/docs/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henriqpohl/turborepo-shadcn-ui-tailwindcss/HEAD/apps/docs/app/favicon.ico -------------------------------------------------------------------------------- /apps/docs/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | transpilePackages: ["ui"], 4 | }; 5 | 6 | export default nextConfig; -------------------------------------------------------------------------------- /packages/ui/turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "extends": ["//"], 4 | "tasks": { 5 | "build": { 6 | "outputs": ["dist/**"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/ui/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | }, 7 | }; 8 | 9 | export default config; -------------------------------------------------------------------------------- /packages/ui/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /packages/typescript-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/typescript-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "MIT", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.lint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": ["src", "turbo"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/typescript-config/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "React Library", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "jsx": "react-jsx", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/docs/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/docs/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ["@repo/eslint-config/next.js"], 5 | parser: "@typescript-eslint/parser", 6 | parserOptions: { 7 | project: true, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /packages/ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ["@repo/eslint-config/react-internal.js"], 5 | parser: "@typescript-eslint/parser", 6 | parserOptions: { 7 | project: "./tsconfig.lint.json", 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This configuration only applies to the package manager root. 2 | /** @type {import("eslint").Linter.Config} */ 3 | module.exports = { 4 | ignorePatterns: ["apps/**", "packages/**"], 5 | extends: ["@repo/eslint-config/library.js"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | project: true, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | //"outDir": "dist" 5 | "baseUrl": ".", 6 | "paths": { 7 | "@ui/*": ["./src/*"], 8 | "@ui/components/ui*": ["./src/components/ui/*"] 9 | } 10 | }, 11 | "include": ["."], 12 | "exclude": ["node_modules", "dist"] 13 | } 14 | -------------------------------------------------------------------------------- /apps/docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/nextjs.json", 3 | "compilerOptions": { 4 | "plugins": [ 5 | { 6 | "name": "next" 7 | } 8 | ] 9 | }, 10 | "include": [ 11 | "next-env.d.ts", 12 | "next.config.mjs", 13 | "**/*.ts", 14 | "**/*.tsx", 15 | ".next/types/**/*.ts" 16 | ], 17 | "exclude": ["node_modules"] 18 | } 19 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": ["**/.env.*local"], 4 | "tasks": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "outputs": [".next/**", "!.next/cache/**"] 8 | }, 9 | "lint": { 10 | "dependsOn": ["^lint"] 11 | }, 12 | "dev": { 13 | "cache": false, 14 | "persistent": true 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/ui/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true 11 | }, 12 | "aliases": { 13 | "components": "@ui/components", 14 | "utils": "@ui/lib/utils" 15 | } 16 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # Local env files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Testing 16 | coverage 17 | 18 | # Turbo 19 | .turbo 20 | 21 | # Vercel 22 | .vercel 23 | 24 | # Build Outputs 25 | .next/ 26 | out/ 27 | build 28 | dist 29 | 30 | 31 | # Debug 32 | npm-debug.log* 33 | 34 | # Misc 35 | .DS_Store 36 | *.pem 37 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/eslint-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "files": [ 6 | "library.js", 7 | "next.js", 8 | "react-internal.js" 9 | ], 10 | "devDependencies": { 11 | "@typescript-eslint/eslint-plugin": "^8.18.2", 12 | "@typescript-eslint/parser": "^8.18.2", 13 | "@vercel/style-guide": "^6.0.0", 14 | "eslint-config-prettier": "^9.1.0", 15 | "eslint-config-turbo": "^2.3.3", 16 | "eslint-plugin-only-warn": "^1.1.0", 17 | "typescript": "^5.7.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "turborepo-tailwind-shadcn-ui", 3 | "version": "1.9.4", 4 | "private": true, 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "turbo build", 8 | "dev": "turbo dev", 9 | "lint": "turbo lint", 10 | "format": "prettier --write \"**/*.{ts,tsx,md}\"" 11 | }, 12 | "devDependencies": { 13 | "@repo/eslint-config": "workspace:*", 14 | "@repo/typescript-config": "workspace:*", 15 | "prettier": "^3.7.4", 16 | "turbo": "^2.6.3" 17 | }, 18 | "packageManager": "pnpm@9.15.1", 19 | "engines": { 20 | "node": ">=18" 21 | } 22 | } -------------------------------------------------------------------------------- /apps/docs/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "@ui/styles/globals.css"; 2 | import type { Metadata } from "next"; 3 | import { Inter } from "next/font/google"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Turborepo", 9 | description: "Generated by create turbo", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /packages/typescript-config/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Next.js", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "plugins": [{ "name": "next" }], 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "allowJs": true, 10 | "jsx": "preserve", 11 | "noEmit": true, 12 | "paths": { 13 | "@/*": ["./*"], 14 | "@ui/*": ["../../packages/ui/src/*"], 15 | "@ui/components/*": ["../../packages/ui/src/components/ui/*"], 16 | "@ui/components/ui/*": ["../../packages/ui/src/components/ui/*"] 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /apps/docs/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/typescript-config/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "declaration": true, 6 | "declarationMap": true, 7 | "esModuleInterop": true, 8 | "incremental": false, 9 | "isolatedModules": true, 10 | "lib": ["es2022", "DOM", "DOM.Iterable"], 11 | "module": "NodeNext", 12 | "moduleDetection": "force", 13 | "moduleResolution": "NodeNext", 14 | "noUncheckedIndexedAccess": true, 15 | "resolveJsonModule": true, 16 | "skipLibCheck": true, 17 | "strict": true, 18 | "target": "ES2022" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/eslint-config/library.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("node:path"); 2 | 3 | const project = resolve(process.cwd(), "tsconfig.json"); 4 | 5 | /** @type {import("eslint").Linter.Config} */ 6 | module.exports = { 7 | extends: ["eslint:recommended", "prettier", "eslint-config-turbo"], 8 | plugins: ["only-warn"], 9 | globals: { 10 | React: true, 11 | JSX: true, 12 | }, 13 | env: { 14 | node: true, 15 | }, 16 | settings: { 17 | "import/resolver": { 18 | typescript: { 19 | project, 20 | }, 21 | }, 22 | }, 23 | ignorePatterns: [ 24 | // Ignore dotfiles 25 | ".*.js", 26 | "node_modules/", 27 | "dist/", 28 | ], 29 | overrides: [ 30 | { 31 | files: ["*.js?(x)", "*.ts?(x)"], 32 | }, 33 | ], 34 | }; 35 | -------------------------------------------------------------------------------- /packages/eslint-config/next.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("node:path"); 2 | 3 | const project = resolve(process.cwd(), "tsconfig.json"); 4 | 5 | /** @type {import("eslint").Linter.Config} */ 6 | module.exports = { 7 | extends: [ 8 | "eslint:recommended", 9 | "prettier", 10 | require.resolve("@vercel/style-guide/eslint/next"), 11 | "eslint-config-turbo", 12 | ], 13 | globals: { 14 | React: true, 15 | JSX: true, 16 | }, 17 | env: { 18 | node: true, 19 | browser: true, 20 | }, 21 | plugins: ["only-warn"], 22 | settings: { 23 | "import/resolver": { 24 | typescript: { 25 | project, 26 | }, 27 | }, 28 | }, 29 | ignorePatterns: [ 30 | // Ignore dotfiles 31 | ".*.js", 32 | "node_modules/", 33 | ], 34 | overrides: [{ files: ["*.js?(x)", "*.ts?(x)"] }], 35 | }; 36 | -------------------------------------------------------------------------------- /apps/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --port 3001", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "eslint . --max-warnings 0" 10 | }, 11 | "dependencies": { 12 | "eslint": "^9.17.0", 13 | "next": "^15.1.3", 14 | "react": "^19.0.0", 15 | "react-dom": "^19.0.0", 16 | "ui": "workspace:*" 17 | }, 18 | "devDependencies": { 19 | "@next/eslint-plugin-next": "^15.1.3", 20 | "@repo/eslint-config": "workspace:*", 21 | "@repo/typescript-config": "workspace:*", 22 | "@types/eslint": "^9.6.1", 23 | "@types/node": "^22.10.2", 24 | "@types/react": "^19.0.2", 25 | "@types/react-dom": "^19.0.2", 26 | "autoprefixer": "^10.4.20", 27 | "postcss": "^8.4.49", 28 | "tailwindcss": "^3.4.17", 29 | "typescript": "^5.7.2" 30 | } 31 | } -------------------------------------------------------------------------------- /packages/eslint-config/react-internal.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("node:path"); 2 | 3 | const project = resolve(process.cwd(), "tsconfig.json"); 4 | 5 | /* 6 | * This is a custom ESLint configuration for use with 7 | * internal (bundled by their consumer) libraries 8 | * that utilize React. 9 | * 10 | * This config extends the Vercel Engineering Style Guide. 11 | * For more information, see https://github.com/vercel/style-guide 12 | * 13 | */ 14 | 15 | /** @type {import("eslint").Linter.Config} */ 16 | module.exports = { 17 | extends: ["eslint:recommended", "prettier", "eslint-config-turbo"], 18 | plugins: ["only-warn"], 19 | globals: { 20 | React: true, 21 | JSX: true, 22 | }, 23 | env: { 24 | browser: true, 25 | }, 26 | settings: { 27 | "import/resolver": { 28 | typescript: { 29 | project, 30 | }, 31 | }, 32 | }, 33 | ignorePatterns: [ 34 | // Ignore dotfiles 35 | ".*.js", 36 | "node_modules/", 37 | "dist/", 38 | ], 39 | overrides: [ 40 | // Force ESLint to detect .tsx files 41 | { files: ["*.js?(x)", "*.ts?(x)"] }, 42 | ], 43 | }; 44 | -------------------------------------------------------------------------------- /apps/docs/public/circles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 henriqpohl (hello@henriqpohl.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ui", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "lint": "eslint . --max-warnings 0" 7 | }, 8 | "devDependencies": { 9 | "@repo/eslint-config": "workspace:*", 10 | "@repo/typescript-config": "workspace:*", 11 | "@turbo/gen": "^2.3.3", 12 | "@types/eslint": "^9.6.1", 13 | "@types/node": "^22.10.2", 14 | "@types/react": "^19.0.2", 15 | "@types/react-dom": "^19.0.2", 16 | "autoprefixer": "^10.4.20", 17 | "eslint": "^9.17.0", 18 | "postcss": "^8.4.49", 19 | "react": "^19.0.0", 20 | "tailwindcss": "^3.4.17", 21 | "typescript": "^5.7.2" 22 | }, 23 | "dependencies": { 24 | "@radix-ui/react-slot": "^1.1.1", 25 | "class-variance-authority": "^0.7.1", 26 | "clsx": "^2.1.1", 27 | "lucide-react": "^0.469.0", 28 | "tailwind-merge": "^2.6.0", 29 | "tailwindcss-animate": "^1.0.7" 30 | }, 31 | "exports": { 32 | "./globals.css": "./src/styles/globals.css", 33 | "./postcss.config": "./postcss.config.mjs", 34 | "./tailwind.config": "./tailwind.config.ts", 35 | "./lib/*": "./src/lib/*.ts", 36 | "./components/*": "./src/components/*.tsx" 37 | } 38 | } -------------------------------------------------------------------------------- /apps/docs/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/docs/README.md: -------------------------------------------------------------------------------- 1 | ## Getting Started 2 | 3 | First, run the development server: 4 | 5 | ```bash 6 | pnpm dev 7 | ``` 8 | 9 | Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. 10 | 11 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 12 | 13 | To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello). 14 | 15 | ## Learn More 16 | 17 | To learn more about Next.js, take a look at the following resources: 18 | 19 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 20 | - [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. 21 | 22 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 23 | 24 | ## Deploy on Vercel 25 | 26 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. 27 | 28 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 29 | -------------------------------------------------------------------------------- /apps/docs/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image" 2 | import { Button } from "@ui/components/button" 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |
8 |
9 |
10 |
11 |
12 | Turborepo 19 |
20 |
21 |
22 | Turborepo Docs with: tailwindcss & shadcn/ui pre-configured. 23 | 24 |
25 |
26 |
27 |
28 |
29 |
30 | ) 31 | } -------------------------------------------------------------------------------- /packages/ui/src/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@ui/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | } 34 | ) 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button" 45 | return ( 46 | 51 | ) 52 | } 53 | ) 54 | Button.displayName = "Button" 55 | 56 | export { Button, buttonVariants } 57 | -------------------------------------------------------------------------------- /packages/ui/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | import tailwindcssAnimate from "tailwindcss-animate"; 3 | 4 | const config = { 5 | darkMode: ["class"], 6 | content: [ 7 | './pages/**/*.{ts,tsx}', 8 | './components/**/*.{ts,tsx}', 9 | './app/**/*.{ts,tsx}', 10 | '../../packages/ui/src/components/**/*.{ts,tsx}', 11 | ], 12 | theme: { 13 | container: { 14 | center: true, 15 | padding: "2rem", 16 | screens: { 17 | "2xl": "1400px", 18 | }, 19 | }, 20 | extend: { 21 | colors: { 22 | border: "hsl(var(--border))", 23 | input: "hsl(var(--input))", 24 | ring: "hsl(var(--ring))", 25 | background: "hsl(var(--background))", 26 | foreground: "hsl(var(--foreground))", 27 | primary: { 28 | DEFAULT: "hsl(var(--primary))", 29 | foreground: "hsl(var(--primary-foreground))", 30 | }, 31 | secondary: { 32 | DEFAULT: "hsl(var(--secondary))", 33 | foreground: "hsl(var(--secondary-foreground))", 34 | }, 35 | destructive: { 36 | DEFAULT: "hsl(var(--destructive))", 37 | foreground: "hsl(var(--destructive-foreground))", 38 | }, 39 | muted: { 40 | DEFAULT: "hsl(var(--muted))", 41 | foreground: "hsl(var(--muted-foreground))", 42 | }, 43 | accent: { 44 | DEFAULT: "hsl(var(--accent))", 45 | foreground: "hsl(var(--accent-foreground))", 46 | }, 47 | popover: { 48 | DEFAULT: "hsl(var(--popover))", 49 | foreground: "hsl(var(--popover-foreground))", 50 | }, 51 | card: { 52 | DEFAULT: "hsl(var(--card))", 53 | foreground: "hsl(var(--card-foreground))", 54 | }, 55 | }, 56 | borderRadius: { 57 | lg: "var(--radius)", 58 | md: "calc(var(--radius) - 2px)", 59 | sm: "calc(var(--radius) - 4px)", 60 | }, 61 | keyframes: { 62 | "accordion-down": { 63 | from: { height: "0" }, 64 | to: { height: "var(--radix-accordion-content-height)" }, 65 | }, 66 | "accordion-up": { 67 | from: { height: "var(--radix-accordion-content-height)" }, 68 | to: { height:"0" }, 69 | }, 70 | }, 71 | animation: { 72 | "accordion-down": "accordion-down 0.2s ease-out", 73 | "accordion-up": "accordion-up 0.2s ease-out", 74 | }, 75 | }, 76 | }, 77 | plugins: [tailwindcssAnimate], 78 | } satisfies Config; 79 | 80 | export default config; -------------------------------------------------------------------------------- /packages/ui/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --foreground-rgb: 255, 255, 255; 8 | --background-start-rgb: 0, 0, 0; 9 | --background-end-rgb: 0, 0, 0; 10 | 11 | --background: 0 0% 100%; 12 | --foreground: 222.2 84% 4.9%; 13 | 14 | --card: 0 0% 100%; 15 | --card-foreground: 222.2 84% 4.9%; 16 | 17 | --popover: 0 0% 100%; 18 | --popover-foreground: 222.2 84% 4.9%; 19 | 20 | --primary: 222.2 47.4% 11.2%; 21 | --primary-foreground: 210 40% 98%; 22 | 23 | --secondary: 210 40% 96.1%; 24 | --secondary-foreground: 222.2 47.4% 11.2%; 25 | 26 | --muted: 210 40% 96.1%; 27 | --muted-foreground: 215.4 16.3% 46.9%; 28 | 29 | --accent: 210 40% 96.1%; 30 | --accent-foreground: 222.2 47.4% 11.2%; 31 | 32 | --destructive: 0 84.2% 60.2%; 33 | --destructive-foreground: 210 40% 98%; 34 | 35 | --border: 214.3 31.8% 91.4%; 36 | --input: 214.3 31.8% 91.4%; 37 | --ring: 222.2 84% 4.9%; 38 | 39 | --radius: 0.5rem; 40 | } 41 | 42 | .dark { 43 | --background: 222.2 84% 4.9%; 44 | --foreground: 210 40% 98%; 45 | 46 | --card: 222.2 84% 4.9%; 47 | --card-foreground: 210 40% 98%; 48 | 49 | --popover: 222.2 84% 4.9%; 50 | --popover-foreground: 210 40% 98%; 51 | 52 | --primary: 210 40% 98%; 53 | --primary-foreground: 222.2 47.4% 11.2%; 54 | 55 | --secondary: 217.2 32.6% 17.5%; 56 | --secondary-foreground: 210 40% 98%; 57 | 58 | --muted: 217.2 32.6% 17.5%; 59 | --muted-foreground: 215 20.2% 65.1%; 60 | 61 | --accent: 217.2 32.6% 17.5%; 62 | --accent-foreground: 210 40% 98%; 63 | 64 | --destructive: 0 62.8% 30.6%; 65 | --destructive-foreground: 210 40% 98%; 66 | 67 | --border: 217.2 32.6% 17.5%; 68 | --input: 217.2 32.6% 17.5%; 69 | --ring: 212.7 26.8% 83.9%; 70 | } 71 | } 72 | 73 | @layer base { 74 | * { 75 | @apply border-border; 76 | padding: 0; 77 | margin: 0; 78 | } 79 | 80 | html, 81 | body { 82 | max-width: 100vw; 83 | overflow-x: hidden; 84 | } 85 | 86 | body { 87 | @apply text-foreground; 88 | background: linear-gradient( 89 | to bottom, 90 | transparent, 91 | rgb(var(--background-end-rgb)) 92 | ) 93 | rgb(var(--background-start-rgb)); 94 | } 95 | } 96 | 97 | .gradient { 98 | background-image: conic-gradient( 99 | rgb(157, 23, 77), 100 | rgb(107, 33, 168), 101 | rgb(55, 48, 163) 102 | ); 103 | } 104 | -------------------------------------------------------------------------------- /apps/docs/public/turborepo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![image](https://res.cloudinary.com/dvgb6dadg/image/upload/v1719326274/turborepo-tailwindcss-shadcn-ui/cover-turborepo-project_vfha54.png)](https://github.com/henriqpohl/turborepo-shadcn-ui-tailwindcss.git) 2 | 3 | # 🚀 Turborepo starter NextJS with Shadcn/UI & Tailwind CSS 4 | 5 |
6 | 7 | ![Static Badge](https://img.shields.io/badge/Turborepo-2.6.3-orangered?logo=turborepo&link=https%3A%2F%2Fgithub.com%2Fvercel%2Fturbo%2Freleases%2Ftag%2Fv2.6.3) 8 | ![Static Badge](https://img.shields.io/badge/1.0-181818?logo=shadcn%2Fui&label=shadcn%2Fui) 9 | ![Static Badge](https://img.shields.io/badge/3.4.17-blue?&logo=tailwindcss&label=Tailwind%20CSS&color=blue) 10 | ![Static Badge](https://img.shields.io/badge/15.1.3-181818?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI%2BPHRpdGxlPk5leHQuanM8L3RpdGxlPjxwYXRoIGQ9Ik0xOC42NjUgMjEuOTc4QzE2Ljc1OCAyMy4yNTUgMTQuNDY1IDI0IDEyIDI0IDUuMzc3IDI0IDAgMTguNjIzIDAgMTJTNS4zNzcgMCAxMiAwczEyIDUuMzc3IDEyIDEyYzAgMy41ODMtMS41NzQgNi44MDEtNC4wNjcgOS4wMDFMOS4yMTkgNy4ySDcuMnY5LjU5NmgxLjYxNVY5LjI1MWw5Ljg1IDEyLjcyN1ptLTMuMzMyLTguNTMzIDEuNiAyLjA2MVY3LjJoLTEuNnY2LjI0NVoiLz48L3N2Zz4%3D&label=NextJS) 11 | ![Static Badge](https://img.shields.io/badge/pnpm-9.15.1-orange?link=https%3A%2F%2Fgithub.com%2Fpnpm%2Fpnpm%2&logo=PNPM&2Freleases%2Ftag%2Fv9.15.1) 12 | ![GitHub repo size](https://img.shields.io/github/repo-size/henriqpohl/turborepo-shadcn-ui-tailwindcss?color=green) 13 | ![GitHub Release](https://img.shields.io/github/v/release/henriqpohl/turborepo-shadcn-ui-tailwindcss?color=gold) 14 | 15 |
16 | 17 | Turborepo starter **NextJS** with **Shadcn/UI** & **Tailwind CSS** pre-configured for shared UI components powered by: 18 | 19 | - [Turborepo](https://turborepo.org/) 20 | - [Shadcn/UI](https://ui.shadcn.com/) 21 | - [Tailwind CSS](https://tailwindcss.com/) 22 | - [PNPM](https://pnpm.io/) 23 | 24 | > [!NOTE] 25 | > This example uses `pnpm` as package manager. 26 | 27 | ## 📝 Using this example 28 | 29 | Clone the repository: 30 | 31 | ```sh 32 | git clone https://github.com/henriqpohl/turborepo-shadcn-ui-tailwindcss.git 33 | ``` 34 | 35 | Install dependencies: 36 | 37 | ```sh 38 | cd turborepo-shadcn-ui-tailwindcss 39 | pnpm install 40 | ``` 41 | 42 | ## 📦 What's inside? 43 | 44 | This Turborepo includes the following packages/apps: 45 | 46 | ### Apps and Packages 47 | 48 | - `docs`: a [Next.js](https://nextjs.org/) app 49 | - `@repo/ui`: a stub React component library shared by applications inside of `apps` folder (🚀 powered by **Shadcn/UI** and **Tailwind CSS**) 50 | - `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) 51 | - `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo 52 | 53 | Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). 54 | 55 | ### Utilities 56 | 57 | This Turborepo has some additional tools already setup for you: 58 | 59 | - [TypeScript](https://www.typescriptlang.org/) for static type checking 60 | - [ESLint](https://eslint.org/) for code linting 61 | - [Prettier](https://prettier.io) for code formatting 62 | 63 | ### 🏗️ Build 64 | 65 | To build all apps and packages, run the following command: 66 | 67 | ```sh 68 | cd turborepo-shadcn-ui-tailwindcss 69 | pnpm build 70 | ``` 71 | 72 | ### 💻 Develop 73 | 74 | To develop all apps and packages, run the following command: 75 | 76 | ```sh 77 | cd turborepo-shadcn-ui-tailwindcss 78 | pnpm dev 79 | ``` 80 | 81 | ### 🌐 Remote Caching 82 | 83 | Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. 84 | 85 | By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands: 86 | 87 | ```sh 88 | cd turborepo-shadcn-ui-tailwindcss 89 | npx turbo login 90 | ``` 91 | 92 | This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). 93 | 94 | Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: 95 | 96 | ```sh 97 | npx turbo link 98 | ``` 99 | 100 | ## ℹ️ Useful Links 101 | 102 | Learn more about the power of **Turborepo**: 103 | 104 | - [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) 105 | - [Caching](https://turbo.build/repo/docs/core-concepts/caching) 106 | - [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) 107 | - [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) 108 | - [Configuration Options](https://turbo.build/repo/docs/reference/configuration) 109 | - [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) 110 | 111 | Learn more about **Shadcn/UI**: 112 | 113 | - [Documentation](https://ui.shadcn.com/docs) 114 | - [Components](https://ui.shadcn.com/docs/components/accordion) 115 | 116 | ## 🐞 Found a Bug? 117 | 118 | Uh-oh, looks like you stumbled upon a bug? No worries, we're here to squash it! Just head over to our issues section on GitHub and let us know what's up. 119 | --------------------------------------------------------------------------------