Initial commit with translated description
This commit is contained in:
57
scripts/bundle-artifact.sh
Normal file
57
scripts/bundle-artifact.sh
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# Bundle a Vite React project into a single HTML file
|
||||
# Usage: bash scripts/bundle-artifact.sh
|
||||
# Run from project root (where package.json is)
|
||||
|
||||
set -e
|
||||
|
||||
echo "📦 Bundling to single HTML file..."
|
||||
|
||||
# Check if we're in a project directory
|
||||
if [ ! -f "package.json" ]; then
|
||||
echo "❌ Error: No package.json found. Run this from your project root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if index.html exists
|
||||
if [ ! -f "index.html" ]; then
|
||||
echo "❌ Error: No index.html found in project root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install bundling dependencies if needed
|
||||
if ! npm ls parcel > /dev/null 2>&1; then
|
||||
echo "📦 Installing bundling dependencies..."
|
||||
npm install -D parcel @parcel/config-default parcel-resolver-tspaths html-inline
|
||||
fi
|
||||
|
||||
# Create .parcelrc if it doesn't exist
|
||||
if [ ! -f ".parcelrc" ]; then
|
||||
echo "⚙️ Creating Parcel config..."
|
||||
cat > .parcelrc << 'EOF'
|
||||
{
|
||||
"extends": "@parcel/config-default",
|
||||
"resolvers": ["parcel-resolver-tspaths", "..."]
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Build with Parcel
|
||||
echo "🔨 Building with Parcel..."
|
||||
npx parcel build index.html --no-source-maps --dist-dir dist-parcel
|
||||
|
||||
# Inline all assets
|
||||
echo "📄 Inlining assets into single HTML..."
|
||||
npx html-inline -i dist-parcel/index.html -o bundle.html -b dist-parcel
|
||||
|
||||
# Clean up
|
||||
rm -rf dist-parcel .parcel-cache
|
||||
|
||||
# Get file size
|
||||
SIZE=$(ls -lh bundle.html | awk '{print $5}')
|
||||
|
||||
echo ""
|
||||
echo "✅ Bundle created: bundle.html ($SIZE)"
|
||||
echo ""
|
||||
echo "You can now share this file or use it as a Claude artifact."
|
||||
echo ""
|
||||
154
scripts/init-nextjs.sh
Normal file
154
scripts/init-nextjs.sh
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
# Initialize a Next.js + TypeScript + Tailwind + shadcn/ui project
|
||||
# Usage: bash scripts/init-nextjs.sh <project-name>
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_NAME="${1:-my-site}"
|
||||
|
||||
# Check Node version
|
||||
NODE_VERSION=$(node -v 2>/dev/null | cut -d'v' -f2 | cut -d'.' -f1)
|
||||
if [ -z "$NODE_VERSION" ] || [ "$NODE_VERSION" -lt 18 ]; then
|
||||
echo "❌ Error: Node.js 18+ is required. Current: $(node -v 2>/dev/null || echo 'not installed')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🚀 Creating Next.js project: $PROJECT_NAME"
|
||||
|
||||
# Create Next.js project with all options
|
||||
npx create-next-app@latest "$PROJECT_NAME" \
|
||||
--typescript \
|
||||
--tailwind \
|
||||
--eslint \
|
||||
--app \
|
||||
--src-dir \
|
||||
--import-alias "@/*"
|
||||
|
||||
cd "$PROJECT_NAME"
|
||||
|
||||
# Create .nvmrc for Node version
|
||||
echo "18" > .nvmrc
|
||||
|
||||
echo "📦 Installing additional dependencies..."
|
||||
|
||||
# Install animation library
|
||||
npm install framer-motion
|
||||
|
||||
# Install shadcn/ui
|
||||
echo "📦 Initializing shadcn/ui..."
|
||||
npx shadcn@latest init -y -d
|
||||
|
||||
# Install common components
|
||||
echo "📦 Installing common components..."
|
||||
npx shadcn@latest add button badge card accordion dialog navigation-menu tabs sheet separator avatar alert -y || {
|
||||
echo "⚠️ Warning: Some shadcn components may not have installed. Run 'npx shadcn@latest add [name]' manually."
|
||||
}
|
||||
|
||||
# Install lucide icons
|
||||
npm install lucide-react
|
||||
|
||||
# Create config directory
|
||||
mkdir -p src/config
|
||||
|
||||
# Create site config
|
||||
cat > src/config/site.ts << 'EOF'
|
||||
export const siteConfig = {
|
||||
name: "My Site",
|
||||
tagline: "Build something amazing",
|
||||
description: "A modern website built with Next.js, Tailwind, and shadcn/ui",
|
||||
url: "https://mysite.com",
|
||||
|
||||
nav: {
|
||||
links: [
|
||||
{ label: "Features", href: "#features" },
|
||||
{ label: "Pricing", href: "#pricing" },
|
||||
{ label: "FAQ", href: "#faq" },
|
||||
],
|
||||
cta: { label: "Get Started", href: "/signup" },
|
||||
},
|
||||
|
||||
// Add more sections as needed
|
||||
}
|
||||
|
||||
export type SiteConfig = typeof siteConfig
|
||||
EOF
|
||||
|
||||
# Update globals.css with custom animations
|
||||
cat >> src/app/globals.css << 'EOF'
|
||||
|
||||
/* Custom animations */
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.5s ease-out;
|
||||
}
|
||||
|
||||
.animate-slide-up {
|
||||
animation: slide-up 0.5s ease-out;
|
||||
}
|
||||
|
||||
/* Staggered animations */
|
||||
.stagger-1 { animation-delay: 0.1s; }
|
||||
.stagger-2 { animation-delay: 0.2s; }
|
||||
.stagger-3 { animation-delay: 0.3s; }
|
||||
.stagger-4 { animation-delay: 0.4s; }
|
||||
.stagger-5 { animation-delay: 0.5s; }
|
||||
EOF
|
||||
|
||||
# Create a basic page with animation example
|
||||
cat > src/app/page.tsx << 'EOF'
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { siteConfig } from "@/config/site"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-center p-24">
|
||||
<h1 className="text-5xl font-bold mb-4 animate-slide-up">
|
||||
{siteConfig.name}
|
||||
</h1>
|
||||
<p className="text-xl text-muted-foreground mb-8 animate-slide-up stagger-1">
|
||||
{siteConfig.tagline}
|
||||
</p>
|
||||
<Button size="lg" className="animate-slide-up stagger-2">
|
||||
Get Started
|
||||
</Button>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
echo "✅ Next.js project created successfully!"
|
||||
echo ""
|
||||
echo "Installed:"
|
||||
echo " ✓ Next.js 14+ with App Router"
|
||||
echo " ✓ TypeScript + Tailwind CSS"
|
||||
echo " ✓ shadcn/ui with 10 components"
|
||||
echo " ✓ Framer Motion for animations"
|
||||
echo " ✓ Site config pattern"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " cd $PROJECT_NAME"
|
||||
echo " npm run dev"
|
||||
echo ""
|
||||
echo "Add more components:"
|
||||
echo " npx shadcn@latest add [component-name]"
|
||||
echo " npx shadcn@latest add --all # Install all components"
|
||||
echo ""
|
||||
echo "Deploy to Vercel:"
|
||||
echo " vercel"
|
||||
echo ""
|
||||
357
scripts/init-vite.sh
Normal file
357
scripts/init-vite.sh
Normal file
@@ -0,0 +1,357 @@
|
||||
#!/bin/bash
|
||||
# Initialize a Vite + React + TypeScript + Tailwind + shadcn/ui project
|
||||
# Usage: bash scripts/init-vite.sh <project-name>
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_NAME="${1:-my-site}"
|
||||
|
||||
# Check Node version
|
||||
NODE_VERSION=$(node -v 2>/dev/null | cut -d'v' -f2 | cut -d'.' -f1)
|
||||
if [ -z "$NODE_VERSION" ] || [ "$NODE_VERSION" -lt 18 ]; then
|
||||
echo "❌ Error: Node.js 18+ is required. Current: $(node -v 2>/dev/null || echo 'not installed')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🚀 Creating Vite project: $PROJECT_NAME"
|
||||
|
||||
# Create Vite project
|
||||
npm create vite@latest "$PROJECT_NAME" -- --template react-ts
|
||||
cd "$PROJECT_NAME"
|
||||
|
||||
# Create .nvmrc for Node version
|
||||
echo "18" > .nvmrc
|
||||
|
||||
echo "📦 Installing dependencies..."
|
||||
|
||||
# Install Tailwind CSS
|
||||
npm install -D tailwindcss postcss autoprefixer
|
||||
npx tailwindcss init -p
|
||||
|
||||
# Install animation library
|
||||
npm install framer-motion
|
||||
|
||||
# Install shadcn/ui base dependencies
|
||||
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge
|
||||
npm install lucide-react
|
||||
npm install @radix-ui/react-slot
|
||||
|
||||
echo "⚙️ Configuring Tailwind..."
|
||||
|
||||
# Create tailwind.config.ts
|
||||
cat > tailwind.config.ts << 'EOF'
|
||||
import type { Config } from "tailwindcss"
|
||||
import { fontFamily } from "tailwindcss/defaultTheme"
|
||||
import tailwindcssAnimate from "tailwindcss-animate"
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px",
|
||||
},
|
||||
},
|
||||
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)",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ["var(--font-sans)", ...fontFamily.sans],
|
||||
},
|
||||
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: [tailwindcssAnimate],
|
||||
}
|
||||
|
||||
export default config
|
||||
EOF
|
||||
|
||||
# Create base CSS
|
||||
cat > src/index.css << 'EOF'
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
--ring: 212.7 26.8% 83.9%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create utils
|
||||
mkdir -p src/lib
|
||||
cat > src/lib/utils.ts << 'EOF'
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create components directory
|
||||
mkdir -p src/components/ui
|
||||
|
||||
# Create Button component
|
||||
cat > src/components/ui/button.tsx << 'EOF'
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"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",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
||||
EOF
|
||||
|
||||
# Update vite.config.ts with path aliases
|
||||
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
|
||||
|
||||
# Update tsconfig.json
|
||||
cat > tsconfig.json << 'EOF'
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create components.json for shadcn CLI
|
||||
cat > components.json << 'EOF'
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "default",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "slate",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
echo "📦 Installing shadcn/ui components..."
|
||||
|
||||
# Install common components via shadcn CLI
|
||||
npx shadcn@latest add button badge card accordion dialog navigation-menu tabs sheet separator avatar alert -y || {
|
||||
echo "⚠️ Warning: Some shadcn components may not have installed. Run 'npx shadcn@latest add [name]' manually."
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "✅ Project created successfully!"
|
||||
echo ""
|
||||
echo "Installed:"
|
||||
echo " ✓ React 18 + TypeScript + Vite"
|
||||
echo " ✓ Tailwind CSS with shadcn/ui theming"
|
||||
echo " ✓ Framer Motion for animations"
|
||||
echo " ✓ 10 shadcn/ui components (add more with: npx shadcn@latest add [component])"
|
||||
echo " ✓ Path aliases (@/) configured"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " cd $PROJECT_NAME"
|
||||
echo " npm run dev"
|
||||
echo ""
|
||||
echo "Add more components:"
|
||||
echo " npx shadcn@latest add [component-name]"
|
||||
echo " npx shadcn@latest add --all # Install all components"
|
||||
echo ""
|
||||
echo "Build for production:"
|
||||
echo " npm run build"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user