Skill: wing8169/ui-ux-dev (version 1.0.0)

--- name: ui-designer description: Generate and serve live HTML/CSS/JS UI designs from natural language prompts. Use when the user asks to design, create, build, or prototype a website, landing page, UI, dashboard, web page, or frontend mockup. Also triggers on requests to update, tweak, or iterate on a previously generated design. Replaces traditional UI design + frontend dev workflow. --- # UI Designer Generate production-quality React pages from natural language, serve live, iterate until satisfied. ## Setup Check TOOLS.md for `### UI Designer` config. If missing, run first-time setup: 1. Ask user which port (default: 5174) 2. Run: `bash scripts/setup.sh <port>` 3. Save config to TOOLS.md ## Project Structure ``` <serve_dir>/ ├── project-a/ │ ├── project.json (config: name, preferences, design system, pages) │ ├── assets/ (images, converted to .webp) │ ├── landing/index.html (React page via CDN) │ └── about/index.html ``` ### React Page Template (CDN, no build step) ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Page Title</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> function App() { return <div>...</div>; } ReactDOM.createRoot(document.getElementById('root')).render(<App />); </script> </body> </html> ``` ## Workflow **Critical: Message the user at EVERY action — not just milestones. If you're reading a file, say "Reading project config...". If you're writing HTML, say "Writing bounty page...". If you're taking a screenshot, say "Taking screenshot...". The user should never wonder what you're doing. Treat it like a live build log.** ### Step 1: Project Name Ask: "What's the project name?" - If `<serve_dir>/<project>/` exists: read `project.json`, show current setup and existing pages, ask if amending or adding - If new: create directory + `project.json` - **→ Message user: "Project created / loaded ✓"** ### Step 2: Preferences (new or amending) Ask about design preferences (style, font, colors, brand assets). Save to `project.json`. - **→ Message user: "Preferences saved ✓"** ### Step 3: Page Slug Ask: "What slug for this page?" - Check if exists → ask to overwrite or new - **→ Message user: "Slug confirmed: /<slug> ✓"** ### Step 4: Design Details & Design System Ask about page content + design system (see Design Principles below). Update `project.json` with design system details. - **→ Message user: "Got it, generating now..."** ### Step 5: Generate Generate the React page. Apply Design Principles strictly. - **→ Message user: "HTML generated, running visual review..."** ### Step 6: Screenshot Review Loop ```bash bash scripts/screenshot.sh "http://localhost:<port>/<project>/<slug>/" /tmp/<slug>-review.png 1400 900 ``` Analyze with `image` tool. Fix issues. Re-screenshot. Also check mobile (width=390). - **→ Message user: "Review done, sending preview..."** **Do at least one desktop + one mobile review pass before sharing.** ### Step 7: Share and Iterate Send live URL + screenshot to user. Ask for feedback. Apply changes → re-screenshot → share. Repeat. - **→ Keep user informed at every iteration step** ### Step 8: Media Assets If user provides images: 1. Save to `<project>/assets/` 2. Convert to .webp: `bash scripts/convert-image.sh <input> <output.webp> [quality]` 3. Reference in HTML as `../assets/filename.webp` - **→ Message user: "Image converted: 1.2MB → 340KB (72% smaller) ✓"** ### Step 9: Export Zip the project folder and send: ```bash cd <serve_dir> && zip -r /tmp/<project>.zip <project>/ ``` Send zip via message tool with `filePath`. The CDN-based React pages work standalone — just open `index.html` or serve with any static server. ## Image Handling Convert all user-provided images to `.webp` for performance: ```bash bash scripts/convert-image.sh input.png output.webp 80 ``` - Default quality: 80 (good balance of quality/size) - For hero/banner images: quality 85 - For thumbnails/icons: quality 70 - Always report compression savings to user For placeholder images during prototyping: - Photos: `https://picsum.photos/seed/<name>/<width>/<height>` - Solid placeholders: `https://placehold.co/<width>x<height>/<bg>/<text>` ## Design Principles Apply these consistently to every generated page. These are non-negotiable quality standards. ### Layout & Spacing - **Use consistent spacing scale** — stick to Tailwind's scale (4, 6, 8, 12, 16, 20, 24). Don't mix random values. - **Max content width** — always constrain content (max-w-5xl or max-w-6xl). Never let text run full-width. - **Vertical rhythm** — consistent gaps between sections (py-16 for sections, py-8 for subsections). - **Padding on mobile** — minimum px-4 on all containers. Text must never touch screen edges. ### Typography - **Clear hierarchy** — h1 largest, then h2, h3. Max 3-4 font sizes per page. - **Line length** — max 65-75 characters per line for readability. Use max-w-prose or max-w-2xl on text blocks. - **Font weight contrast** — bold for headings (font-bold/font-semibold), regular for body. - **Text color hierarchy** — white for headings, gray-300 for body, gray-500 for muted/secondary. ### Color & Contrast - **WCAG AA minimum** — text must have 4.5:1 contrast against background. - **Limit palette** — max 1 primary color + 1 accent + neutrals. Don't rainbow. - **Consistent accent usage** — primary color for CTAs, links, active states only. Don't overuse. - **Dark backgrounds** — use layered darkness (bg-900 → bg-800 → bg-700) for depth, not flat black. ### Responsive Design - **Mobile-first** — design for 390px first, enhance for larger screens. - **Breakpoints** — use sm: (640px), md: (768px), lg: (1024px). Test all three. - **Touch targets** — buttons/links min 44x44px on mobile. - **Stack on mobile** — grids collapse to single column. Never horizontal scroll for content. - **Navigation** — hamburger menu on mobile with slide-down panel. Always include. ### Components & Interactions - **Icons** — always use SVG, never emoji (emoji break in headless browsers and render inconsistently). - **Buttons** — clear hover states (color shift + slight scale or shadow). Consistent border-radius. - **Cards** — subtle border (border-white/5 or border-dark-600), slight bg difference from page bg. - **Transitions** — add `transition` class to all interactive elements. Duration 150-200ms. - **Focus states** — all interactive elements must have visible focus rings for accessibility. ### Images & Performance - **All images in .webp** — convert user images with scripts/convert-image.sh. - **Lazy loading** — add `loading="lazy"` to images below the fold. - **Aspect ratios** — use `aspect-video` or `aspect-square` classes to prevent layout shift. - **Alt text** — every image needs descriptive alt text. ### Code Quality - **Semantic HTML** — use header, main, section, footer, nav. Not div soup. - **No Lorem ipsum** — always use contextually relevant placeholder text. - **React components** — break UI into logical components (Navbar, Hero, Features, etc.). - **State management** — use useState for interactive elements (tabs, modals, dropdowns). ### Common Mistakes to Avoid - ❌ Text touching screen edges on mobile - ❌ Emoji for icons (use SVG) - ❌ Flat black backgrounds (use layered darks) - ❌ No hover states on clickable elements - ❌ Inconsistent border-radius across elements - ❌ Giant font sizes that overflow on mobile - ❌ Missing meta viewport tag - ❌ Forgetting hamburger menu on mobile

