├── .npmrc ├── apps └── web │ ├── hooks │ └── .gitkeep │ ├── lib │ └── .gitkeep │ ├── components │ ├── .gitkeep │ ├── theme-provider.tsx │ ├── providers.tsx │ ├── theme-toggle.tsx │ ├── demo.tsx │ └── copy.tsx │ ├── app │ ├── favicon.ico │ ├── twitter-image.jpg │ ├── opengraph-image.jpg │ ├── layout.tsx │ ├── globals.css │ ├── example │ │ └── page.tsx │ └── page.tsx │ ├── postcss.config.mjs │ ├── public │ ├── vercel.svg │ ├── window.svg │ ├── file.svg │ ├── globe.svg │ └── next.svg │ ├── eslint.config.js │ ├── next.config.mjs │ ├── next-env.d.ts │ ├── components.json │ ├── tsconfig.json │ └── package.json ├── packages ├── ui │ ├── src │ │ ├── hooks │ │ │ └── .gitkeep │ │ ├── components │ │ │ ├── .gitkeep │ │ │ ├── sonner.tsx │ │ │ └── button.tsx │ │ ├── lib │ │ │ └── utils.ts │ │ └── styles │ │ │ └── globals.css │ ├── eslint.config.js │ ├── postcss.config.mjs │ ├── tsconfig.lint.json │ ├── tsconfig.json │ ├── components.json │ └── package.json ├── eslint-config │ ├── README.md │ ├── base.js │ ├── package.json │ ├── react-internal.js │ └── next.js ├── typescript-config │ ├── README.md │ ├── package.json │ ├── react-library.json │ ├── nextjs.json │ └── base.json └── craft-ds │ ├── postcss.config.mjs │ ├── lib │ └── utils.ts │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── .gitignore │ ├── package.json │ ├── CLAUDE.md │ ├── pnpm-lock.yaml │ ├── bin │ └── init.js │ └── ds.tsx ├── pnpm-workspace.yaml ├── tsconfig.json ├── .vscode └── settings.json ├── .eslintrc.js ├── turbo.json ├── .gitignore ├── package.json └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/web/hooks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/web/lib/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/web/components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/ui/src/hooks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/ui/src/components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "apps/*" 3 | - "packages/*" 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@workspace/typescript-config/base.json" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /apps/web/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brijr/craft/HEAD/apps/web/app/favicon.ico -------------------------------------------------------------------------------- /apps/web/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export { default } from "../../packages/ui/postcss.config.mjs"; 2 | -------------------------------------------------------------------------------- /apps/web/app/twitter-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brijr/craft/HEAD/apps/web/app/twitter-image.jpg -------------------------------------------------------------------------------- /apps/web/app/opengraph-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brijr/craft/HEAD/apps/web/app/opengraph-image.jpg -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "tailwindCSS.experimental.configFile": "packages/ui/src/styles/globals.css" 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # `@workspace/eslint-config` 2 | 3 | Shared eslint configuration for the workspace. 4 | -------------------------------------------------------------------------------- /packages/typescript-config/README.md: -------------------------------------------------------------------------------- 1 | # `@workspace/typescript-config` 2 | 3 | Shared typescript configuration for the workspace. 4 | -------------------------------------------------------------------------------- /apps/web/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/ui/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { config } from "@workspace/eslint-config/react-internal" 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default config 5 | -------------------------------------------------------------------------------- /apps/web/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@workspace/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/web/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | transpilePackages: ["@workspace/ui"], 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /packages/ui/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { "@tailwindcss/postcss": {} }, 4 | }; 5 | 6 | export default config; 7 | -------------------------------------------------------------------------------- /packages/craft-ds/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { "@tailwindcss/postcss": {} }, 4 | }; 5 | 6 | export default config; 7 | -------------------------------------------------------------------------------- /packages/ui/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /packages/craft-ds/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } 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": "@workspace/typescript-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "PROPRIETARY", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.lint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@workspace/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": ["src", "turbo"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/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 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@workspace/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@workspace/ui/*": ["./src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["node_modules", "dist"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/craft-ds/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // ...other config 3 | variants: { 4 | extend: { 5 | flexDirection: ["responsive"], 6 | flexWrap: ["responsive"], 7 | gap: ["responsive"], 8 | gridTemplateColumns: ["responsive"], 9 | gridTemplateRows: ["responsive"], 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /.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: ["@workspace/eslint-config/library.js"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | project: true, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /apps/web/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { ThemeProvider as NextThemesProvider } from "next-themes"; 5 | 6 | export function ThemeProvider({ 7 | children, 8 | ...props 9 | }: React.ComponentProps) { 10 | return {children}; 11 | } 12 | -------------------------------------------------------------------------------- /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 | } 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/web/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/web/components/providers.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { ThemeProvider as NextThemesProvider } from "next-themes" 5 | 6 | export function Providers({ children }: { children: React.ReactNode }) { 7 | return ( 8 | 15 | {children} 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "ui": "tui", 4 | "tasks": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "inputs": ["$TURBO_DEFAULT$", ".env*"], 8 | "outputs": [".next/**", "!.next/cache/**"] 9 | }, 10 | "lint": { 11 | "dependsOn": ["^lint"] 12 | }, 13 | "check-types": { 14 | "dependsOn": ["^check-types"] 15 | }, 16 | "dev": { 17 | "cache": false, 18 | "persistent": true 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.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/ui/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "stone", 10 | "cssVariables": true 11 | }, 12 | "iconLibrary": "lucide", 13 | "aliases": { 14 | "components": "@workspace/ui/components", 15 | "utils": "@workspace/ui/lib/utils", 16 | "hooks": "@workspace/ui/hooks", 17 | "lib": "@workspace/ui/lib", 18 | "ui": "@workspace/ui/components" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "../../packages/ui/src/styles/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true 11 | }, 12 | "iconLibrary": "lucide", 13 | "aliases": { 14 | "components": "@/components", 15 | "hooks": "@/hooks", 16 | "lib": "@/lib", 17 | "utils": "@workspace/ui/lib/utils", 18 | "ui": "@workspace/ui/components", 19 | "craft-ds": "@workspace/craft-ds" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /apps/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@workspace/typescript-config/nextjs.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["./*"], 7 | "@workspace/ui/*": ["../../packages/ui/src/*"], 8 | "@workspace/ui": ["../../packages/ui"], 9 | "@workspace/craft-ds/*": ["../../packages/craft-ds/*"] 10 | }, 11 | "plugins": [ 12 | { 13 | "name": "next" 14 | } 15 | ] 16 | }, 17 | "include": [ 18 | "next-env.d.ts", 19 | "next.config.ts", 20 | "**/*.ts", 21 | "**/*.tsx", 22 | ".next/types/**/*.ts" 23 | ], 24 | "exclude": ["node_modules"] 25 | } 26 | -------------------------------------------------------------------------------- /packages/ui/src/components/sonner.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useTheme } from "next-themes" 4 | import { Toaster as Sonner, ToasterProps } from "sonner" 5 | 6 | const Toaster = ({ ...props }: ToasterProps) => { 7 | const { theme = "system" } = useTheme() 8 | 9 | return ( 10 | 22 | ) 23 | } 24 | 25 | export { Toaster } 26 | -------------------------------------------------------------------------------- /packages/craft-ds/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "bundler", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "paths": { 23 | "@/*": ["./*"] 24 | } 25 | }, 26 | "include": ["**/*.ts", "**/*.tsx"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /apps/web/components/theme-toggle.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { Moon, Sun } from "lucide-react"; 5 | import { useTheme } from "next-themes"; 6 | 7 | export function ThemeToggle() { 8 | const { theme, setTheme } = useTheme(); 9 | 10 | const toggleTheme = () => { 11 | setTheme(theme === "light" ? "dark" : "light"); 12 | }; 13 | 14 | return ( 15 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /packages/eslint-config/base.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js" 2 | import eslintConfigPrettier from "eslint-config-prettier" 3 | import onlyWarn from "eslint-plugin-only-warn" 4 | import turboPlugin from "eslint-plugin-turbo" 5 | import tseslint from "typescript-eslint" 6 | 7 | /** 8 | * A shared ESLint configuration for the repository. 9 | * 10 | * @type {import("eslint").Linter.Config} 11 | * */ 12 | export const config = [ 13 | js.configs.recommended, 14 | eslintConfigPrettier, 15 | ...tseslint.configs.recommended, 16 | { 17 | plugins: { 18 | turbo: turboPlugin, 19 | }, 20 | rules: { 21 | "turbo/no-undeclared-env-vars": "warn", 22 | }, 23 | }, 24 | { 25 | plugins: { 26 | onlyWarn, 27 | }, 28 | }, 29 | { 30 | ignores: ["dist/**"], 31 | }, 32 | ] 33 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@workspace/eslint-config", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "exports": { 7 | "./base": "./base.js", 8 | "./next-js": "./next.js", 9 | "./react-internal": "./react-internal.js" 10 | }, 11 | "devDependencies": { 12 | "@next/eslint-plugin-next": "^15.1.7", 13 | "@typescript-eslint/eslint-plugin": "^8.24.1", 14 | "@typescript-eslint/parser": "^8.24.1", 15 | "eslint": "^9.20.1", 16 | "eslint-config-prettier": "^9.1.0", 17 | "eslint-plugin-only-warn": "^1.1.0", 18 | "eslint-plugin-react": "^7.37.4", 19 | "eslint-plugin-react-hooks": "^5.1.0", 20 | "eslint-plugin-turbo": "^2.4.2", 21 | "globals": "^15.15.0", 22 | "typescript": "^5.7.3", 23 | "typescript-eslint": "^8.24.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/web/components/demo.tsx: -------------------------------------------------------------------------------- 1 | interface Props { 2 | children: React.ReactNode; 3 | attribute: string; 4 | vertical?: boolean; 5 | } 6 | 7 | export const Demo = ({ children, attribute, vertical }: Props) => { 8 | return ( 9 |
14 |
15 |

HTML Attribute

16 |

{attribute}

17 |
18 | 19 |
20 |

21 | Preview 22 |

23 | {children} 24 |
25 |
26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shadcn-ui-monorepo", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "build": "turbo build", 7 | "dev": "turbo dev", 8 | "lint": "turbo lint", 9 | "format": "prettier --write \"**/*.{ts,tsx,md}\"", 10 | "clean": "rimraf node_modules */**/node_modules" 11 | }, 12 | "devDependencies": { 13 | "@workspace/eslint-config": "workspace:*", 14 | "@workspace/typescript-config": "workspace:*", 15 | "prettier": "^3.6.2", 16 | "rimraf": "^6.0.1", 17 | "turbo": "^2.5.4", 18 | "typescript": "5.7.3" 19 | }, 20 | "packageManager": "pnpm@10.4.1", 21 | "engines": { 22 | "node": ">=20" 23 | }, 24 | "pnpm": { 25 | "onlyBuiltDependencies": [ 26 | "@tailwindcss/oxide", 27 | "core-js", 28 | "core-js-pure", 29 | "sharp", 30 | "unrs-resolver" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/craft-ds/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | /.pnp 4 | .pnp.js 5 | 6 | # Testing 7 | /coverage 8 | 9 | # Next.js 10 | /.next/ 11 | /out/ 12 | 13 | # Production 14 | /build 15 | 16 | # Misc 17 | .DS_Store 18 | *.pem 19 | 20 | # Debug 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # Local env files 26 | .env*.local 27 | 28 | # Vercel 29 | .vercel 30 | 31 | # TypeScript 32 | *.tsbuildinfo 33 | next-env.d.ts 34 | 35 | # IDEs and editors 36 | /.idea 37 | .project 38 | .classpath 39 | .c9/ 40 | *.launch 41 | .settings/ 42 | *.sublime-workspace 43 | 44 | # VS Code 45 | .vscode/* 46 | !.vscode/settings.json 47 | !.vscode/tasks.json 48 | !.vscode/launch.json 49 | !.vscode/extensions.json 50 | 51 | # Logs 52 | logs 53 | *.log 54 | 55 | # OS generated files 56 | .DS_Store 57 | .DS_Store? 58 | ._* 59 | .Spotlight-V100 60 | .Trashes 61 | ehthumbs.db 62 | Thumbs.db 63 | 64 | lab/* 65 | -------------------------------------------------------------------------------- /apps/web/public/globe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/craft-ds/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@workspace/craft-ds", 3 | "version": "0.3.56", 4 | "description": "> craft-ds is a Design System developed using a group of `npm` packages and **one component file** created by [Bridger Tower](https://bridger.to) to build websites with NextJS, Tailwind, shadcn/ui, and TypeScript faster 🚀", 5 | "bin": { 6 | "craft-ds": "bin/init.js" 7 | }, 8 | "main": "index.js", 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "clsx": "^2.1.1", 17 | "next-themes": "^0.4.6", 18 | "postcss": "^8.5.4", 19 | "tailwind": "^4.0.0", 20 | "tailwind-merge": "^2.6.0", 21 | "tw-animate-css": "^1.2.4" 22 | }, 23 | "devDependencies": { 24 | "@tailwindcss/postcss": "^4.1.11", 25 | "@types/node": "^22.15.32", 26 | "@types/react": "^19.1.0", 27 | "@types/react-dom": "^19.1.0", 28 | "react": "^19.1.0", 29 | "react-dom": "^19.1.0", 30 | "tailwindcss": "^4.1.11", 31 | "typescript": "^5.8.3" 32 | }, 33 | "exports": { 34 | "./ds": "./ds.tsx" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@workspace/ui", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "lint": "eslint . --max-warnings 0" 8 | }, 9 | "dependencies": { 10 | "@radix-ui/react-slot": "^1.1.2", 11 | "class-variance-authority": "^0.7.1", 12 | "clsx": "^2.1.1", 13 | "lucide-react": "^0.475.0", 14 | "next-themes": "^0.4.4", 15 | "react": "^19.0.0", 16 | "react-dom": "^19.0.0", 17 | "sonner": "^2.0.6", 18 | "tailwind-merge": "^3.0.1", 19 | "tw-animate-css": "^1.2.4", 20 | "zod": "^3.24.2" 21 | }, 22 | "devDependencies": { 23 | "@tailwindcss/postcss": "^4.0.8", 24 | "@turbo/gen": "^2.4.2", 25 | "@types/node": "^20", 26 | "@types/react": "^19", 27 | "@types/react-dom": "^19", 28 | "@workspace/eslint-config": "workspace:*", 29 | "@workspace/typescript-config": "workspace:*", 30 | "tailwindcss": "^4.0.8", 31 | "typescript": "^5.7.3" 32 | }, 33 | "exports": { 34 | "./globals.css": "./src/styles/globals.css", 35 | "./postcss.config": "./postcss.config.mjs", 36 | "./lib/*": "./src/lib/*.ts", 37 | "./components/*": "./src/components/*.tsx", 38 | "./hooks/*": "./src/hooks/*.ts" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --turbopack", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@vercel/analytics": "^1.5.0", 13 | "@workspace/craft-ds": "workspace:*", 14 | "class-variance-authority": "^0.7.1", 15 | "clsx": "^2.1.1", 16 | "lucide-react": "^0.468.0", 17 | "next": "15.3.5", 18 | "next-themes": "^0.4.6", 19 | "react": "^19.1.0", 20 | "react-dom": "^19.1.0", 21 | "react-markdown": "^9.1.0", 22 | "react-wrap-balancer": "^1.1.1", 23 | "sonner": "^1.7.4", 24 | "tailwind-merge": "^2.6.0", 25 | "tailwindcss-animate": "^1.0.7" 26 | }, 27 | "devDependencies": { 28 | "@eslint/eslintrc": "^3.3.1", 29 | "@tailwindcss/postcss": "^4.1.11", 30 | "@types/node": "^20.19.6", 31 | "@types/react": "^19.1.8", 32 | "@types/react-dom": "^19.1.6", 33 | "@workspace/eslint-config": "workspace:^", 34 | "@workspace/typescript-config": "workspace:*", 35 | "eslint": "^9.30.1", 36 | "eslint-config-next": "15.1.0", 37 | "postcss": "^8.5.6", 38 | "tailwindcss": "^4.1.11", 39 | "tw-animate-css": "^1.3.5", 40 | "typescript": "^5.8.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/eslint-config/react-internal.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js" 2 | import eslintConfigPrettier from "eslint-config-prettier" 3 | import pluginReact from "eslint-plugin-react" 4 | import pluginReactHooks from "eslint-plugin-react-hooks" 5 | import globals from "globals" 6 | import tseslint from "typescript-eslint" 7 | 8 | import { config as baseConfig } from "./base.js" 9 | 10 | /** 11 | * A custom ESLint configuration for libraries that use React. 12 | * 13 | * @type {import("eslint").Linter.Config} */ 14 | export const config = [ 15 | ...baseConfig, 16 | js.configs.recommended, 17 | eslintConfigPrettier, 18 | ...tseslint.configs.recommended, 19 | pluginReact.configs.flat.recommended, 20 | { 21 | languageOptions: { 22 | ...pluginReact.configs.flat.recommended.languageOptions, 23 | globals: { 24 | ...globals.serviceworker, 25 | ...globals.browser, 26 | }, 27 | }, 28 | }, 29 | { 30 | plugins: { 31 | "react-hooks": pluginReactHooks, 32 | }, 33 | settings: { react: { version: "detect" } }, 34 | rules: { 35 | ...pluginReactHooks.configs.recommended.rules, 36 | // React scope no longer necessary with new JSX transform. 37 | "react/react-in-jsx-scope": "off", 38 | "react/prop-types": "off", 39 | }, 40 | }, 41 | ] 42 | -------------------------------------------------------------------------------- /apps/web/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/eslint-config/next.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js" 2 | import pluginNext from "@next/eslint-plugin-next" 3 | import eslintConfigPrettier from "eslint-config-prettier" 4 | import pluginReact from "eslint-plugin-react" 5 | import pluginReactHooks from "eslint-plugin-react-hooks" 6 | import globals from "globals" 7 | import tseslint from "typescript-eslint" 8 | 9 | import { config as baseConfig } from "./base.js" 10 | 11 | /** 12 | * A custom ESLint configuration for libraries that use Next.js. 13 | * 14 | * @type {import("eslint").Linter.Config} 15 | * */ 16 | export const nextJsConfig = [ 17 | ...baseConfig, 18 | js.configs.recommended, 19 | eslintConfigPrettier, 20 | ...tseslint.configs.recommended, 21 | { 22 | ...pluginReact.configs.flat.recommended, 23 | languageOptions: { 24 | ...pluginReact.configs.flat.recommended.languageOptions, 25 | globals: { 26 | ...globals.serviceworker, 27 | }, 28 | }, 29 | }, 30 | { 31 | plugins: { 32 | "@next/next": pluginNext, 33 | }, 34 | rules: { 35 | ...pluginNext.configs.recommended.rules, 36 | ...pluginNext.configs["core-web-vitals"].rules, 37 | }, 38 | }, 39 | { 40 | plugins: { 41 | "react-hooks": pluginReactHooks, 42 | }, 43 | settings: { react: { version: "detect" } }, 44 | rules: { 45 | ...pluginReactHooks.configs.recommended.rules, 46 | // React scope no longer necessary with new JSX transform. 47 | "react/react-in-jsx-scope": "off", 48 | "react/prop-types": "off", 49 | }, 50 | }, 51 | ] 52 | -------------------------------------------------------------------------------- /apps/web/components/copy.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { toast } from "sonner"; 4 | 5 | interface CopyProps { 6 | text: string; 7 | } 8 | 9 | export const Copy = ({ text }: CopyProps) => { 10 | return ( 11 | 23 | ); 24 | }; 25 | 26 | const CopyIcon = () => { 27 | return ( 28 | 35 | 41 | 42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /packages/ui/src/components/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 "@workspace/ui/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", 14 | destructive: 15 | "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", 16 | outline: 17 | "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", 18 | secondary: 19 | "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", 20 | ghost: 21 | "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", 22 | link: "text-primary underline-offset-4 hover:underline", 23 | }, 24 | size: { 25 | default: "h-9 px-4 py-2 has-[>svg]:px-3", 26 | sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", 27 | lg: "h-10 rounded-md px-6 has-[>svg]:px-4", 28 | icon: "size-9", 29 | }, 30 | }, 31 | defaultVariants: { 32 | variant: "default", 33 | size: "default", 34 | }, 35 | } 36 | ) 37 | 38 | function Button({ 39 | className, 40 | variant, 41 | size, 42 | asChild = false, 43 | ...props 44 | }: React.ComponentProps<"button"> & 45 | VariantProps & { 46 | asChild?: boolean 47 | }) { 48 | const Comp = asChild ? Slot : "button" 49 | 50 | return ( 51 | 56 | ) 57 | } 58 | 59 | export { Button, buttonVariants } 60 | -------------------------------------------------------------------------------- /packages/craft-ds/CLAUDE.md: -------------------------------------------------------------------------------- 1 | # CLAUDE.md 2 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 | 5 | ## Commands 6 | 7 | ### Development 8 | 9 | - `cd web && npm run dev` - Start the Next.js demo site in development mode with Turbopack 10 | - `cd web && npm run build` - Build the Next.js demo site for production 11 | - `cd web && npm run lint` - Run ESLint on the demo site code 12 | 13 | ### Package Distribution 14 | 15 | - `pnpx craft-ds init` - CLI command to install craft-ds in a Next.js project (run from target project) 16 | 17 | ## Architecture 18 | 19 | craft-ds is a minimalist design system for Next.js applications with two main parts: 20 | 21 | 1. **NPM Package (craft-ds)**: The core design system distributed via npm 22 | 23 | - `ds.tsx` - Main component file containing Layout, Main, Section, Container, Nav, and Prose components 24 | - `lib/utils.ts` - Utility functions including `cn()` for className merging 25 | - `bin/init.js` - CLI installer that sets up the design system in target projects 26 | 27 | 2. **Demo Website (/web)**: Next.js 15 app showcasing the design system 28 | - Uses app router structure 29 | - Configured with Tailwind CSS v4, TypeScript, and shadcn/ui 30 | - Serves as both documentation and live examples 31 | 32 | ### Key Design Principles 33 | 34 | - **Zero runtime overhead**: All styles compiled at build time via Tailwind CSS 35 | - **Type-safe**: Full TypeScript support with strict mode 36 | - **Responsive-first**: Mobile-first breakpoints (sm, md, lg, xl, 2xl) 37 | - **Composable**: Components work together to create consistent layouts 38 | 39 | ### Component Architecture 40 | 41 | ```tsx 42 | // Standard layout pattern 43 | 44 | 45 |
46 |
{/* Semantic sections with consistent spacing */}
47 |
48 |
49 | ``` 50 | 51 | ### Installation Process (handled by CLI) 52 | 53 | 1. Validates Node.js v18+ and Next.js project structure 54 | 2. Installs required dependencies (tailwindcss-animate, clsx, tailwind-merge) 55 | 3. Optionally sets up shadcn/ui with base configuration 56 | 4. Copies ds.tsx to target project's components directory 57 | 5. Updates import paths automatically 58 | 59 | ### Testing 60 | 61 | Currently no test framework is implemented. The `test` script is a placeholder. 62 | -------------------------------------------------------------------------------- /apps/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Geist, Geist_Mono } from "next/font/google"; 2 | import { Analytics } from "@vercel/analytics/next"; 3 | 4 | import Balancer from "react-wrap-balancer"; 5 | import Link from "next/link"; 6 | 7 | import "./globals.css"; 8 | 9 | import { Container, Section } from "@workspace/craft-ds/ds"; 10 | import { ThemeProvider } from "@/components/theme-provider"; 11 | import { ThemeToggle } from "@/components/theme-toggle"; 12 | import { Toaster } from "@workspace/ui/components/sonner"; 13 | import { Github } from "lucide-react"; 14 | import { Copy } from "@/components/copy"; 15 | 16 | import type { Metadata } from "next"; 17 | 18 | const geistSans = Geist({ 19 | variable: "--font-geist-sans", 20 | subsets: ["latin"], 21 | }); 22 | 23 | const geistMono = Geist_Mono({ 24 | variable: "--font-geist-mono", 25 | subsets: ["latin"], 26 | }); 27 | 28 | export const metadata: Metadata = { 29 | title: "Craft Design System", 30 | description: 31 | "A lightweight, flexible design system for building responsive layouts in React and handling prose.", 32 | }; 33 | 34 | export default function RootLayout({ 35 | children, 36 | }: Readonly<{ 37 | children: React.ReactNode; 38 | }>) { 39 | return ( 40 | 41 | 44 | 50 |
51 | {children} 52 |