├── .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 |
19 |
20 |
21 |
22 | Turborepo Docs with: tailwindcss & shadcn/ui pre-configured.
23 | Shadcn/UI Button
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 | [](https://github.com/henriqpohl/turborepo-shadcn-ui-tailwindcss.git)
2 |
3 | # 🚀 Turborepo starter NextJS with Shadcn/UI & Tailwind CSS
4 |
5 |
6 |
7 | 
8 | 
9 | 
10 | 
11 | 
12 | 
13 | 
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 |
--------------------------------------------------------------------------------