Buckets:
| # Exit on error | |
| set -e | |
| # Detect Node version | |
| NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) | |
| echo "๐ Detected Node.js version: $NODE_VERSION" | |
| if [ "$NODE_VERSION" -lt 18 ]; then | |
| echo "โ Error: Node.js 18 or higher is required" | |
| echo " Current version: $(node -v)" | |
| exit 1 | |
| fi | |
| # Set Vite version based on Node version | |
| if [ "$NODE_VERSION" -ge 20 ]; then | |
| VITE_VERSION="latest" | |
| echo "โ Using Vite latest (Node 20+)" | |
| else | |
| VITE_VERSION="5.4.11" | |
| echo "โ Using Vite $VITE_VERSION (Node 18 compatible)" | |
| fi | |
| # Detect OS and set sed syntax | |
| if [[ "$OSTYPE" == "darwin"* ]]; then | |
| SED_INPLACE="sed -i ''" | |
| else | |
| SED_INPLACE="sed -i" | |
| fi | |
| # Check if pnpm is installed | |
| if ! command -v pnpm &> /dev/null; then | |
| echo "๐ฆ pnpm not found. Installing pnpm..." | |
| npm install -g pnpm | |
| fi | |
| # Check if project name is provided | |
| if [ -z "$1" ]; then | |
| echo "โ Usage: ./create-react-shadcn-complete.sh <project-name>" | |
| exit 1 | |
| fi | |
| PROJECT_NAME="$1" | |
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| COMPONENTS_TARBALL="$SCRIPT_DIR/shadcn-components.tar.gz" | |
| # Check if components tarball exists | |
| if [ ! -f "$COMPONENTS_TARBALL" ]; then | |
| echo "โ Error: shadcn-components.tar.gz not found in script directory" | |
| echo " Expected location: $COMPONENTS_TARBALL" | |
| exit 1 | |
| fi | |
| echo "๐ Creating new React + Vite project: $PROJECT_NAME" | |
| # Create new Vite project (always use latest create-vite, pin vite version later) | |
| pnpm create vite "$PROJECT_NAME" --template react-ts | |
| # Navigate into project directory | |
| cd "$PROJECT_NAME" | |
| echo "๐งน Cleaning up Vite template..." | |
| $SED_INPLACE '/<link rel="icon".*vite\.svg/d' index.html | |
| $SED_INPLACE 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html | |
| echo "๐ฆ Installing base dependencies..." | |
| pnpm install | |
| # Pin Vite version for Node 18 | |
| if [ "$NODE_VERSION" -lt 20 ]; then | |
| echo "๐ Pinning Vite to $VITE_VERSION for Node 18 compatibility..." | |
| pnpm add -D vite@$VITE_VERSION | |
| fi | |
| echo "๐ฆ Installing Tailwind CSS and dependencies..." | |
| pnpm install -D tailwindcss@3.4.1 postcss autoprefixer @types/node tailwindcss-animate | |
| pnpm install class-variance-authority clsx tailwind-merge lucide-react next-themes | |
| echo "โ๏ธ Creating Tailwind and PostCSS configuration..." | |
| cat > postcss.config.js << 'EOF' | |
| export default { | |
| plugins: { | |
| tailwindcss: {}, | |
| autoprefixer: {}, | |
| }, | |
| } | |
| EOF | |
| echo "๐ Configuring Tailwind with shadcn theme..." | |
| cat > tailwind.config.js << 'EOF' | |
| /** @type {import('tailwindcss').Config} */ | |
| module.exports = { | |
| darkMode: ["class"], | |
| content: [ | |
| "./index.html", | |
| "./src/**/*.{js,ts,jsx,tsx}", | |
| ], | |
| theme: { | |
| extend: { | |
| colors: { | |
| border: "hsl(var(--border))", | |
| input: "hsl(var(--input))", | |
| ring: "hsl(var(--ring))", | |
| background: "hsl(var(--background))", | |
| foreground: "hsl(var(--foreground))", | |
| primary: { | |
| DEFAULT: "hsl(var(--primary))", | |
| foreground: "hsl(var(--primary-foreground))", | |
| }, | |
| secondary: { | |
| DEFAULT: "hsl(var(--secondary))", | |
| foreground: "hsl(var(--secondary-foreground))", | |
| }, | |
| destructive: { | |
| DEFAULT: "hsl(var(--destructive))", | |
| foreground: "hsl(var(--destructive-foreground))", | |
| }, | |
| muted: { | |
| DEFAULT: "hsl(var(--muted))", | |
| foreground: "hsl(var(--muted-foreground))", | |
| }, | |
| accent: { | |
| DEFAULT: "hsl(var(--accent))", | |
| foreground: "hsl(var(--accent-foreground))", | |
| }, | |
| popover: { | |
| DEFAULT: "hsl(var(--popover))", | |
| foreground: "hsl(var(--popover-foreground))", | |
| }, | |
| card: { | |
| DEFAULT: "hsl(var(--card))", | |
| foreground: "hsl(var(--card-foreground))", | |
| }, | |
| }, | |
| borderRadius: { | |
| lg: "var(--radius)", | |
| md: "calc(var(--radius) - 2px)", | |
| sm: "calc(var(--radius) - 4px)", | |
| }, | |
| keyframes: { | |
| "accordion-down": { | |
| from: { height: "0" }, | |
| to: { height: "var(--radix-accordion-content-height)" }, | |
| }, | |
| "accordion-up": { | |
| from: { height: "var(--radix-accordion-content-height)" }, | |
| to: { height: "0" }, | |
| }, | |
| }, | |
| animation: { | |
| "accordion-down": "accordion-down 0.2s ease-out", | |
| "accordion-up": "accordion-up 0.2s ease-out", | |
| }, | |
| }, | |
| }, | |
| plugins: [require("tailwindcss-animate")], | |
| } | |
| EOF | |
| # Add Tailwind directives and CSS variables to index.css | |
| echo "๐จ Adding Tailwind directives and CSS variables..." | |
| cat > src/index.css << 'EOF' | |
| @tailwind base; | |
| @tailwind components; | |
| @tailwind utilities; | |
| @layer base { | |
| :root { | |
| --background: 0 0% 100%; | |
| --foreground: 0 0% 3.9%; | |
| --card: 0 0% 100%; | |
| --card-foreground: 0 0% 3.9%; | |
| --popover: 0 0% 100%; | |
| --popover-foreground: 0 0% 3.9%; | |
| --primary: 0 0% 9%; | |
| --primary-foreground: 0 0% 98%; | |
| --secondary: 0 0% 96.1%; | |
| --secondary-foreground: 0 0% 9%; | |
| --muted: 0 0% 96.1%; | |
| --muted-foreground: 0 0% 45.1%; | |
| --accent: 0 0% 96.1%; | |
| --accent-foreground: 0 0% 9%; | |
| --destructive: 0 84.2% 60.2%; | |
| --destructive-foreground: 0 0% 98%; | |
| --border: 0 0% 89.8%; | |
| --input: 0 0% 89.8%; | |
| --ring: 0 0% 3.9%; | |
| --radius: 0.5rem; | |
| } | |
| .dark { | |
| --background: 0 0% 3.9%; | |
| --foreground: 0 0% 98%; | |
| --card: 0 0% 3.9%; | |
| --card-foreground: 0 0% 98%; | |
| --popover: 0 0% 3.9%; | |
| --popover-foreground: 0 0% 98%; | |
| --primary: 0 0% 98%; | |
| --primary-foreground: 0 0% 9%; | |
| --secondary: 0 0% 14.9%; | |
| --secondary-foreground: 0 0% 98%; | |
| --muted: 0 0% 14.9%; | |
| --muted-foreground: 0 0% 63.9%; | |
| --accent: 0 0% 14.9%; | |
| --accent-foreground: 0 0% 98%; | |
| --destructive: 0 62.8% 30.6%; | |
| --destructive-foreground: 0 0% 98%; | |
| --border: 0 0% 14.9%; | |
| --input: 0 0% 14.9%; | |
| --ring: 0 0% 83.1%; | |
| } | |
| } | |
| @layer base { | |
| * { | |
| @apply border-border; | |
| } | |
| body { | |
| @apply bg-background text-foreground; | |
| } | |
| } | |
| EOF | |
| # Add path aliases to tsconfig.json | |
| echo "๐ง Adding path aliases to tsconfig.json..." | |
| node -e " | |
| const fs = require('fs'); | |
| const config = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8')); | |
| config.compilerOptions = config.compilerOptions || {}; | |
| config.compilerOptions.baseUrl = '.'; | |
| config.compilerOptions.paths = { '@/*': ['./src/*'] }; | |
| fs.writeFileSync('tsconfig.json', JSON.stringify(config, null, 2)); | |
| " | |
| # Add path aliases to tsconfig.app.json | |
| echo "๐ง Adding path aliases to tsconfig.app.json..." | |
| node -e " | |
| const fs = require('fs'); | |
| const path = 'tsconfig.app.json'; | |
| const content = fs.readFileSync(path, 'utf8'); | |
| // Remove comments manually | |
| const lines = content.split('\n').filter(line => !line.trim().startsWith('//')); | |
| const jsonContent = lines.join('\n'); | |
| const config = JSON.parse(jsonContent.replace(/\/\*[\s\S]*?\*\//g, '').replace(/,(\s*[}\]])/g, '\$1')); | |
| config.compilerOptions = config.compilerOptions || {}; | |
| config.compilerOptions.baseUrl = '.'; | |
| config.compilerOptions.paths = { '@/*': ['./src/*'] }; | |
| fs.writeFileSync(path, JSON.stringify(config, null, 2)); | |
| " | |
| # Update vite.config.ts | |
| echo "โ๏ธ Updating Vite configuration..." | |
| cat > vite.config.ts << 'EOF' | |
| import path from "path"; | |
| import react from "@vitejs/plugin-react"; | |
| import { defineConfig } from "vite"; | |
| export default defineConfig({ | |
| plugins: [react()], | |
| resolve: { | |
| alias: { | |
| "@": path.resolve(__dirname, "./src"), | |
| }, | |
| }, | |
| }); | |
| EOF | |
| # Install all shadcn/ui dependencies | |
| echo "๐ฆ Installing shadcn/ui dependencies..." | |
| pnpm install @radix-ui/react-accordion @radix-ui/react-aspect-ratio @radix-ui/react-avatar @radix-ui/react-checkbox @radix-ui/react-collapsible @radix-ui/react-context-menu @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-hover-card @radix-ui/react-label @radix-ui/react-menubar @radix-ui/react-navigation-menu @radix-ui/react-popover @radix-ui/react-progress @radix-ui/react-radio-group @radix-ui/react-scroll-area @radix-ui/react-select @radix-ui/react-separator @radix-ui/react-slider @radix-ui/react-slot @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-toast @radix-ui/react-toggle @radix-ui/react-toggle-group @radix-ui/react-tooltip | |
| pnpm install sonner cmdk vaul embla-carousel-react react-day-picker react-resizable-panels date-fns react-hook-form @hookform/resolvers zod | |
| # Extract shadcn components from tarball | |
| echo "๐ฆ Extracting shadcn/ui components..." | |
| tar -xzf "$COMPONENTS_TARBALL" -C src/ | |
| # Create components.json for reference | |
| echo "๐ Creating components.json config..." | |
| cat > components.json << 'EOF' | |
| { | |
| "$schema": "https://ui.shadcn.com/schema.json", | |
| "style": "default", | |
| "rsc": false, | |
| "tsx": true, | |
| "tailwind": { | |
| "config": "tailwind.config.js", | |
| "css": "src/index.css", | |
| "baseColor": "slate", | |
| "cssVariables": true, | |
| "prefix": "" | |
| }, | |
| "aliases": { | |
| "components": "@/components", | |
| "utils": "@/lib/utils", | |
| "ui": "@/components/ui", | |
| "lib": "@/lib", | |
| "hooks": "@/hooks" | |
| } | |
| } | |
| EOF | |
| echo "โ Setup complete! You can now use Tailwind CSS and shadcn/ui in your project." | |
| echo "" | |
| echo "๐ฆ Included components (40+ total):" | |
| echo " - accordion, alert, aspect-ratio, avatar, badge, breadcrumb" | |
| echo " - button, calendar, card, carousel, checkbox, collapsible" | |
| echo " - command, context-menu, dialog, drawer, dropdown-menu" | |
| echo " - form, hover-card, input, label, menubar, navigation-menu" | |
| echo " - popover, progress, radio-group, resizable, scroll-area" | |
| echo " - select, separator, sheet, skeleton, slider, sonner" | |
| echo " - switch, table, tabs, textarea, toast, toggle, toggle-group, tooltip" | |
| echo "" | |
| echo "To start developing:" | |
| echo " cd $PROJECT_NAME" | |
| echo " pnpm dev" | |
| echo "" | |
| echo "๐ Import components like:" | |
| echo " import { Button } from '@/components/ui/button'" | |
| echo " import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'" | |
| echo " import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog'" | |
Xet Storage Details
- Size:
- 9.92 kB
- Xet hash:
- b586316c0a69eea82829d65ae15954986a4581f734bd66469590eb999ed31552
ยท
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.