path: scripts/setup.sh
content: #!/bin/bash
# UI Designer Setup Script
# Usage: bash setup.sh <port> [serve_dir]

PORT="${1:-5174}"
SERVE_DIR="${2:-/var/www/ui-designer}"
HOST_IP=$(hostname -I | awk '{print $1}')

echo "=== UI Designer Setup ==="
echo "Port: $PORT"
echo "Serve directory: $SERVE_DIR"

# Create serve directory
sudo mkdir -p "$SERVE_DIR"
sudo chown "$(whoami):$(whoami)" "$SERVE_DIR"
chmod 755 "$SERVE_DIR"

# Create welcome page
cat > "$SERVE_DIR/index.html" << 'WELCOME'
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>UI Designer — Ready</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
  <style>body { font-family: 'Inter', sans-serif; }</style>
</head>
<body class="bg-gray-950 text-white min-h-screen flex items-center justify-center">
  <div class="text-center space-y-6 p-8">
    <div class="text-6xl">🎨</div>
    <h1 class="text-4xl font-bold bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent">
      UI Designer
    </h1>
    <p class="text-gray-400 text-lg max-w-md mx-auto">
      Your AI-powered design studio is ready. Ask ClawBit to generate a page and it'll appear here.
    </p>
    <div class="flex items-center justify-center gap-2 text-sm text-gray-500">
      <div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
      Server running
    </div>
  </div>
