{
  "schemaVersion": "1.0",
  "item": {
    "slug": "frontend-dev",
    "name": "NextJS Frontend Development + Integration",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/wing8169/frontend-dev",
    "canonicalUrl": "https://clawhub.ai/wing8169/frontend-dev",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/frontend-dev",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=frontend-dev",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md",
      "scripts/screenshot.sh"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "frontend-dev",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-06T03:00:02.960Z",
      "expiresAt": "2026-05-13T03:00:02.960Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=frontend-dev",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=frontend-dev",
        "contentDisposition": "attachment; filename=\"frontend-dev-0.1.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "frontend-dev"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/frontend-dev"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/frontend-dev",
    "agentPageUrl": "https://openagent3.xyz/skills/frontend-dev/agent",
    "manifestUrl": "https://openagent3.xyz/skills/frontend-dev/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/frontend-dev/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "UI Development",
        "body": "Generate production-ready Next.js projects from natural language, with shadcn/ui components, API integration, type safety, and modern tooling."
      },
      {
        "title": "Quick Start (TL;DR)",
        "body": "Fast path for simple projects:\n\nCreate Next.js app → 2. Install shadcn/ui → 3. Build UI → 4. Start with PM2 → 5. Screenshot review → 6. Done\n\nLive preview: Projects run on PM2 (port 3002), accessible at http://localhost:3002 or via nginx proxy if configured.\n\nDefault workflow: All projects use PM2 for dev server management (prevents port conflicts, ensures single instance)."
      },
      {
        "title": "Required Dependencies",
        "body": "Node.js 18+ and npm/yarn/pnpm\nGit (for project initialization)"
      },
      {
        "title": "Optional Features (user can decline)",
        "body": "1. Auto-Revision with Visual Review (requires Chromium)\n\nWhat it does: Takes screenshots during development to visually review designs and auto-fix issues\nInstallation: sudo apt-get install chromium-browser (Debian/Ubuntu)\nPrivileges: Read/write access to project files, execute chromium in headless mode\nIf declined: Manual review only (you describe, user verifies)\n\n2. Live Preview Server (requires Nginx)\n\nWhat it does: Serves project on external port for live preview during development (useful for mobile testing or remote access)\nInstallation: sudo apt-get install nginx\nHow it works: PM2 runs dev server on port 3002, nginx proxies it to chosen external port\nNginx config template:\n# /etc/nginx/sites-available/<project-name>\nserver {\n  listen <external-port>;  # e.g., 3001, 8081, etc.\n  server_name _;\n  \n  location / {\n    proxy_pass http://localhost:3002;  # PM2 dev server\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection 'upgrade';\n    proxy_set_header Host $host;\n    proxy_cache_bypass $http_upgrade;\n  }\n}\n\n\nEnable: sudo ln -s /etc/nginx/sites-available/<project-name> /etc/nginx/sites-enabled/ && sudo systemctl reload nginx\nIf declined: Access directly via http://localhost:3002 (PM2 port)\n\nBefore starting, ask user if they want to enable optional features."
      },
      {
        "title": "Common Project Types",
        "body": "Quick reference for typical requests:\n\nDashboard/Admin Panel → Use (dashboard) route group, shadcn data tables, charts\nLanding Page → Single app/page.tsx, hero section, features grid, testimonials\nTodo/Task App → shadcn checkbox, input, button; local state or API\nBlog/CMS → Dynamic routes app/blog/[slug]/page.tsx, markdown support\nE-commerce → Product catalog, cart state (Zustand), checkout flow\nSaaS App → Auth ((auth) group), protected routes, subscription logic\nPortfolio → Projects grid, contact form, image gallery\nForm-heavy App → React Hook Form + Zod validation, shadcn form components\n\nAsk user: What type of project are you building? (helps determine structure and components)"
      },
      {
        "title": "Tech Stack",
        "body": "Core:\n\nNext.js 14+ (App Router)\nTypeScript\nTailwind CSS v3\nshadcn/ui (recommended UI component library)\nESLint + Prettier\n\nAPI Integration (default):\n\naxios (HTTP client)\n@tanstack/react-query (data fetching, caching, state management)\n\nOptional (based on needs):\n\nZustand (client-side state management)\nZod (runtime validation)\nnext-auth (authentication)\nPrisma (database ORM)"
      },
      {
        "title": "Project Structure",
        "body": "Industry-standard Next.js 14+ App Router structure with feature-based organization:\n\n<project-name>/\n├── app/                                # Next.js 14 App Router\n│   ├── (auth)/                         # Route group (auth pages)\n│   │   ├── login/\n│   │   │   └── page.tsx\n│   │   ├── register/\n│   │   │   └── page.tsx\n│   │   └── layout.tsx                  # Auth-specific layout\n│   ├── (dashboard)/                    # Route group (protected pages)\n│   │   ├── dashboard/\n│   │   │   ├── page.tsx\n│   │   │   └── loading.tsx\n│   │   ├── profile/\n│   │   │   └── page.tsx\n│   │   ├── settings/\n│   │   │   └── page.tsx\n│   │   └── layout.tsx                  # Dashboard layout with sidebar\n│   ├── api/                            # API routes\n│   │   ├── auth/\n│   │   │   └── [...nextauth]/route.ts\n│   │   └── users/\n│   │       └── route.ts\n│   ├── layout.tsx                      # Root layout\n│   ├── page.tsx                        # Home page\n│   ├── loading.tsx                     # Root loading UI\n│   ├── error.tsx                       # Root error boundary\n│   ├── not-found.tsx                   # 404 page\n│   └── providers.tsx                   # Client providers (React Query, etc.)\n│\n├── components/\n│   ├── ui/                             # shadcn/ui components (auto-generated)\n│   │   ├── button.tsx\n│   │   ├── card.tsx\n│   │   ├── input.tsx\n│   │   ├── form.tsx\n│   │   └── ...\n│   ├── layout/                         # Layout components\n│   │   ├── header.tsx\n│   │   ├── footer.tsx\n│   │   ├── sidebar.tsx\n│   │   └── mobile-nav.tsx\n│   ├── features/                       # Feature-specific components\n│   │   ├── auth/\n│   │   │   ├── login-form.tsx\n│   │   │   └── register-form.tsx\n│   │   ├── dashboard/\n│   │   │   ├── stats-card.tsx\n│   │   │   └── recent-activity.tsx\n│   │   └── profile/\n│   │       ├── profile-header.tsx\n│   │       └── edit-profile-form.tsx\n│   └── shared/                         # Shared/common components\n│       ├── data-table.tsx\n│       ├── search-bar.tsx\n│       └── pagination.tsx\n│\n├── lib/                                # Utility functions & configurations\n│   ├── api.ts                          # Axios instance + interceptors\n│   ├── react-query.ts                  # React Query client config\n│   ├── utils.ts                        # Utility functions (cn, formatters)\n│   ├── validations.ts                  # Zod schemas\n│   ├── constants.ts                    # App constants\n│   └── auth.ts                         # Auth utilities (if using next-auth)\n│\n├── hooks/                              # Custom React hooks\n│   ├── use-auth.ts                     # Authentication hook\n│   ├── use-user.ts                     # User data hook (React Query)\n│   ├── use-posts.ts                    # Posts data hook (React Query)\n│   ├── use-media-query.ts              # Responsive design hook\n│   └── use-toast.ts                    # Toast notifications (shadcn)\n│\n├── types/                              # TypeScript type definitions\n│   ├── index.ts                        # Common types\n│   ├── api.ts                          # API response types\n│   ├── user.ts                         # User-related types\n│   └── database.ts                     # Database types (Prisma generated)\n│\n├── actions/                            # Server Actions (Next.js 14+)\n│   ├── auth.ts                         # Auth actions\n│   ├── user.ts                         # User actions\n│   └── posts.ts                        # Posts actions\n│\n├── config/                             # Configuration files\n│   ├── site.ts                         # Site metadata (name, description, etc.)\n│   └── navigation.ts                   # Navigation menu config\n│\n├── prisma/                             # Prisma ORM (if using database)\n│   ├── schema.prisma                   # Database schema\n│   └── migrations/                     # Database migrations\n│\n├── public/                             # Static assets\n│   ├── images/\n│   ├── icons/\n│   └── fonts/\n│\n├── styles/                             # Global styles\n│   └── globals.css                     # Tailwind imports + custom styles\n│\n├── .env.local                          # Environment variables (gitignored)\n├── .env.example                        # Environment variables template\n├── .eslintrc.json                      # ESLint config\n├── .prettierrc                         # Prettier config\n├── components.json                     # shadcn/ui config\n├── next.config.js                      # Next.js config\n├── tailwind.config.ts                  # Tailwind config\n├── tsconfig.json                       # TypeScript config\n├── package.json                        # Dependencies\n└── README.md                           # Project documentation"
      },
      {
        "title": "Directory Purpose",
        "body": "app/ - Next.js 14 App Router pages and layouts. Use route groups (name) for logical grouping without affecting URLs.\n\ncomponents/ - All React components, organized by type:\n\nui/ - shadcn/ui components (copy-paste, customizable)\nlayout/ - Shared layout components (header, footer, sidebar)\nfeatures/ - Feature-specific components (scoped to one feature)\nshared/ - Reusable components used across features\n\nlib/ - Utility functions, configurations, and third-party library setups.\n\nhooks/ - Custom React hooks, especially React Query hooks for API calls.\n\ntypes/ - TypeScript type definitions and interfaces.\n\nactions/ - Server Actions for form handling and server-side operations (Next.js 14+).\n\nconfig/ - App configuration (site metadata, navigation menus, constants).\n\nprisma/ - Database schema and migrations (if using Prisma).\n\npublic/ - Static files served at root URL.\n\nstyles/ - Global CSS (Tailwind imports + custom styles)."
      },
      {
        "title": "Workflow",
        "body": "Keep user informed at every step — this is a live build log.\n\n⚠️ Important: All projects use PM2 for dev server management (port 3002 by default). This ensures:\n\nOnly one instance runs at a time (no port conflicts)\nEasy process management (list/logs/restart/stop)\nPersistent dev server across terminal sessions\nBetter error logging and debugging"
      },
      {
        "title": "Step 1: Project Setup",
        "body": "Ask:\n\nProject name\nDescription/purpose\nOptional features (chromium review, nginx preview)\n\nCreate Next.js project:\n\nnpx create-next-app@latest <project-name> \\\n  --typescript \\\n  --tailwind \\\n  --app \\\n  --no-src-dir \\\n  --import-alias \"@/*\"\n\n→ Message user: \"Next.js project initialized ✓\""
      },
      {
        "title": "Step 2: Create Directory Structure",
        "body": "Create all necessary directories following industry best practices:\n\ncd <project-name>\n\n# Create app route groups\nmkdir -p app/\\(auth\\)/login app/\\(auth\\)/register\nmkdir -p app/\\(dashboard\\)/dashboard app/\\(dashboard\\)/profile app/\\(dashboard\\)/settings\nmkdir -p app/api/auth app/api/users\n\n# Create component directories\nmkdir -p components/ui components/layout components/features components/shared\nmkdir -p components/features/auth components/features/dashboard components/features/profile\n\n# Create utility directories\nmkdir -p lib hooks types actions config\n\n# Create static asset directories\nmkdir -p public/images public/icons public/fonts\n\n# Create styles directory\nmkdir styles\n\n# Create Prisma directory (if using database)\n# mkdir -p prisma\n\nCreate essential config files:\n\nconfig/site.ts - Site metadata\n\nexport const siteConfig = {\n  name: '<Project Name>',\n  description: '<Project Description>',\n  url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',\n  links: {\n    github: 'https://github.com/...',\n  },\n};\n\nconfig/navigation.ts - Navigation menu\n\nexport const mainNav = [\n  { title: 'Home', href: '/' },\n  { title: 'Dashboard', href: '/dashboard' },\n  { title: 'Profile', href: '/profile' },\n];\n\nexport const dashboardNav = [\n  { title: 'Overview', href: '/dashboard' },\n  { title: 'Profile', href: '/profile' },\n  { title: 'Settings', href: '/settings' },\n];\n\n.env.example - Environment variables template\n\nNEXT_PUBLIC_APP_URL=http://localhost:3000\nNEXT_PUBLIC_API_BASE_URL=http://localhost:3000/api\nDATABASE_URL=postgresql://...\nNEXTAUTH_SECRET=...\nNEXTAUTH_URL=http://localhost:3000\n\n→ Message user: \"Directory structure created ✓\""
      },
      {
        "title": "Step 3: Install Dependencies",
        "body": "Core dependencies:\n\ncd <project-name>\nnpm install axios @tanstack/react-query\nnpm install -D @types/node\n\nshadcn/ui setup (recommended):\n\nnpx shadcn-ui@latest init\n\nThis will prompt for configuration. Recommended answers:\n\nStyle: Default\nBase color: Slate\nCSS variables: Yes\n\nInstall essential shadcn components:\n\nnpx shadcn-ui@latest add button card input label select textarea\nnpx shadcn-ui@latest add dropdown-menu dialog sheet tabs\nnpx shadcn-ui@latest add table form avatar badge separator toast\n\nInstall form dependencies (for shadcn/ui forms):\n\nnpm install react-hook-form @hookform/resolvers zod\n\nOptional (ask user based on needs):\n\nnpm install zustand  # State management\nnpm install next-auth  # Authentication\nnpm install prisma @prisma/client  # Database ORM\n\n→ Message user: \"Dependencies + shadcn/ui installed ✓\""
      },
      {
        "title": "Step 4: Configure Base Files",
        "body": "lib/api.ts (axios instance)\n\nimport axios from 'axios';\n\nexport const api = axios.create({\n  baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000/api',\n  timeout: 10000,\n  headers: { 'Content-Type': 'application/json' }\n});\n\n// Request interceptor (add auth tokens, etc.)\napi.interceptors.request.use(\n  (config) => {\n    const token = localStorage.getItem('token');\n    if (token) config.headers.Authorization = `Bearer ${token}`;\n    return config;\n  },\n  (error) => Promise.reject(error)\n);\n\n// Response interceptor (handle errors globally)\napi.interceptors.response.use(\n  (response) => response,\n  (error) => {\n    if (error.response?.status === 401) {\n      // Handle unauthorized\n    }\n    return Promise.reject(error);\n  }\n);\n\nlib/react-query.ts (query client)\n\nimport { QueryClient } from '@tanstack/react-query';\n\nexport const queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: 60 * 1000, // 1 minute\n      refetchOnWindowFocus: false,\n      retry: 1,\n    },\n  },\n});\n\napp/providers.tsx (wrap app with providers)\n\n'use client';\n\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools';\nimport { queryClient } from '@/lib/react-query';\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n  return (\n    <QueryClientProvider client={queryClient}>\n      {children}\n      <ReactQueryDevtools initialIsOpen={false} />\n    </QueryClientProvider>\n  );\n}\n\nUpdate app/layout.tsx to use Providers.\n\n→ Message user: \"Base configuration complete ✓\""
      },
      {
        "title": "Step 5: Generate Features",
        "body": "Ask what features/pages to build. For each feature:\n\nCreate route (app/<feature>/page.tsx)\nCreate components (components/features/<feature>/)\nCreate API hooks (hooks/use<Feature>.ts) using react-query\nCreate types (types/<feature>.ts)\nOptionally create API routes (app/api/<feature>/route.ts)\n\nExample: User Profile Feature\n\n// types/user.ts\nexport interface User {\n  id: string;\n  name: string;\n  email: string;\n}\n\n// hooks/useUser.ts\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { api } from '@/lib/api';\nimport type { User } from '@/types/user';\n\nexport const useUser = (id: string) => {\n  return useQuery({\n    queryKey: ['user', id],\n    queryFn: async () => {\n      const { data } = await api.get<User>(`/users/${id}`);\n      return data;\n    },\n  });\n};\n\nexport const useUpdateUser = () => {\n  const queryClient = useQueryClient();\n  \n  return useMutation({\n    mutationFn: async (user: Partial<User>) => {\n      const { data } = await api.patch<User>(`/users/${user.id}`, user);\n      return data;\n    },\n    onSuccess: (data) => {\n      queryClient.invalidateQueries({ queryKey: ['user', data.id] });\n    },\n  });\n};\n\n// app/profile/[id]/page.tsx\n'use client';\n\nimport { useUser, useUpdateUser } from '@/hooks/useUser';\n\nexport default function ProfilePage({ params }: { params: { id: string } }) {\n  const { data: user, isLoading, error } = useUser(params.id);\n  const updateUser = useUpdateUser();\n\n  if (isLoading) return <div>Loading...</div>;\n  if (error) return <div>Error: {error.message}</div>;\n\n  return (\n    <div>\n      <h1>{user?.name}</h1>\n      <p>{user?.email}</p>\n    </div>\n  );\n}\n\n→ Message user after each feature: \"Profile page complete ✓\""
      },
      {
        "title": "Step 6: Build UI with shadcn/ui Components",
        "body": "Use shadcn/ui components (already installed) for consistent, accessible UI. Apply Design Principles (see below).\n\nExample: Profile page with shadcn/ui\n\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { Button } from '@/components/ui/button';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\n\nexport default function ProfilePage({ params }: { params: { id: string } }) {\n  const { data: user, isLoading } = useUser(params.id);\n\n  if (isLoading) return <Card className=\"w-full max-w-2xl mx-auto\"><CardContent>Loading...</CardContent></Card>;\n\n  return (\n    <Card className=\"w-full max-w-2xl mx-auto\">\n      <CardHeader>\n        <div className=\"flex items-center gap-4\">\n          <Avatar className=\"h-20 w-20\">\n            <AvatarImage src={user?.avatar} />\n            <AvatarFallback>{user?.name[0]}</AvatarFallback>\n          </Avatar>\n          <div>\n            <CardTitle>{user?.name}</CardTitle>\n            <p className=\"text-sm text-muted-foreground\">{user?.email}</p>\n          </div>\n        </div>\n      </CardHeader>\n      <CardContent>\n        <Button>Edit Profile</Button>\n      </CardContent>\n    </Card>\n  );\n}\n\nWhen to add more components:\n\nForms → npx shadcn-ui@latest add form input label\nData tables → npx shadcn-ui@latest add table\nNavigation → npx shadcn-ui@latest add navigation-menu\nFeedback → npx shadcn-ui@latest add toast alert\n\n→ Message user: \"UI built with shadcn/ui ✓\""
      },
      {
        "title": "Step 7: Visual Review (if chromium enabled)",
        "body": "Important: Use PM2 to manage the dev server (ensures only 1 instance runs, prevents port conflicts).\n\nStart dev server with PM2:\n\n# Stop any existing instance of this project\npm2 delete <project-name> 2>/dev/null || true\n\n# Start with PM2 (port 3002 for nginx proxy)\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\n# Give PM2 a moment to start\nsleep 2\n\nWait for server to be fully ready (critical - avoid white screen screenshots):\n\n# Wait for \"Ready in\" message in PM2 logs (usually 5-15 seconds)\ntimeout=30\nelapsed=0\nwhile [ $elapsed -lt $timeout ]; do\n  if pm2 logs <project-name> --nostream --lines 50 2>/dev/null | grep -q \"Ready in\"; then\n    echo \"Server ready!\"\n    sleep 3  # Extra buffer for module loading\n    break\n  fi\n  sleep 1\n  elapsed=$((elapsed + 1))\ndone\n\n# Verify server is responding\nif ! curl -s http://localhost:3002 > /dev/null; then\n  echo \"Warning: Server not responding on port 3002\"\n  pm2 logs <project-name> --nostream --lines 20\nfi\n\nTake screenshots (requires chromium):\n\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/review-desktop.png 1400 900\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/review-mobile.png 390 844\n\nReview Checklist (analyze with image tool):\n\n✅ Desktop (1400px): Content centered, proper spacing\n✅ Mobile (390px):\n\nNo horizontal overflow (content fits within screen)\nText readable (not too small)\nPadding appropriate (p-4 not p-24)\nTouch targets large enough (min 44x44px)\nNo content cutting off edges\n\nIf issues found: Fix responsive classes, re-run screenshots.\n\nCommon fixes:\n\nLarge padding → p-4 md:p-8 lg:p-12\nLarge text → text-2xl md:text-4xl\nWide content → Add max-w-full or px-4\n\n→ Message user: \"Review complete, sending preview...\""
      },
      {
        "title": "Step 8: Environment Setup",
        "body": "Create .env.local:\n\nNEXT_PUBLIC_API_BASE_URL=https://api.example.com\nDATABASE_URL=postgresql://...\nNEXTAUTH_SECRET=...\n\nCreate .env.example (template for user).\n\n→ Message user: \"Environment template created ✓\""
      },
      {
        "title": "Step 9: Scripts & Documentation",
        "body": "Update package.json scripts:\n\n{\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"next lint\",\n    \"type-check\": \"tsc --noEmit\"\n  }\n}\n\nCreate README.md with:\n\nSetup instructions\nEnvironment variables needed\nDevelopment commands\nAPI integration guide\n\n→ Message user: \"Documentation complete ✓\""
      },
      {
        "title": "Step 10: Export & Deploy Guidance",
        "body": "Stop PM2 dev server (if running):\n\npm2 delete <project-name> 2>/dev/null || true\npm2 save  # Persist PM2 process list\n\nZip the project:\n\ncd .. && zip -r /tmp/<project-name>.zip <project-name>/\n\nSend via message tool with filePath.\n\nProvide deployment options:\n\nVercel (recommended): npx vercel\nNetlify: npm run build && netlify deploy\nDocker: Provide Dockerfile\nSelf-hosted: Provide systemd service + nginx config\n\n→ Message user: \"Project ready! 🚀\""
      },
      {
        "title": "Quick Test (during development)",
        "body": "1. PM2 dev server (always running after Step 7):\n\n# Check status\npm2 list\n\n# View logs\npm2 logs <project-name>\n\n# Access locally\ncurl http://localhost:3002\n\n2. Live preview URLs:\n\nLocal access: http://localhost:3002\nNginx proxy (if configured): http://<server-ip>:<external-port>\nMobile testing: Use nginx proxy or ngrok/tunneling service\n\n3. Screenshot review (if chromium enabled):\n\n# Desktop (1400x900)\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/desktop.png 1400 900\n\n# Mobile (390x844)\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/mobile.png 390 844"
      },
      {
        "title": "End-to-End Testing Workflow",
        "body": "Full test sequence:\n\n# 1. Check PM2 status\npm2 list | grep <project-name>\n\n# 2. Verify dev server responding\ncurl -I http://localhost:3002\n\n# 3. Take screenshots for visual verification\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/test-desktop.png 1400 900\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/test-mobile.png 390 844\n\n# 4. Check logs for errors\npm2 logs <project-name> --lines 50 | grep -i error\n\n# 5. Test API endpoints (if using API routes)\ncurl http://localhost:3002/api/health  # Example health check\n\n# 6. Production build test\nnpm run build && npm run start  # Test production build\n\n# 7. Type check\nnpm run type-check"
      },
      {
        "title": "Common Testing Scenarios",
        "body": "Scenario 1: Test responsive design\n\n# Mobile, tablet, desktop\nfor width in 390 768 1400; do\n  bash scripts/screenshot.sh \"http://localhost:3002\" /tmp/screen-${width}.png $width 900\ndone\n\nScenario 2: Test specific page/route\n\n# Take screenshot of specific route\nbash scripts/screenshot.sh \"http://localhost:3002/dashboard\" /tmp/dashboard.png 1400 900\n\nScenario 3: Test after making changes\n\n# PM2 auto-reloads on file changes, verify in logs\npm2 logs <project-name> --lines 20\n\n# Wait for \"compiled successfully\" then take new screenshot\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/updated.png 1400 900"
      },
      {
        "title": "Sharing Preview with User",
        "body": "Option 1: Screenshots\n\nSend desktop + mobile screenshots via message tool\nUser provides feedback, you iterate\n\nOption 2: Nginx proxy + external access\n\nSet up nginx config (see Optional Features)\nShare URL: http://<server-ip>:<port>\nUser can test live in browser\n\nOption 3: Export & deploy\n\nZip project and send to user\nUser deploys to Vercel/Netlify\nTest on production URL"
      },
      {
        "title": "Pattern 1: REST API (default)",
        "body": "Use axios + react-query:\n\n// hooks/usePosts.ts\nimport { useQuery, useMutation } from '@tanstack/react-query';\nimport { api } from '@/lib/api';\n\nexport const usePosts = () => {\n  return useQuery({\n    queryKey: ['posts'],\n    queryFn: async () => {\n      const { data } = await api.get('/posts');\n      return data;\n    },\n  });\n};\n\nexport const useCreatePost = () => {\n  return useMutation({\n    mutationFn: async (post: { title: string; body: string }) => {\n      const { data } = await api.post('/posts', post);\n      return data;\n    },\n  });\n};"
      },
      {
        "title": "Pattern 2: GraphQL (optional)",
        "body": "Install:\n\nnpm install @apollo/client graphql\n\nSetup Apollo Client, use useQuery and useMutation from Apollo."
      },
      {
        "title": "Pattern 3: tRPC (optional)",
        "body": "For Next.js API routes with type safety:\n\nnpm install @trpc/server @trpc/client @trpc/react-query @trpc/next"
      },
      {
        "title": "Pattern 4: Server Actions (Next.js 14+)",
        "body": "For form handling without API routes:\n\n// app/actions.ts\n'use server';\n\nexport async function createPost(formData: FormData) {\n  const title = formData.get('title');\n  // ...\n}\n\nAlways ask user which pattern they prefer for their use case."
      },
      {
        "title": "Design Principles",
        "body": "Apply these consistently. These are quality standards."
      },
      {
        "title": "Layout & Spacing",
        "body": "Consistent Tailwind spacing scale (4, 6, 8, 12, 16, 20, 24)\nMax content width: max-w-5xl or max-w-6xl\nVertical rhythm: py-16 for sections, py-8 for subsections\nMobile: minimum px-4 padding"
      },
      {
        "title": "Typography",
        "body": "Clear hierarchy (h1 → h2 → h3, max 3-4 sizes)\nLine length: max 65-75 characters (max-w-prose)\nFont weight contrast (bold headings, regular body)\nText color hierarchy (slate-900 → slate-700 → slate-500)"
      },
      {
        "title": "Color & Contrast",
        "body": "WCAG AA minimum (4.5:1 contrast)\nLimit palette (1 primary + 1 accent + neutrals)\nConsistent accent usage (CTAs, links, active states)"
      },
      {
        "title": "Responsive Design (Critical)",
        "body": "Mobile-first (390px → 768px → 1024px) - Always design for 390px first\nResponsive padding - Use Tailwind responsive classes:\n\nMobile: p-4 or px-4 py-6 (never p-24 on mobile!)\nTablet: md:p-8 or md:px-6 md:py-8\nDesktop: lg:p-12 xl:p-24\nExample: <main className=\"p-4 md:p-8 lg:p-12\">\n\n\nResponsive text sizes - Scale down headings on mobile:\n\nMobile: text-2xl → Desktop: md:text-4xl\nMobile: text-lg → Desktop: md:text-2xl\n\n\nNo horizontal overflow - Content must fit within 390px width\n\nTest: Check mobile screenshot for any content cutting off edges\nUse max-w-full on containers\nBreak long words: break-words\n\n\nTouch targets - min 44x44px for buttons/links on mobile\nStack on mobile - Grids collapse to single column: grid-cols-1 md:grid-cols-2 lg:grid-cols-3\nHamburger menu - Required on mobile for navigation"
      },
      {
        "title": "Components (Use shadcn/ui)",
        "body": "Icons: Use Lucide React (comes with shadcn/ui), never emoji\nButtons: Use <Button> component with variants (default, destructive, outline, ghost)\nForms: Use shadcn <Form> with react-hook-form integration\nCards: Use <Card> component for content sections\nDialogs/Modals: Use <Dialog> or <Sheet> components\nLoading states: Use shadcn <Skeleton> component for loading UI\nError handling: Use <Alert> component for error messages\nData display: Use <Table> component for tabular data\n\nshadcn/ui benefits: Accessible, customizable, copy-paste friendly, works with Tailwind"
      },
      {
        "title": "TypeScript Best Practices",
        "body": "Strict mode enabled\nExplicit return types for functions\nInterface over type for objects\nAvoid any (use unknown if needed)\nUse discriminated unions for variants"
      },
      {
        "title": "Performance",
        "body": "Use Next.js Image component (next/image)\nLazy load below-the-fold content\nCode splitting (dynamic imports)\nMemoize expensive computations (useMemo, useCallback)"
      },
      {
        "title": "Form Handling (with shadcn/ui)",
        "body": "'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useForm } from 'react-hook-form';\nimport * as z from 'zod';\nimport { useMutation } from '@tanstack/react-query';\nimport { Button } from '@/components/ui/button';\nimport { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';\nimport { Input } from '@/components/ui/input';\nimport { useToast } from '@/components/ui/use-toast';\n\nconst formSchema = z.object({\n  name: z.string().min(2, 'Name must be at least 2 characters'),\n  email: z.string().email('Invalid email address'),\n});\n\nexport default function ContactForm() {\n  const { toast } = useToast();\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: { name: '', email: '' },\n  });\n\n  const mutation = useMutation({\n    mutationFn: async (data: z.infer<typeof formSchema>) => {\n      const res = await api.post('/contact', data);\n      return res.data;\n    },\n    onSuccess: () => {\n      toast({ title: 'Success', description: 'Message sent!' });\n      form.reset();\n    },\n    onError: (error) => {\n      toast({ title: 'Error', description: error.message, variant: 'destructive' });\n    },\n  });\n\n  return (\n    <Form {...form}>\n      <form onSubmit={form.handleSubmit((data) => mutation.mutate(data))} className=\"space-y-4\">\n        <FormField\n          control={form.control}\n          name=\"name\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Name</FormLabel>\n              <FormControl>\n                <Input placeholder=\"John Doe\" {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name=\"email\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <FormControl>\n                <Input type=\"email\" placeholder=\"john@example.com\" {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button type=\"submit\" disabled={mutation.isPending}>\n          {mutation.isPending ? 'Sending...' : 'Send Message'}\n        </Button>\n      </form>\n    </Form>\n  );\n}\n\nNote: Run npx shadcn-ui@latest add form toast and install npm install react-hook-form @hookform/resolvers zod for this pattern."
      },
      {
        "title": "Pagination",
        "body": "const usePaginatedPosts = (page: number) => {\n  return useQuery({\n    queryKey: ['posts', page],\n    queryFn: async () => {\n      const { data } = await api.get(`/posts?page=${page}`);\n      return data;\n    },\n    keepPreviousData: true, // Smooth transitions\n  });\n};"
      },
      {
        "title": "Infinite Scroll",
        "body": "import { useInfiniteQuery } from '@tanstack/react-query';\n\nconst useInfinitePosts = () => {\n  return useInfiniteQuery({\n    queryKey: ['posts'],\n    queryFn: async ({ pageParam = 1 }) => {\n      const { data } = await api.get(`/posts?page=${pageParam}`);\n      return data;\n    },\n    getNextPageParam: (lastPage, pages) => lastPage.nextPage,\n  });\n};"
      },
      {
        "title": "Common Mistakes to Avoid",
        "body": "❌ Not wrapping app with QueryClientProvider\n❌ Using axios without interceptors (no error handling)\n❌ Forgetting loading/error states in components\n❌ Not invalidating queries after mutations\n❌ Using any instead of proper TypeScript types\n❌ Client components when server components would work\n❌ Not using Next.js Image component (performance loss)\n❌ Missing error boundaries\n❌ Hardcoding API URLs (use env vars)\n❌ No mobile testing (always check responsive at 390px width)\n❌ Large padding on mobile (p-24 = 96px causes overflow on 390px screens)\n❌ Not using responsive Tailwind classes (use p-4 md:p-8 lg:p-12)\n❌ Horizontal overflow on mobile (content wider than 390px)\n❌ Building custom components when shadcn/ui has them (Button, Card, Dialog, etc.)\n❌ Using emoji for icons (use Lucide React icons from shadcn/ui)\n❌ Not installing @hookform/resolvers and zod before using shadcn forms\n❌ Forgetting to add <Toaster /> component when using toast notifications\n❌ Taking screenshots before dev server is fully ready (causes white screens)\n❌ Not waiting for module loading (causes \"Module not found\" errors in screenshots)"
      },
      {
        "title": "White Screen Screenshots",
        "body": "Problem: Screenshots show blank white page\nCause: Dev server not fully initialized before screenshot\nSolution:\n\nWait for \"Ready in\" message in dev server logs\nAdd 3-5 second buffer after \"Ready\" message\nVerify localhost:3000 loads in browser before taking screenshot"
      },
      {
        "title": "Module Not Found Errors",
        "body": "Problem: React error \"Module not found: Can't resolve @tanstack/react-query\"\nCause: Dev server started before all packages loaded\nSolution:\n\nRestart dev server: pkill -f \"next dev\" && npm run dev\nVerify packages in node_modules: ls node_modules/@tanstack/\nWait 10-15 seconds after npm install before starting dev server"
      },
      {
        "title": "Dev Server Won't Start",
        "body": "Problem: Port already in use (EADDRINUSE error)\nSolution (PM2 method):\n\n# Check what's running\npm2 list\n\n# Stop the conflicting process\npm2 delete <project-name>\n\n# Or check port directly\nlsof -ti:3002\n\n# Kill process on port (if not PM2-managed)\nkill -9 $(lsof -ti:3002)\n\n# Restart with PM2\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev"
      },
      {
        "title": "PM2 Process Management",
        "body": "List all PM2 processes:\n\npm2 list\n\nCheck logs:\n\npm2 logs <project-name> --lines 50\n\nRestart a process:\n\npm2 restart <project-name>\n\nStop a process:\n\npm2 stop <project-name>\n\nDelete a process:\n\npm2 delete <project-name>\n\nEnsure only one instance runs:\n\n# Always delete before starting\npm2 delete <project-name> 2>/dev/null || true\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\nCommon PM2 scenarios:\n\nProject won't start → Check logs: pm2 logs <project-name>\nProcess keeps restarting → Module missing or port conflict, check logs\nChanges not reflecting → PM2 auto-reloads, verify in logs: pm2 logs <project-name> | grep compiled\nMultiple instances running → Delete all: pm2 delete all && pm2 list\nCheck resource usage → pm2 monit (real-time monitoring)\nSave PM2 process list → pm2 save (persists across reboots)"
      },
      {
        "title": "Iteration & Updates",
        "body": "When user requests changes:\n\nIdentify affected files\nMake changes\nPM2 auto-reloads (no manual restart needed for file changes)\nRun type check: npm run type-check\nVerify in logs: pm2 logs <project-name> --lines 20\nIf chromium enabled: take new screenshot\nReport changes to user\n\nAlways explain what changed and why."
      },
      {
        "title": "Essential Commands",
        "body": "# Start dev server\npm2 delete <project-name> 2>/dev/null || true\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\n# Check status\npm2 list\npm2 logs <project-name>\n\n# Take screenshots\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/desktop.png 1400 900\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/mobile.png 390 844\n\n# Test production build\nnpm run build && npm run start\n\n# Type check\nnpm run type-check"
      },
      {
        "title": "File Locations",
        "body": "Components: components/ui/ (shadcn), components/features/ (custom)\nPages: app/*/page.tsx\nAPI routes: app/api/*/route.ts\nStyles: app/globals.css, tailwind.config.ts\nConfig: next.config.ts, .env.local"
      },
      {
        "title": "Common shadcn Components",
        "body": "npx shadcn-ui@latest add button input form card table dialog toast"
      },
      {
        "title": "Live Preview URLs",
        "body": "Local: http://localhost:3002\nNginx proxy: http://<server-ip>:<external-port>\nMobile testing: Use nginx proxy or ngrok"
      },
      {
        "title": "Troubleshooting",
        "body": "Port conflict → pm2 delete <name> then restart\nWhite screen → Wait for \"Ready in\" message (check logs)\nModule errors → npm install then restart PM2\nType errors → npm run type-check\nLayout breaks → Check responsive classes (p-4 md:p-8 lg:p-12)"
      }
    ],
    "body": "UI Development\n\nGenerate production-ready Next.js projects from natural language, with shadcn/ui components, API integration, type safety, and modern tooling.\n\nQuick Start (TL;DR)\n\nFast path for simple projects:\n\nCreate Next.js app → 2. Install shadcn/ui → 3. Build UI → 4. Start with PM2 → 5. Screenshot review → 6. Done\n\nLive preview: Projects run on PM2 (port 3002), accessible at http://localhost:3002 or via nginx proxy if configured.\n\nDefault workflow: All projects use PM2 for dev server management (prevents port conflicts, ensures single instance).\n\nRequirements & Optional Features\nRequired Dependencies\nNode.js 18+ and npm/yarn/pnpm\nGit (for project initialization)\nOptional Features (user can decline)\n1. Auto-Revision with Visual Review (requires Chromium)\nWhat it does: Takes screenshots during development to visually review designs and auto-fix issues\nInstallation: sudo apt-get install chromium-browser (Debian/Ubuntu)\nPrivileges: Read/write access to project files, execute chromium in headless mode\nIf declined: Manual review only (you describe, user verifies)\n2. Live Preview Server (requires Nginx)\nWhat it does: Serves project on external port for live preview during development (useful for mobile testing or remote access)\nInstallation: sudo apt-get install nginx\nHow it works: PM2 runs dev server on port 3002, nginx proxies it to chosen external port\nNginx config template:\n# /etc/nginx/sites-available/<project-name>\nserver {\n  listen <external-port>;  # e.g., 3001, 8081, etc.\n  server_name _;\n  \n  location / {\n    proxy_pass http://localhost:3002;  # PM2 dev server\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection 'upgrade';\n    proxy_set_header Host $host;\n    proxy_cache_bypass $http_upgrade;\n  }\n}\n\nEnable: sudo ln -s /etc/nginx/sites-available/<project-name> /etc/nginx/sites-enabled/ && sudo systemctl reload nginx\nIf declined: Access directly via http://localhost:3002 (PM2 port)\n\nBefore starting, ask user if they want to enable optional features.\n\nCommon Project Types\n\nQuick reference for typical requests:\n\nDashboard/Admin Panel → Use (dashboard) route group, shadcn data tables, charts\nLanding Page → Single app/page.tsx, hero section, features grid, testimonials\nTodo/Task App → shadcn checkbox, input, button; local state or API\nBlog/CMS → Dynamic routes app/blog/[slug]/page.tsx, markdown support\nE-commerce → Product catalog, cart state (Zustand), checkout flow\nSaaS App → Auth ((auth) group), protected routes, subscription logic\nPortfolio → Projects grid, contact form, image gallery\nForm-heavy App → React Hook Form + Zod validation, shadcn form components\n\nAsk user: What type of project are you building? (helps determine structure and components)\n\nTech Stack\n\nCore:\n\nNext.js 14+ (App Router)\nTypeScript\nTailwind CSS v3\nshadcn/ui (recommended UI component library)\nESLint + Prettier\n\nAPI Integration (default):\n\naxios (HTTP client)\n@tanstack/react-query (data fetching, caching, state management)\n\nOptional (based on needs):\n\nZustand (client-side state management)\nZod (runtime validation)\nnext-auth (authentication)\nPrisma (database ORM)\nProject Structure\n\nIndustry-standard Next.js 14+ App Router structure with feature-based organization:\n\n<project-name>/\n├── app/                                # Next.js 14 App Router\n│   ├── (auth)/                         # Route group (auth pages)\n│   │   ├── login/\n│   │   │   └── page.tsx\n│   │   ├── register/\n│   │   │   └── page.tsx\n│   │   └── layout.tsx                  # Auth-specific layout\n│   ├── (dashboard)/                    # Route group (protected pages)\n│   │   ├── dashboard/\n│   │   │   ├── page.tsx\n│   │   │   └── loading.tsx\n│   │   ├── profile/\n│   │   │   └── page.tsx\n│   │   ├── settings/\n│   │   │   └── page.tsx\n│   │   └── layout.tsx                  # Dashboard layout with sidebar\n│   ├── api/                            # API routes\n│   │   ├── auth/\n│   │   │   └── [...nextauth]/route.ts\n│   │   └── users/\n│   │       └── route.ts\n│   ├── layout.tsx                      # Root layout\n│   ├── page.tsx                        # Home page\n│   ├── loading.tsx                     # Root loading UI\n│   ├── error.tsx                       # Root error boundary\n│   ├── not-found.tsx                   # 404 page\n│   └── providers.tsx                   # Client providers (React Query, etc.)\n│\n├── components/\n│   ├── ui/                             # shadcn/ui components (auto-generated)\n│   │   ├── button.tsx\n│   │   ├── card.tsx\n│   │   ├── input.tsx\n│   │   ├── form.tsx\n│   │   └── ...\n│   ├── layout/                         # Layout components\n│   │   ├── header.tsx\n│   │   ├── footer.tsx\n│   │   ├── sidebar.tsx\n│   │   └── mobile-nav.tsx\n│   ├── features/                       # Feature-specific components\n│   │   ├── auth/\n│   │   │   ├── login-form.tsx\n│   │   │   └── register-form.tsx\n│   │   ├── dashboard/\n│   │   │   ├── stats-card.tsx\n│   │   │   └── recent-activity.tsx\n│   │   └── profile/\n│   │       ├── profile-header.tsx\n│   │       └── edit-profile-form.tsx\n│   └── shared/                         # Shared/common components\n│       ├── data-table.tsx\n│       ├── search-bar.tsx\n│       └── pagination.tsx\n│\n├── lib/                                # Utility functions & configurations\n│   ├── api.ts                          # Axios instance + interceptors\n│   ├── react-query.ts                  # React Query client config\n│   ├── utils.ts                        # Utility functions (cn, formatters)\n│   ├── validations.ts                  # Zod schemas\n│   ├── constants.ts                    # App constants\n│   └── auth.ts                         # Auth utilities (if using next-auth)\n│\n├── hooks/                              # Custom React hooks\n│   ├── use-auth.ts                     # Authentication hook\n│   ├── use-user.ts                     # User data hook (React Query)\n│   ├── use-posts.ts                    # Posts data hook (React Query)\n│   ├── use-media-query.ts              # Responsive design hook\n│   └── use-toast.ts                    # Toast notifications (shadcn)\n│\n├── types/                              # TypeScript type definitions\n│   ├── index.ts                        # Common types\n│   ├── api.ts                          # API response types\n│   ├── user.ts                         # User-related types\n│   └── database.ts                     # Database types (Prisma generated)\n│\n├── actions/                            # Server Actions (Next.js 14+)\n│   ├── auth.ts                         # Auth actions\n│   ├── user.ts                         # User actions\n│   └── posts.ts                        # Posts actions\n│\n├── config/                             # Configuration files\n│   ├── site.ts                         # Site metadata (name, description, etc.)\n│   └── navigation.ts                   # Navigation menu config\n│\n├── prisma/                             # Prisma ORM (if using database)\n│   ├── schema.prisma                   # Database schema\n│   └── migrations/                     # Database migrations\n│\n├── public/                             # Static assets\n│   ├── images/\n│   ├── icons/\n│   └── fonts/\n│\n├── styles/                             # Global styles\n│   └── globals.css                     # Tailwind imports + custom styles\n│\n├── .env.local                          # Environment variables (gitignored)\n├── .env.example                        # Environment variables template\n├── .eslintrc.json                      # ESLint config\n├── .prettierrc                         # Prettier config\n├── components.json                     # shadcn/ui config\n├── next.config.js                      # Next.js config\n├── tailwind.config.ts                  # Tailwind config\n├── tsconfig.json                       # TypeScript config\n├── package.json                        # Dependencies\n└── README.md                           # Project documentation\n\nDirectory Purpose\n\napp/ - Next.js 14 App Router pages and layouts. Use route groups (name) for logical grouping without affecting URLs.\n\ncomponents/ - All React components, organized by type:\n\nui/ - shadcn/ui components (copy-paste, customizable)\nlayout/ - Shared layout components (header, footer, sidebar)\nfeatures/ - Feature-specific components (scoped to one feature)\nshared/ - Reusable components used across features\n\nlib/ - Utility functions, configurations, and third-party library setups.\n\nhooks/ - Custom React hooks, especially React Query hooks for API calls.\n\ntypes/ - TypeScript type definitions and interfaces.\n\nactions/ - Server Actions for form handling and server-side operations (Next.js 14+).\n\nconfig/ - App configuration (site metadata, navigation menus, constants).\n\nprisma/ - Database schema and migrations (if using Prisma).\n\npublic/ - Static files served at root URL.\n\nstyles/ - Global CSS (Tailwind imports + custom styles).\n\nWorkflow\n\nKeep user informed at every step — this is a live build log.\n\n⚠️ Important: All projects use PM2 for dev server management (port 3002 by default). This ensures:\n\nOnly one instance runs at a time (no port conflicts)\nEasy process management (list/logs/restart/stop)\nPersistent dev server across terminal sessions\nBetter error logging and debugging\nStep 1: Project Setup\n\nAsk:\n\nProject name\nDescription/purpose\nOptional features (chromium review, nginx preview)\n\nCreate Next.js project:\n\nnpx create-next-app@latest <project-name> \\\n  --typescript \\\n  --tailwind \\\n  --app \\\n  --no-src-dir \\\n  --import-alias \"@/*\"\n\n\n→ Message user: \"Next.js project initialized ✓\"\n\nStep 2: Create Directory Structure\n\nCreate all necessary directories following industry best practices:\n\ncd <project-name>\n\n# Create app route groups\nmkdir -p app/\\(auth\\)/login app/\\(auth\\)/register\nmkdir -p app/\\(dashboard\\)/dashboard app/\\(dashboard\\)/profile app/\\(dashboard\\)/settings\nmkdir -p app/api/auth app/api/users\n\n# Create component directories\nmkdir -p components/ui components/layout components/features components/shared\nmkdir -p components/features/auth components/features/dashboard components/features/profile\n\n# Create utility directories\nmkdir -p lib hooks types actions config\n\n# Create static asset directories\nmkdir -p public/images public/icons public/fonts\n\n# Create styles directory\nmkdir styles\n\n# Create Prisma directory (if using database)\n# mkdir -p prisma\n\n\nCreate essential config files:\n\nconfig/site.ts - Site metadata\n\nexport const siteConfig = {\n  name: '<Project Name>',\n  description: '<Project Description>',\n  url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',\n  links: {\n    github: 'https://github.com/...',\n  },\n};\n\n\nconfig/navigation.ts - Navigation menu\n\nexport const mainNav = [\n  { title: 'Home', href: '/' },\n  { title: 'Dashboard', href: '/dashboard' },\n  { title: 'Profile', href: '/profile' },\n];\n\nexport const dashboardNav = [\n  { title: 'Overview', href: '/dashboard' },\n  { title: 'Profile', href: '/profile' },\n  { title: 'Settings', href: '/settings' },\n];\n\n\n.env.example - Environment variables template\n\nNEXT_PUBLIC_APP_URL=http://localhost:3000\nNEXT_PUBLIC_API_BASE_URL=http://localhost:3000/api\nDATABASE_URL=postgresql://...\nNEXTAUTH_SECRET=...\nNEXTAUTH_URL=http://localhost:3000\n\n\n→ Message user: \"Directory structure created ✓\"\n\nStep 3: Install Dependencies\n\nCore dependencies:\n\ncd <project-name>\nnpm install axios @tanstack/react-query\nnpm install -D @types/node\n\n\nshadcn/ui setup (recommended):\n\nnpx shadcn-ui@latest init\n\n\nThis will prompt for configuration. Recommended answers:\n\nStyle: Default\nBase color: Slate\nCSS variables: Yes\n\nInstall essential shadcn components:\n\nnpx shadcn-ui@latest add button card input label select textarea\nnpx shadcn-ui@latest add dropdown-menu dialog sheet tabs\nnpx shadcn-ui@latest add table form avatar badge separator toast\n\n\nInstall form dependencies (for shadcn/ui forms):\n\nnpm install react-hook-form @hookform/resolvers zod\n\n\nOptional (ask user based on needs):\n\nnpm install zustand  # State management\nnpm install next-auth  # Authentication\nnpm install prisma @prisma/client  # Database ORM\n\n\n→ Message user: \"Dependencies + shadcn/ui installed ✓\"\n\nStep 4: Configure Base Files\nlib/api.ts (axios instance)\nimport axios from 'axios';\n\nexport const api = axios.create({\n  baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000/api',\n  timeout: 10000,\n  headers: { 'Content-Type': 'application/json' }\n});\n\n// Request interceptor (add auth tokens, etc.)\napi.interceptors.request.use(\n  (config) => {\n    const token = localStorage.getItem('token');\n    if (token) config.headers.Authorization = `Bearer ${token}`;\n    return config;\n  },\n  (error) => Promise.reject(error)\n);\n\n// Response interceptor (handle errors globally)\napi.interceptors.response.use(\n  (response) => response,\n  (error) => {\n    if (error.response?.status === 401) {\n      // Handle unauthorized\n    }\n    return Promise.reject(error);\n  }\n);\n\nlib/react-query.ts (query client)\nimport { QueryClient } from '@tanstack/react-query';\n\nexport const queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: 60 * 1000, // 1 minute\n      refetchOnWindowFocus: false,\n      retry: 1,\n    },\n  },\n});\n\napp/providers.tsx (wrap app with providers)\n'use client';\n\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools';\nimport { queryClient } from '@/lib/react-query';\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n  return (\n    <QueryClientProvider client={queryClient}>\n      {children}\n      <ReactQueryDevtools initialIsOpen={false} />\n    </QueryClientProvider>\n  );\n}\n\n\nUpdate app/layout.tsx to use Providers.\n\n→ Message user: \"Base configuration complete ✓\"\n\nStep 5: Generate Features\n\nAsk what features/pages to build. For each feature:\n\nCreate route (app/<feature>/page.tsx)\nCreate components (components/features/<feature>/)\nCreate API hooks (hooks/use<Feature>.ts) using react-query\nCreate types (types/<feature>.ts)\nOptionally create API routes (app/api/<feature>/route.ts)\n\nExample: User Profile Feature\n\n// types/user.ts\nexport interface User {\n  id: string;\n  name: string;\n  email: string;\n}\n\n// hooks/useUser.ts\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { api } from '@/lib/api';\nimport type { User } from '@/types/user';\n\nexport const useUser = (id: string) => {\n  return useQuery({\n    queryKey: ['user', id],\n    queryFn: async () => {\n      const { data } = await api.get<User>(`/users/${id}`);\n      return data;\n    },\n  });\n};\n\nexport const useUpdateUser = () => {\n  const queryClient = useQueryClient();\n  \n  return useMutation({\n    mutationFn: async (user: Partial<User>) => {\n      const { data } = await api.patch<User>(`/users/${user.id}`, user);\n      return data;\n    },\n    onSuccess: (data) => {\n      queryClient.invalidateQueries({ queryKey: ['user', data.id] });\n    },\n  });\n};\n\n// app/profile/[id]/page.tsx\n'use client';\n\nimport { useUser, useUpdateUser } from '@/hooks/useUser';\n\nexport default function ProfilePage({ params }: { params: { id: string } }) {\n  const { data: user, isLoading, error } = useUser(params.id);\n  const updateUser = useUpdateUser();\n\n  if (isLoading) return <div>Loading...</div>;\n  if (error) return <div>Error: {error.message}</div>;\n\n  return (\n    <div>\n      <h1>{user?.name}</h1>\n      <p>{user?.email}</p>\n    </div>\n  );\n}\n\n\n→ Message user after each feature: \"Profile page complete ✓\"\n\nStep 6: Build UI with shadcn/ui Components\n\nUse shadcn/ui components (already installed) for consistent, accessible UI. Apply Design Principles (see below).\n\nExample: Profile page with shadcn/ui\n\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { Button } from '@/components/ui/button';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\n\nexport default function ProfilePage({ params }: { params: { id: string } }) {\n  const { data: user, isLoading } = useUser(params.id);\n\n  if (isLoading) return <Card className=\"w-full max-w-2xl mx-auto\"><CardContent>Loading...</CardContent></Card>;\n\n  return (\n    <Card className=\"w-full max-w-2xl mx-auto\">\n      <CardHeader>\n        <div className=\"flex items-center gap-4\">\n          <Avatar className=\"h-20 w-20\">\n            <AvatarImage src={user?.avatar} />\n            <AvatarFallback>{user?.name[0]}</AvatarFallback>\n          </Avatar>\n          <div>\n            <CardTitle>{user?.name}</CardTitle>\n            <p className=\"text-sm text-muted-foreground\">{user?.email}</p>\n          </div>\n        </div>\n      </CardHeader>\n      <CardContent>\n        <Button>Edit Profile</Button>\n      </CardContent>\n    </Card>\n  );\n}\n\n\nWhen to add more components:\n\nForms → npx shadcn-ui@latest add form input label\nData tables → npx shadcn-ui@latest add table\nNavigation → npx shadcn-ui@latest add navigation-menu\nFeedback → npx shadcn-ui@latest add toast alert\n\n→ Message user: \"UI built with shadcn/ui ✓\"\n\nStep 7: Visual Review (if chromium enabled)\n\nImportant: Use PM2 to manage the dev server (ensures only 1 instance runs, prevents port conflicts).\n\nStart dev server with PM2:\n\n# Stop any existing instance of this project\npm2 delete <project-name> 2>/dev/null || true\n\n# Start with PM2 (port 3002 for nginx proxy)\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\n# Give PM2 a moment to start\nsleep 2\n\n\nWait for server to be fully ready (critical - avoid white screen screenshots):\n\n# Wait for \"Ready in\" message in PM2 logs (usually 5-15 seconds)\ntimeout=30\nelapsed=0\nwhile [ $elapsed -lt $timeout ]; do\n  if pm2 logs <project-name> --nostream --lines 50 2>/dev/null | grep -q \"Ready in\"; then\n    echo \"Server ready!\"\n    sleep 3  # Extra buffer for module loading\n    break\n  fi\n  sleep 1\n  elapsed=$((elapsed + 1))\ndone\n\n# Verify server is responding\nif ! curl -s http://localhost:3002 > /dev/null; then\n  echo \"Warning: Server not responding on port 3002\"\n  pm2 logs <project-name> --nostream --lines 20\nfi\n\n\nTake screenshots (requires chromium):\n\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/review-desktop.png 1400 900\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/review-mobile.png 390 844\n\n\nReview Checklist (analyze with image tool):\n\n✅ Desktop (1400px): Content centered, proper spacing\n✅ Mobile (390px):\nNo horizontal overflow (content fits within screen)\nText readable (not too small)\nPadding appropriate (p-4 not p-24)\nTouch targets large enough (min 44x44px)\nNo content cutting off edges\n\nIf issues found: Fix responsive classes, re-run screenshots.\n\nCommon fixes:\n\nLarge padding → p-4 md:p-8 lg:p-12\nLarge text → text-2xl md:text-4xl\nWide content → Add max-w-full or px-4\n\n→ Message user: \"Review complete, sending preview...\"\n\nStep 8: Environment Setup\n\nCreate .env.local:\n\nNEXT_PUBLIC_API_BASE_URL=https://api.example.com\nDATABASE_URL=postgresql://...\nNEXTAUTH_SECRET=...\n\n\nCreate .env.example (template for user).\n\n→ Message user: \"Environment template created ✓\"\n\nStep 9: Scripts & Documentation\n\nUpdate package.json scripts:\n\n{\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"next lint\",\n    \"type-check\": \"tsc --noEmit\"\n  }\n}\n\n\nCreate README.md with:\n\nSetup instructions\nEnvironment variables needed\nDevelopment commands\nAPI integration guide\n\n→ Message user: \"Documentation complete ✓\"\n\nStep 10: Export & Deploy Guidance\n\nStop PM2 dev server (if running):\n\npm2 delete <project-name> 2>/dev/null || true\npm2 save  # Persist PM2 process list\n\n\nZip the project:\n\ncd .. && zip -r /tmp/<project-name>.zip <project-name>/\n\n\nSend via message tool with filePath.\n\nProvide deployment options:\n\nVercel (recommended): npx vercel\nNetlify: npm run build && netlify deploy\nDocker: Provide Dockerfile\nSelf-hosted: Provide systemd service + nginx config\n\n→ Message user: \"Project ready! 🚀\"\n\nTesting & Live Preview\nQuick Test (during development)\n\n1. PM2 dev server (always running after Step 7):\n\n# Check status\npm2 list\n\n# View logs\npm2 logs <project-name>\n\n# Access locally\ncurl http://localhost:3002\n\n\n2. Live preview URLs:\n\nLocal access: http://localhost:3002\nNginx proxy (if configured): http://<server-ip>:<external-port>\nMobile testing: Use nginx proxy or ngrok/tunneling service\n\n3. Screenshot review (if chromium enabled):\n\n# Desktop (1400x900)\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/desktop.png 1400 900\n\n# Mobile (390x844)\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/mobile.png 390 844\n\nEnd-to-End Testing Workflow\n\nFull test sequence:\n\n# 1. Check PM2 status\npm2 list | grep <project-name>\n\n# 2. Verify dev server responding\ncurl -I http://localhost:3002\n\n# 3. Take screenshots for visual verification\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/test-desktop.png 1400 900\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/test-mobile.png 390 844\n\n# 4. Check logs for errors\npm2 logs <project-name> --lines 50 | grep -i error\n\n# 5. Test API endpoints (if using API routes)\ncurl http://localhost:3002/api/health  # Example health check\n\n# 6. Production build test\nnpm run build && npm run start  # Test production build\n\n# 7. Type check\nnpm run type-check\n\nCommon Testing Scenarios\n\nScenario 1: Test responsive design\n\n# Mobile, tablet, desktop\nfor width in 390 768 1400; do\n  bash scripts/screenshot.sh \"http://localhost:3002\" /tmp/screen-${width}.png $width 900\ndone\n\n\nScenario 2: Test specific page/route\n\n# Take screenshot of specific route\nbash scripts/screenshot.sh \"http://localhost:3002/dashboard\" /tmp/dashboard.png 1400 900\n\n\nScenario 3: Test after making changes\n\n# PM2 auto-reloads on file changes, verify in logs\npm2 logs <project-name> --lines 20\n\n# Wait for \"compiled successfully\" then take new screenshot\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/updated.png 1400 900\n\nSharing Preview with User\n\nOption 1: Screenshots\n\nSend desktop + mobile screenshots via message tool\nUser provides feedback, you iterate\n\nOption 2: Nginx proxy + external access\n\nSet up nginx config (see Optional Features)\nShare URL: http://<server-ip>:<port>\nUser can test live in browser\n\nOption 3: Export & deploy\n\nZip project and send to user\nUser deploys to Vercel/Netlify\nTest on production URL\nAPI Integration Patterns\nPattern 1: REST API (default)\n\nUse axios + react-query:\n\n// hooks/usePosts.ts\nimport { useQuery, useMutation } from '@tanstack/react-query';\nimport { api } from '@/lib/api';\n\nexport const usePosts = () => {\n  return useQuery({\n    queryKey: ['posts'],\n    queryFn: async () => {\n      const { data } = await api.get('/posts');\n      return data;\n    },\n  });\n};\n\nexport const useCreatePost = () => {\n  return useMutation({\n    mutationFn: async (post: { title: string; body: string }) => {\n      const { data } = await api.post('/posts', post);\n      return data;\n    },\n  });\n};\n\nPattern 2: GraphQL (optional)\n\nInstall:\n\nnpm install @apollo/client graphql\n\n\nSetup Apollo Client, use useQuery and useMutation from Apollo.\n\nPattern 3: tRPC (optional)\n\nFor Next.js API routes with type safety:\n\nnpm install @trpc/server @trpc/client @trpc/react-query @trpc/next\n\nPattern 4: Server Actions (Next.js 14+)\n\nFor form handling without API routes:\n\n// app/actions.ts\n'use server';\n\nexport async function createPost(formData: FormData) {\n  const title = formData.get('title');\n  // ...\n}\n\n\nAlways ask user which pattern they prefer for their use case.\n\nDesign Principles\n\nApply these consistently. These are quality standards.\n\nLayout & Spacing\nConsistent Tailwind spacing scale (4, 6, 8, 12, 16, 20, 24)\nMax content width: max-w-5xl or max-w-6xl\nVertical rhythm: py-16 for sections, py-8 for subsections\nMobile: minimum px-4 padding\nTypography\nClear hierarchy (h1 → h2 → h3, max 3-4 sizes)\nLine length: max 65-75 characters (max-w-prose)\nFont weight contrast (bold headings, regular body)\nText color hierarchy (slate-900 → slate-700 → slate-500)\nColor & Contrast\nWCAG AA minimum (4.5:1 contrast)\nLimit palette (1 primary + 1 accent + neutrals)\nConsistent accent usage (CTAs, links, active states)\nResponsive Design (Critical)\nMobile-first (390px → 768px → 1024px) - Always design for 390px first\nResponsive padding - Use Tailwind responsive classes:\nMobile: p-4 or px-4 py-6 (never p-24 on mobile!)\nTablet: md:p-8 or md:px-6 md:py-8\nDesktop: lg:p-12 xl:p-24\nExample: <main className=\"p-4 md:p-8 lg:p-12\">\nResponsive text sizes - Scale down headings on mobile:\nMobile: text-2xl → Desktop: md:text-4xl\nMobile: text-lg → Desktop: md:text-2xl\nNo horizontal overflow - Content must fit within 390px width\nTest: Check mobile screenshot for any content cutting off edges\nUse max-w-full on containers\nBreak long words: break-words\nTouch targets - min 44x44px for buttons/links on mobile\nStack on mobile - Grids collapse to single column: grid-cols-1 md:grid-cols-2 lg:grid-cols-3\nHamburger menu - Required on mobile for navigation\nComponents (Use shadcn/ui)\nIcons: Use Lucide React (comes with shadcn/ui), never emoji\nButtons: Use <Button> component with variants (default, destructive, outline, ghost)\nForms: Use shadcn <Form> with react-hook-form integration\nCards: Use <Card> component for content sections\nDialogs/Modals: Use <Dialog> or <Sheet> components\nLoading states: Use shadcn <Skeleton> component for loading UI\nError handling: Use <Alert> component for error messages\nData display: Use <Table> component for tabular data\n\nshadcn/ui benefits: Accessible, customizable, copy-paste friendly, works with Tailwind\n\nTypeScript Best Practices\nStrict mode enabled\nExplicit return types for functions\nInterface over type for objects\nAvoid any (use unknown if needed)\nUse discriminated unions for variants\nPerformance\nUse Next.js Image component (next/image)\nLazy load below-the-fold content\nCode splitting (dynamic imports)\nMemoize expensive computations (useMemo, useCallback)\nCommon Patterns\nForm Handling (with shadcn/ui)\n'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useForm } from 'react-hook-form';\nimport * as z from 'zod';\nimport { useMutation } from '@tanstack/react-query';\nimport { Button } from '@/components/ui/button';\nimport { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';\nimport { Input } from '@/components/ui/input';\nimport { useToast } from '@/components/ui/use-toast';\n\nconst formSchema = z.object({\n  name: z.string().min(2, 'Name must be at least 2 characters'),\n  email: z.string().email('Invalid email address'),\n});\n\nexport default function ContactForm() {\n  const { toast } = useToast();\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: { name: '', email: '' },\n  });\n\n  const mutation = useMutation({\n    mutationFn: async (data: z.infer<typeof formSchema>) => {\n      const res = await api.post('/contact', data);\n      return res.data;\n    },\n    onSuccess: () => {\n      toast({ title: 'Success', description: 'Message sent!' });\n      form.reset();\n    },\n    onError: (error) => {\n      toast({ title: 'Error', description: error.message, variant: 'destructive' });\n    },\n  });\n\n  return (\n    <Form {...form}>\n      <form onSubmit={form.handleSubmit((data) => mutation.mutate(data))} className=\"space-y-4\">\n        <FormField\n          control={form.control}\n          name=\"name\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Name</FormLabel>\n              <FormControl>\n                <Input placeholder=\"John Doe\" {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name=\"email\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <FormControl>\n                <Input type=\"email\" placeholder=\"john@example.com\" {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button type=\"submit\" disabled={mutation.isPending}>\n          {mutation.isPending ? 'Sending...' : 'Send Message'}\n        </Button>\n      </form>\n    </Form>\n  );\n}\n\n\nNote: Run npx shadcn-ui@latest add form toast and install npm install react-hook-form @hookform/resolvers zod for this pattern.\n\nPagination\nconst usePaginatedPosts = (page: number) => {\n  return useQuery({\n    queryKey: ['posts', page],\n    queryFn: async () => {\n      const { data } = await api.get(`/posts?page=${page}`);\n      return data;\n    },\n    keepPreviousData: true, // Smooth transitions\n  });\n};\n\nInfinite Scroll\nimport { useInfiniteQuery } from '@tanstack/react-query';\n\nconst useInfinitePosts = () => {\n  return useInfiniteQuery({\n    queryKey: ['posts'],\n    queryFn: async ({ pageParam = 1 }) => {\n      const { data } = await api.get(`/posts?page=${pageParam}`);\n      return data;\n    },\n    getNextPageParam: (lastPage, pages) => lastPage.nextPage,\n  });\n};\n\nCommon Mistakes to Avoid\n❌ Not wrapping app with QueryClientProvider\n❌ Using axios without interceptors (no error handling)\n❌ Forgetting loading/error states in components\n❌ Not invalidating queries after mutations\n❌ Using any instead of proper TypeScript types\n❌ Client components when server components would work\n❌ Not using Next.js Image component (performance loss)\n❌ Missing error boundaries\n❌ Hardcoding API URLs (use env vars)\n❌ No mobile testing (always check responsive at 390px width)\n❌ Large padding on mobile (p-24 = 96px causes overflow on 390px screens)\n❌ Not using responsive Tailwind classes (use p-4 md:p-8 lg:p-12)\n❌ Horizontal overflow on mobile (content wider than 390px)\n❌ Building custom components when shadcn/ui has them (Button, Card, Dialog, etc.)\n❌ Using emoji for icons (use Lucide React icons from shadcn/ui)\n❌ Not installing @hookform/resolvers and zod before using shadcn forms\n❌ Forgetting to add <Toaster /> component when using toast notifications\n❌ Taking screenshots before dev server is fully ready (causes white screens)\n❌ Not waiting for module loading (causes \"Module not found\" errors in screenshots)\nTroubleshooting\nWhite Screen Screenshots\n\nProblem: Screenshots show blank white page Cause: Dev server not fully initialized before screenshot Solution:\n\nWait for \"Ready in\" message in dev server logs\nAdd 3-5 second buffer after \"Ready\" message\nVerify localhost:3000 loads in browser before taking screenshot\nModule Not Found Errors\n\nProblem: React error \"Module not found: Can't resolve @tanstack/react-query\" Cause: Dev server started before all packages loaded Solution:\n\nRestart dev server: pkill -f \"next dev\" && npm run dev\nVerify packages in node_modules: ls node_modules/@tanstack/\nWait 10-15 seconds after npm install before starting dev server\nDev Server Won't Start\n\nProblem: Port already in use (EADDRINUSE error) Solution (PM2 method):\n\n# Check what's running\npm2 list\n\n# Stop the conflicting process\npm2 delete <project-name>\n\n# Or check port directly\nlsof -ti:3002\n\n# Kill process on port (if not PM2-managed)\nkill -9 $(lsof -ti:3002)\n\n# Restart with PM2\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\nPM2 Process Management\n\nList all PM2 processes:\n\npm2 list\n\n\nCheck logs:\n\npm2 logs <project-name> --lines 50\n\n\nRestart a process:\n\npm2 restart <project-name>\n\n\nStop a process:\n\npm2 stop <project-name>\n\n\nDelete a process:\n\npm2 delete <project-name>\n\n\nEnsure only one instance runs:\n\n# Always delete before starting\npm2 delete <project-name> 2>/dev/null || true\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\n\nCommon PM2 scenarios:\n\nProject won't start → Check logs: pm2 logs <project-name>\nProcess keeps restarting → Module missing or port conflict, check logs\nChanges not reflecting → PM2 auto-reloads, verify in logs: pm2 logs <project-name> | grep compiled\nMultiple instances running → Delete all: pm2 delete all && pm2 list\nCheck resource usage → pm2 monit (real-time monitoring)\nSave PM2 process list → pm2 save (persists across reboots)\nIteration & Updates\n\nWhen user requests changes:\n\nIdentify affected files\nMake changes\nPM2 auto-reloads (no manual restart needed for file changes)\nRun type check: npm run type-check\nVerify in logs: pm2 logs <project-name> --lines 20\nIf chromium enabled: take new screenshot\nReport changes to user\n\nAlways explain what changed and why.\n\nQuick Reference Cheat Sheet\nEssential Commands\n# Start dev server\npm2 delete <project-name> 2>/dev/null || true\nPORT=3002 pm2 start npm --name \"<project-name>\" --cwd \"$(pwd)\" -- run dev\n\n# Check status\npm2 list\npm2 logs <project-name>\n\n# Take screenshots\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/desktop.png 1400 900\nbash scripts/screenshot.sh \"http://localhost:3002\" /tmp/mobile.png 390 844\n\n# Test production build\nnpm run build && npm run start\n\n# Type check\nnpm run type-check\n\nFile Locations\nComponents: components/ui/ (shadcn), components/features/ (custom)\nPages: app/*/page.tsx\nAPI routes: app/api/*/route.ts\nStyles: app/globals.css, tailwind.config.ts\nConfig: next.config.ts, .env.local\nCommon shadcn Components\nnpx shadcn-ui@latest add button input form card table dialog toast\n\nLive Preview URLs\nLocal: http://localhost:3002\nNginx proxy: http://<server-ip>:<external-port>\nMobile testing: Use nginx proxy or ngrok\nTroubleshooting\nPort conflict → pm2 delete <name> then restart\nWhite screen → Wait for \"Ready in\" message (check logs)\nModule errors → npm install then restart PM2\nType errors → npm run type-check\nLayout breaks → Check responsive classes (p-4 md:p-8 lg:p-12)"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/wing8169/frontend-dev",
    "publisherUrl": "https://clawhub.ai/wing8169/frontend-dev",
    "owner": "wing8169",
    "version": "0.1.1",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/frontend-dev",
    "downloadUrl": "https://openagent3.xyz/downloads/frontend-dev",
    "agentUrl": "https://openagent3.xyz/skills/frontend-dev/agent",
    "manifestUrl": "https://openagent3.xyz/skills/frontend-dev/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/frontend-dev/agent.md"
  }
}