Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Generate production-ready Next.js projects with TypeScript, Tailwind CSS, shadcn/ui, and API integration. Use when the user asks to build, create, develop, or scaffold a Next.js application, web app, full-stack project, or frontend with backend integration. Prioritizes modern stack (Next.js 14+, TypeScript, shadcn/ui, axios, react-query) and best practices. Also triggers on requests to add features, integrate APIs, or extend existing Next.js projects.
Generate production-ready Next.js projects with TypeScript, Tailwind CSS, shadcn/ui, and API integration. Use when the user asks to build, create, develop, or scaffold a Next.js application, web app, full-stack project, or frontend with backend integration. Prioritizes modern stack (Next.js 14+, TypeScript, shadcn/ui, axios, react-query) and best practices. Also triggers on requests to add features, integrate APIs, or extend existing Next.js projects.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
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.
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.
Generate production-ready Next.js projects from natural language, with shadcn/ui components, API integration, type safety, and modern tooling.
Fast path for simple projects: Create Next.js app โ 2. Install shadcn/ui โ 3. Build UI โ 4. Start with PM2 โ 5. Screenshot review โ 6. Done Live preview: Projects run on PM2 (port 3002), accessible at http://localhost:3002 or via nginx proxy if configured. Default workflow: All projects use PM2 for dev server management (prevents port conflicts, ensures single instance).
Node.js 18+ and npm/yarn/pnpm Git (for project initialization)
1. Auto-Revision with Visual Review (requires Chromium) What it does: Takes screenshots during development to visually review designs and auto-fix issues Installation: sudo apt-get install chromium-browser (Debian/Ubuntu) Privileges: Read/write access to project files, execute chromium in headless mode If declined: Manual review only (you describe, user verifies) 2. Live Preview Server (requires Nginx) What it does: Serves project on external port for live preview during development (useful for mobile testing or remote access) Installation: sudo apt-get install nginx How it works: PM2 runs dev server on port 3002, nginx proxies it to chosen external port Nginx config template: # /etc/nginx/sites-available/<project-name> server { listen <external-port>; # e.g., 3001, 8081, etc. server_name _; location / { proxy_pass http://localhost:3002; # PM2 dev server proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } Enable: sudo ln -s /etc/nginx/sites-available/<project-name> /etc/nginx/sites-enabled/ && sudo systemctl reload nginx If declined: Access directly via http://localhost:3002 (PM2 port) Before starting, ask user if they want to enable optional features.
Quick reference for typical requests: Dashboard/Admin Panel โ Use (dashboard) route group, shadcn data tables, charts Landing Page โ Single app/page.tsx, hero section, features grid, testimonials Todo/Task App โ shadcn checkbox, input, button; local state or API Blog/CMS โ Dynamic routes app/blog/[slug]/page.tsx, markdown support E-commerce โ Product catalog, cart state (Zustand), checkout flow SaaS App โ Auth ((auth) group), protected routes, subscription logic Portfolio โ Projects grid, contact form, image gallery Form-heavy App โ React Hook Form + Zod validation, shadcn form components Ask user: What type of project are you building? (helps determine structure and components)
Core: Next.js 14+ (App Router) TypeScript Tailwind CSS v3 shadcn/ui (recommended UI component library) ESLint + Prettier API Integration (default): axios (HTTP client) @tanstack/react-query (data fetching, caching, state management) Optional (based on needs): Zustand (client-side state management) Zod (runtime validation) next-auth (authentication) Prisma (database ORM)
Industry-standard Next.js 14+ App Router structure with feature-based organization: <project-name>/ โโโ app/ # Next.js 14 App Router โ โโโ (auth)/ # Route group (auth pages) โ โ โโโ login/ โ โ โ โโโ page.tsx โ โ โโโ register/ โ โ โ โโโ page.tsx โ โ โโโ layout.tsx # Auth-specific layout โ โโโ (dashboard)/ # Route group (protected pages) โ โ โโโ dashboard/ โ โ โ โโโ page.tsx โ โ โ โโโ loading.tsx โ โ โโโ profile/ โ โ โ โโโ page.tsx โ โ โโโ settings/ โ โ โ โโโ page.tsx โ โ โโโ layout.tsx # Dashboard layout with sidebar โ โโโ api/ # API routes โ โ โโโ auth/ โ โ โ โโโ [...nextauth]/route.ts โ โ โโโ users/ โ โ โโโ route.ts โ โโโ layout.tsx # Root layout โ โโโ page.tsx # Home page โ โโโ loading.tsx # Root loading UI โ โโโ error.tsx # Root error boundary โ โโโ not-found.tsx # 404 page โ โโโ providers.tsx # Client providers (React Query, etc.) โ โโโ components/ โ โโโ ui/ # shadcn/ui components (auto-generated) โ โ โโโ button.tsx โ โ โโโ card.tsx โ โ โโโ input.tsx โ โ โโโ form.tsx โ โ โโโ ... โ โโโ layout/ # Layout components โ โ โโโ header.tsx โ โ โโโ footer.tsx โ โ โโโ sidebar.tsx โ โ โโโ mobile-nav.tsx โ โโโ features/ # Feature-specific components โ โ โโโ auth/ โ โ โ โโโ login-form.tsx โ โ โ โโโ register-form.tsx โ โ โโโ dashboard/ โ โ โ โโโ stats-card.tsx โ โ โ โโโ recent-activity.tsx โ โ โโโ profile/ โ โ โโโ profile-header.tsx โ โ โโโ edit-profile-form.tsx โ โโโ shared/ # Shared/common components โ โโโ data-table.tsx โ โโโ search-bar.tsx โ โโโ pagination.tsx โ โโโ lib/ # Utility functions & configurations โ โโโ api.ts # Axios instance + interceptors โ โโโ react-query.ts # React Query client config โ โโโ utils.ts # Utility functions (cn, formatters) โ โโโ validations.ts # Zod schemas โ โโโ constants.ts # App constants โ โโโ auth.ts # Auth utilities (if using next-auth) โ โโโ hooks/ # Custom React hooks โ โโโ use-auth.ts # Authentication hook โ โโโ use-user.ts # User data hook (React Query) โ โโโ use-posts.ts # Posts data hook (React Query) โ โโโ use-media-query.ts # Responsive design hook โ โโโ use-toast.ts # Toast notifications (shadcn) โ โโโ types/ # TypeScript type definitions โ โโโ index.ts # Common types โ โโโ api.ts # API response types โ โโโ user.ts # User-related types โ โโโ database.ts # Database types (Prisma generated) โ โโโ actions/ # Server Actions (Next.js 14+) โ โโโ auth.ts # Auth actions โ โโโ user.ts # User actions โ โโโ posts.ts # Posts actions โ โโโ config/ # Configuration files โ โโโ site.ts # Site metadata (name, description, etc.) โ โโโ navigation.ts # Navigation menu config โ โโโ prisma/ # Prisma ORM (if using database) โ โโโ schema.prisma # Database schema โ โโโ migrations/ # Database migrations โ โโโ public/ # Static assets โ โโโ images/ โ โโโ icons/ โ โโโ fonts/ โ โโโ styles/ # Global styles โ โโโ globals.css # Tailwind imports + custom styles โ โโโ .env.local # Environment variables (gitignored) โโโ .env.example # Environment variables template โโโ .eslintrc.json # ESLint config โโโ .prettierrc # Prettier config โโโ components.json # shadcn/ui config โโโ next.config.js # Next.js config โโโ tailwind.config.ts # Tailwind config โโโ tsconfig.json # TypeScript config โโโ package.json # Dependencies โโโ README.md # Project documentation
app/ - Next.js 14 App Router pages and layouts. Use route groups (name) for logical grouping without affecting URLs. components/ - All React components, organized by type: ui/ - shadcn/ui components (copy-paste, customizable) layout/ - Shared layout components (header, footer, sidebar) features/ - Feature-specific components (scoped to one feature) shared/ - Reusable components used across features lib/ - Utility functions, configurations, and third-party library setups. hooks/ - Custom React hooks, especially React Query hooks for API calls. types/ - TypeScript type definitions and interfaces. actions/ - Server Actions for form handling and server-side operations (Next.js 14+). config/ - App configuration (site metadata, navigation menus, constants). prisma/ - Database schema and migrations (if using Prisma). public/ - Static files served at root URL. styles/ - Global CSS (Tailwind imports + custom styles).
Keep user informed at every step โ this is a live build log. โ ๏ธ Important: All projects use PM2 for dev server management (port 3002 by default). This ensures: Only one instance runs at a time (no port conflicts) Easy process management (list/logs/restart/stop) Persistent dev server across terminal sessions Better error logging and debugging
Ask: Project name Description/purpose Optional features (chromium review, nginx preview) Create Next.js project: npx create-next-app@latest <project-name> \ --typescript \ --tailwind \ --app \ --no-src-dir \ --import-alias "@/*" โ Message user: "Next.js project initialized โ"
Create all necessary directories following industry best practices: cd <project-name> # Create app route groups mkdir -p app/\(auth\)/login app/\(auth\)/register mkdir -p app/\(dashboard\)/dashboard app/\(dashboard\)/profile app/\(dashboard\)/settings mkdir -p app/api/auth app/api/users # Create component directories mkdir -p components/ui components/layout components/features components/shared mkdir -p components/features/auth components/features/dashboard components/features/profile # Create utility directories mkdir -p lib hooks types actions config # Create static asset directories mkdir -p public/images public/icons public/fonts # Create styles directory mkdir styles # Create Prisma directory (if using database) # mkdir -p prisma Create essential config files: config/site.ts - Site metadata export const siteConfig = { name: '<Project Name>', description: '<Project Description>', url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000', links: { github: 'https://github.com/...', }, }; config/navigation.ts - Navigation menu export const mainNav = [ { title: 'Home', href: '/' }, { title: 'Dashboard', href: '/dashboard' }, { title: 'Profile', href: '/profile' }, ]; export const dashboardNav = [ { title: 'Overview', href: '/dashboard' }, { title: 'Profile', href: '/profile' }, { title: 'Settings', href: '/settings' }, ]; .env.example - Environment variables template NEXT_PUBLIC_APP_URL=http://localhost:3000 NEXT_PUBLIC_API_BASE_URL=http://localhost:3000/api DATABASE_URL=postgresql://... NEXTAUTH_SECRET=... NEXTAUTH_URL=http://localhost:3000 โ Message user: "Directory structure created โ"
Core dependencies: cd <project-name> npm install axios @tanstack/react-query npm install -D @types/node shadcn/ui setup (recommended): npx shadcn-ui@latest init This will prompt for configuration. Recommended answers: Style: Default Base color: Slate CSS variables: Yes Install essential shadcn components: npx shadcn-ui@latest add button card input label select textarea npx shadcn-ui@latest add dropdown-menu dialog sheet tabs npx shadcn-ui@latest add table form avatar badge separator toast Install form dependencies (for shadcn/ui forms): npm install react-hook-form @hookform/resolvers zod Optional (ask user based on needs): npm install zustand # State management npm install next-auth # Authentication npm install prisma @prisma/client # Database ORM โ Message user: "Dependencies + shadcn/ui installed โ"
lib/api.ts (axios instance) import axios from 'axios'; export const api = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000/api', timeout: 10000, headers: { 'Content-Type': 'application/json' } }); // Request interceptor (add auth tokens, etc.) api.interceptors.request.use( (config) => { const token = localStorage.getItem('token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }, (error) => Promise.reject(error) ); // Response interceptor (handle errors globally) api.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // Handle unauthorized } return Promise.reject(error); } ); lib/react-query.ts (query client) import { QueryClient } from '@tanstack/react-query'; export const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, // 1 minute refetchOnWindowFocus: false, retry: 1, }, }, }); app/providers.tsx (wrap app with providers) 'use client'; import { QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { queryClient } from '@/lib/react-query'; export function Providers({ children }: { children: React.ReactNode }) { return ( <QueryClientProvider client={queryClient}> {children} <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider> ); } Update app/layout.tsx to use Providers. โ Message user: "Base configuration complete โ"
Ask what features/pages to build. For each feature: Create route (app/<feature>/page.tsx) Create components (components/features/<feature>/) Create API hooks (hooks/use<Feature>.ts) using react-query Create types (types/<feature>.ts) Optionally create API routes (app/api/<feature>/route.ts) Example: User Profile Feature // types/user.ts export interface User { id: string; name: string; email: string; } // hooks/useUser.ts import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { api } from '@/lib/api'; import type { User } from '@/types/user'; export const useUser = (id: string) => { return useQuery({ queryKey: ['user', id], queryFn: async () => { const { data } = await api.get<User>(`/users/${id}`); return data; }, }); }; export const useUpdateUser = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (user: Partial<User>) => { const { data } = await api.patch<User>(`/users/${user.id}`, user); return data; }, onSuccess: (data) => { queryClient.invalidateQueries({ queryKey: ['user', data.id] }); }, }); }; // app/profile/[id]/page.tsx 'use client'; import { useUser, useUpdateUser } from '@/hooks/useUser'; export default function ProfilePage({ params }: { params: { id: string } }) { const { data: user, isLoading, error } = useUser(params.id); const updateUser = useUpdateUser(); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <h1>{user?.name}</h1> <p>{user?.email}</p> </div> ); } โ Message user after each feature: "Profile page complete โ"
Use shadcn/ui components (already installed) for consistent, accessible UI. Apply Design Principles (see below). Example: Profile page with shadcn/ui import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; export default function ProfilePage({ params }: { params: { id: string } }) { const { data: user, isLoading } = useUser(params.id); if (isLoading) return <Card className="w-full max-w-2xl mx-auto"><CardContent>Loading...</CardContent></Card>; return ( <Card className="w-full max-w-2xl mx-auto"> <CardHeader> <div className="flex items-center gap-4"> <Avatar className="h-20 w-20"> <AvatarImage src={user?.avatar} /> <AvatarFallback>{user?.name[0]}</AvatarFallback> </Avatar> <div> <CardTitle>{user?.name}</CardTitle> <p className="text-sm text-muted-foreground">{user?.email}</p> </div> </div> </CardHeader> <CardContent> <Button>Edit Profile</Button> </CardContent> </Card> ); } When to add more components: Forms โ npx shadcn-ui@latest add form input label Data tables โ npx shadcn-ui@latest add table Navigation โ npx shadcn-ui@latest add navigation-menu Feedback โ npx shadcn-ui@latest add toast alert โ Message user: "UI built with shadcn/ui โ"
Important: Use PM2 to manage the dev server (ensures only 1 instance runs, prevents port conflicts). Start dev server with PM2: # Stop any existing instance of this project pm2 delete <project-name> 2>/dev/null || true # Start with PM2 (port 3002 for nginx proxy) PORT=3002 pm2 start npm --name "<project-name>" --cwd "$(pwd)" -- run dev # Give PM2 a moment to start sleep 2 Wait for server to be fully ready (critical - avoid white screen screenshots): # Wait for "Ready in" message in PM2 logs (usually 5-15 seconds) timeout=30 elapsed=0 while [ $elapsed -lt $timeout ]; do if pm2 logs <project-name> --nostream --lines 50 2>/dev/null | grep -q "Ready in"; then echo "Server ready!" sleep 3 # Extra buffer for module loading break fi sleep 1 elapsed=$((elapsed + 1)) done # Verify server is responding if ! curl -s http://localhost:3002 > /dev/null; then echo "Warning: Server not responding on port 3002" pm2 logs <project-name> --nostream --lines 20 fi Take screenshots (requires chromium): bash scripts/screenshot.sh "http://localhost:3002" /tmp/review-desktop.png 1400 900 bash scripts/screenshot.sh "http://localhost:3002" /tmp/review-mobile.png 390 844 Review Checklist (analyze with image tool): โ Desktop (1400px): Content centered, proper spacing โ Mobile (390px): No horizontal overflow (content fits within screen) Text readable (not too small) Padding appropriate (p-4 not p-24) Touch targets large enough (min 44x44px) No content cutting off edges If issues found: Fix responsive classes, re-run screenshots. Common fixes: Large padding โ p-4 md:p-8 lg:p-12 Large text โ text-2xl md:text-4xl Wide content โ Add max-w-full or px-4 โ Message user: "Review complete, sending preview..."
Create .env.local: NEXT_PUBLIC_API_BASE_URL=https://api.example.com DATABASE_URL=postgresql://... NEXTAUTH_SECRET=... Create .env.example (template for user). โ Message user: "Environment template created โ"
Update package.json scripts: { "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "type-check": "tsc --noEmit" } } Create README.md with: Setup instructions Environment variables needed Development commands API integration guide โ Message user: "Documentation complete โ"
Stop PM2 dev server (if running): pm2 delete <project-name> 2>/dev/null || true pm2 save # Persist PM2 process list Zip the project: cd .. && zip -r /tmp/<project-name>.zip <project-name>/ Send via message tool with filePath. Provide deployment options: Vercel (recommended): npx vercel Netlify: npm run build && netlify deploy Docker: Provide Dockerfile Self-hosted: Provide systemd service + nginx config โ Message user: "Project ready! ๐"
1. PM2 dev server (always running after Step 7): # Check status pm2 list # View logs pm2 logs <project-name> # Access locally curl http://localhost:3002 2. Live preview URLs: Local access: http://localhost:3002 Nginx proxy (if configured): http://<server-ip>:<external-port> Mobile testing: Use nginx proxy or ngrok/tunneling service 3. Screenshot review (if chromium enabled): # Desktop (1400x900) bash scripts/screenshot.sh "http://localhost:3002" /tmp/desktop.png 1400 900 # Mobile (390x844) bash scripts/screenshot.sh "http://localhost:3002" /tmp/mobile.png 390 844
Full test sequence: # 1. Check PM2 status pm2 list | grep <project-name> # 2. Verify dev server responding curl -I http://localhost:3002 # 3. Take screenshots for visual verification bash scripts/screenshot.sh "http://localhost:3002" /tmp/test-desktop.png 1400 900 bash scripts/screenshot.sh "http://localhost:3002" /tmp/test-mobile.png 390 844 # 4. Check logs for errors pm2 logs <project-name> --lines 50 | grep -i error # 5. Test API endpoints (if using API routes) curl http://localhost:3002/api/health # Example health check # 6. Production build test npm run build && npm run start # Test production build # 7. Type check npm run type-check
Scenario 1: Test responsive design # Mobile, tablet, desktop for width in 390 768 1400; do bash scripts/screenshot.sh "http://localhost:3002" /tmp/screen-${width}.png $width 900 done Scenario 2: Test specific page/route # Take screenshot of specific route bash scripts/screenshot.sh "http://localhost:3002/dashboard" /tmp/dashboard.png 1400 900 Scenario 3: Test after making changes # PM2 auto-reloads on file changes, verify in logs pm2 logs <project-name> --lines 20 # Wait for "compiled successfully" then take new screenshot bash scripts/screenshot.sh "http://localhost:3002" /tmp/updated.png 1400 900
Option 1: Screenshots Send desktop + mobile screenshots via message tool User provides feedback, you iterate Option 2: Nginx proxy + external access Set up nginx config (see Optional Features) Share URL: http://<server-ip>:<port> User can test live in browser Option 3: Export & deploy Zip project and send to user User deploys to Vercel/Netlify Test on production URL
Use axios + react-query: // hooks/usePosts.ts import { useQuery, useMutation } from '@tanstack/react-query'; import { api } from '@/lib/api'; export const usePosts = () => { return useQuery({ queryKey: ['posts'], queryFn: async () => { const { data } = await api.get('/posts'); return data; }, }); }; export const useCreatePost = () => { return useMutation({ mutationFn: async (post: { title: string; body: string }) => { const { data } = await api.post('/posts', post); return data; }, }); };
Install: npm install @apollo/client graphql Setup Apollo Client, use useQuery and useMutation from Apollo.
For Next.js API routes with type safety: npm install @trpc/server @trpc/client @trpc/react-query @trpc/next
For form handling without API routes: // app/actions.ts 'use server'; export async function createPost(formData: FormData) { const title = formData.get('title'); // ... } Always ask user which pattern they prefer for their use case.
Apply these consistently. These are quality standards.
Consistent Tailwind spacing scale (4, 6, 8, 12, 16, 20, 24) Max content width: max-w-5xl or max-w-6xl Vertical rhythm: py-16 for sections, py-8 for subsections Mobile: minimum px-4 padding
Clear hierarchy (h1 โ h2 โ h3, max 3-4 sizes) Line length: max 65-75 characters (max-w-prose) Font weight contrast (bold headings, regular body) Text color hierarchy (slate-900 โ slate-700 โ slate-500)
WCAG AA minimum (4.5:1 contrast) Limit palette (1 primary + 1 accent + neutrals) Consistent accent usage (CTAs, links, active states)
Mobile-first (390px โ 768px โ 1024px) - Always design for 390px first Responsive padding - Use Tailwind responsive classes: Mobile: p-4 or px-4 py-6 (never p-24 on mobile!) Tablet: md:p-8 or md:px-6 md:py-8 Desktop: lg:p-12 xl:p-24 Example: <main className="p-4 md:p-8 lg:p-12"> Responsive text sizes - Scale down headings on mobile: Mobile: text-2xl โ Desktop: md:text-4xl Mobile: text-lg โ Desktop: md:text-2xl No horizontal overflow - Content must fit within 390px width Test: Check mobile screenshot for any content cutting off edges Use max-w-full on containers Break long words: break-words Touch targets - min 44x44px for buttons/links on mobile Stack on mobile - Grids collapse to single column: grid-cols-1 md:grid-cols-2 lg:grid-cols-3 Hamburger menu - Required on mobile for navigation
Icons: Use Lucide React (comes with shadcn/ui), never emoji Buttons: Use <Button> component with variants (default, destructive, outline, ghost) Forms: Use shadcn <Form> with react-hook-form integration Cards: Use <Card> component for content sections Dialogs/Modals: Use <Dialog> or <Sheet> components Loading states: Use shadcn <Skeleton> component for loading UI Error handling: Use <Alert> component for error messages Data display: Use <Table> component for tabular data shadcn/ui benefits: Accessible, customizable, copy-paste friendly, works with Tailwind
Strict mode enabled Explicit return types for functions Interface over type for objects Avoid any (use unknown if needed) Use discriminated unions for variants
Use Next.js Image component (next/image) Lazy load below-the-fold content Code splitting (dynamic imports) Memoize expensive computations (useMemo, useCallback)
'use client'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import * as z from 'zod'; import { useMutation } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { useToast } from '@/components/ui/use-toast'; const formSchema = z.object({ name: z.string().min(2, 'Name must be at least 2 characters'), email: z.string().email('Invalid email address'), }); export default function ContactForm() { const { toast } = useToast(); const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { name: '', email: '' }, }); const mutation = useMutation({ mutationFn: async (data: z.infer<typeof formSchema>) => { const res = await api.post('/contact', data); return res.data; }, onSuccess: () => { toast({ title: 'Success', description: 'Message sent!' }); form.reset(); }, onError: (error) => { toast({ title: 'Error', description: error.message, variant: 'destructive' }); }, }); return ( <Form {...form}> <form onSubmit={form.handleSubmit((data) => mutation.mutate(data))} className="space-y-4"> <FormField control={form.control} name="name" render={({ field }) => ( <FormItem> <FormLabel>Name</FormLabel> <FormControl> <Input placeholder="John Doe" {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> <FormField control={form.control} name="email" render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <FormControl> <Input type="email" placeholder="john@example.com" {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> <Button type="submit" disabled={mutation.isPending}> {mutation.isPending ? 'Sending...' : 'Send Message'} </Button> </form> </Form> ); } Note: Run npx shadcn-ui@latest add form toast and install npm install react-hook-form @hookform/resolvers zod for this pattern.
const usePaginatedPosts = (page: number) => { return useQuery({ queryKey: ['posts', page], queryFn: async () => { const { data } = await api.get(`/posts?page=${page}`); return data; }, keepPreviousData: true, // Smooth transitions }); };
import { useInfiniteQuery } from '@tanstack/react-query'; const useInfinitePosts = () => { return useInfiniteQuery({ queryKey: ['posts'], queryFn: async ({ pageParam = 1 }) => { const { data } = await api.get(`/posts?page=${pageParam}`); return data; }, getNextPageParam: (lastPage, pages) => lastPage.nextPage, }); };
โ Not wrapping app with QueryClientProvider โ Using axios without interceptors (no error handling) โ Forgetting loading/error states in components โ Not invalidating queries after mutations โ Using any instead of proper TypeScript types โ Client components when server components would work โ Not using Next.js Image component (performance loss) โ Missing error boundaries โ Hardcoding API URLs (use env vars) โ No mobile testing (always check responsive at 390px width) โ Large padding on mobile (p-24 = 96px causes overflow on 390px screens) โ Not using responsive Tailwind classes (use p-4 md:p-8 lg:p-12) โ Horizontal overflow on mobile (content wider than 390px) โ Building custom components when shadcn/ui has them (Button, Card, Dialog, etc.) โ Using emoji for icons (use Lucide React icons from shadcn/ui) โ Not installing @hookform/resolvers and zod before using shadcn forms โ Forgetting to add <Toaster /> component when using toast notifications โ Taking screenshots before dev server is fully ready (causes white screens) โ Not waiting for module loading (causes "Module not found" errors in screenshots)
Problem: Screenshots show blank white page Cause: Dev server not fully initialized before screenshot Solution: Wait for "Ready in" message in dev server logs Add 3-5 second buffer after "Ready" message Verify localhost:3000 loads in browser before taking screenshot
Problem: React error "Module not found: Can't resolve @tanstack/react-query" Cause: Dev server started before all packages loaded Solution: Restart dev server: pkill -f "next dev" && npm run dev Verify packages in node_modules: ls node_modules/@tanstack/ Wait 10-15 seconds after npm install before starting dev server
Problem: Port already in use (EADDRINUSE error) Solution (PM2 method): # Check what's running pm2 list # Stop the conflicting process pm2 delete <project-name> # Or check port directly lsof -ti:3002 # Kill process on port (if not PM2-managed) kill -9 $(lsof -ti:3002) # Restart with PM2 PORT=3002 pm2 start npm --name "<project-name>" --cwd "$(pwd)" -- run dev
List all PM2 processes: pm2 list Check logs: pm2 logs <project-name> --lines 50 Restart a process: pm2 restart <project-name> Stop a process: pm2 stop <project-name> Delete a process: pm2 delete <project-name> Ensure only one instance runs: # Always delete before starting pm2 delete <project-name> 2>/dev/null || true PORT=3002 pm2 start npm --name "<project-name>" --cwd "$(pwd)" -- run dev Common PM2 scenarios: Project won't start โ Check logs: pm2 logs <project-name> Process keeps restarting โ Module missing or port conflict, check logs Changes not reflecting โ PM2 auto-reloads, verify in logs: pm2 logs <project-name> | grep compiled Multiple instances running โ Delete all: pm2 delete all && pm2 list Check resource usage โ pm2 monit (real-time monitoring) Save PM2 process list โ pm2 save (persists across reboots)
When user requests changes: Identify affected files Make changes PM2 auto-reloads (no manual restart needed for file changes) Run type check: npm run type-check Verify in logs: pm2 logs <project-name> --lines 20 If chromium enabled: take new screenshot Report changes to user Always explain what changed and why.
# Start dev server pm2 delete <project-name> 2>/dev/null || true PORT=3002 pm2 start npm --name "<project-name>" --cwd "$(pwd)" -- run dev # Check status pm2 list pm2 logs <project-name> # Take screenshots bash scripts/screenshot.sh "http://localhost:3002" /tmp/desktop.png 1400 900 bash scripts/screenshot.sh "http://localhost:3002" /tmp/mobile.png 390 844 # Test production build npm run build && npm run start # Type check npm run type-check
Components: components/ui/ (shadcn), components/features/ (custom) Pages: app/*/page.tsx API routes: app/api/*/route.ts Styles: app/globals.css, tailwind.config.ts Config: next.config.ts, .env.local
npx shadcn-ui@latest add button input form card table dialog toast
Local: http://localhost:3002 Nginx proxy: http://<server-ip>:<external-port> Mobile testing: Use nginx proxy or ngrok
Port conflict โ pm2 delete <name> then restart White screen โ Wait for "Ready in" message (check logs) Module errors โ npm install then restart PM2 Type errors โ npm run type-check Layout breaks โ Check responsive classes (p-4 md:p-8 lg:p-12)
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.