</body>
</html>
WELCOME

# Configure Nginx
NGINX_CONF="/etc/nginx/sites-available/ui-designer"
sudo tee "$NGINX_CONF" > /dev/null << NGINX
server {
    listen $PORT;
    server_name _;
    root $SERVE_DIR;
    index index.html;

    location / {
        try_files \$uri \$uri/ \$uri/index.html =404;
    }

    # Cache static assets
    location ~* \.(css|js|png|jpg|gif|svg|ico|woff2?)$ {
        expires 1h;
        add_header Cache-Control "public, immutable";
    }
}
NGINX

# Enable site
sudo ln -sf "$NGINX_CONF" /etc/nginx/sites-enabled/ui-designer

# Test and reload nginx
sudo nginx -t && sudo systemctl reload nginx

echo ""
echo "=== Setup Complete ==="
echo "UI Designer is live at: http://${HOST_IP}:${PORT}/"
echo "Serve directory: $SERVE_DIR"
echo "Generate pages by asking ClawBit!"


path: scripts/screenshot.sh
content: #!/bin/bash
# Take a screenshot of a URL using headless Chromium
# Usage: bash screenshot.sh <url> <output_path> [width] [height]

URL="${1:?Usage: screenshot.sh <url> <output_path> [width] [height]}"
OUTPUT="${2:?Output path required}"
WIDTH="${3:-1400}"
HEIGHT="${4:-900}"

# Use a temp HTML that loads the target in an iframe after delay,
# or use virtual-time-budget to let JS execute
chromium --headless --disable-gpu --no-sandbox --disable-dev-shm-usage \
  --window-size="${WIDTH},${HEIGHT}" \
  --screenshot="$OUTPUT" \
  --hide-scrollbars \
  --virtual-time-budget=5000 \
  "$URL" 2>/dev/null

if [ -f "$OUTPUT" ]; then
  echo "Screenshot saved to: $OUTPUT"
else
  echo "ERROR: Screenshot failed" >&2
  exit 1
fi


path: scripts/convert-image.sh
content: #!/bin/bash
# Convert any image to compressed .webp format
# Usage: bash convert-image.sh <input> [output] [quality]
# Quality: 0-100 (default: 80)

INPUT="${1:?Usage: convert-image.sh <input> [output] [quality]}"
QUALITY="${3:-80}"

# Derive output name if not provided
if [ -z "$2" ]; then
  OUTPUT="${INPUT%.*}.webp"
else
  OUTPUT="$2"
fi

# Get original file size
ORIG_SIZE=$(stat -f%z "$INPUT" 2>/dev/null || stat -c%s "$INPUT" 2>/dev/null)

# Convert to webp
cwebp -q "$QUALITY" "$INPUT" -o "$OUTPUT" 2>/dev/null

if [ -f "$OUTPUT" ]; then
  NEW_SIZE=$(stat -f%z "$OUTPUT" 2>/dev/null || stat -c%s "$OUTPUT" 2>/dev/null)
  SAVINGS=$(( (ORIG_SIZE - NEW_SIZE) * 100 / ORIG_SIZE ))
  echo "Converted: $INPUT -> $OUTPUT"
  echo "Original: $(numfmt --to=iec $ORIG_SIZE) -> Compressed: $(numfmt --to=iec $NEW_SIZE) (${SAVINGS}% smaller)"
else
  echo "ERROR: Conversion failed" >&2
  exit 1
fi


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)