{
  "schemaVersion": "1.0",
  "item": {
    "slug": "senior-frontend",
    "name": "Senior Frontend",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/alirezarezvani/senior-frontend",
    "canonicalUrl": "https://clawhub.ai/alirezarezvani/senior-frontend",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/senior-frontend",
    "sourceDownloadUrl": "https://clawhub.ai/api/v1/download?slug=senior-frontend",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "references/frontend_best_practices.md",
      "references/nextjs_optimization_guide.md",
      "references/react_patterns.md",
      "scripts/bundle_analyzer.py",
      "scripts/component_generator.py"
    ],
    "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. 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. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/senior-frontend"
    },
    "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/senior-frontend",
    "agentPageUrl": "https://openagent3.xyz/skills/senior-frontend/agent",
    "manifestUrl": "https://openagent3.xyz/skills/senior-frontend/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/senior-frontend/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. 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. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Senior Frontend",
        "body": "Frontend development patterns, performance optimization, and automation tools for React/Next.js applications."
      },
      {
        "title": "Table of Contents",
        "body": "Project Scaffolding\nComponent Generation\nBundle Analysis\nReact Patterns\nNext.js Optimization\nAccessibility and Testing"
      },
      {
        "title": "Project Scaffolding",
        "body": "Generate a new Next.js or React project with TypeScript, Tailwind CSS, and best practice configurations."
      },
      {
        "title": "Workflow: Create New Frontend Project",
        "body": "Run the scaffolder with your project name and template:\npython scripts/frontend_scaffolder.py my-app --template nextjs\n\n\n\nAdd optional features (auth, api, forms, testing, storybook):\npython scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api\n\n\n\nNavigate to the project and install dependencies:\ncd my-app && npm install\n\n\n\nStart the development server:\nnpm run dev"
      },
      {
        "title": "Scaffolder Options",
        "body": "OptionDescription--template nextjsNext.js 14+ with App Router and Server Components--template reactReact + Vite with TypeScript--features authAdd NextAuth.js authentication--features apiAdd React Query + API client--features formsAdd React Hook Form + Zod validation--features testingAdd Vitest + Testing Library--dry-runPreview files without creating them"
      },
      {
        "title": "Generated Structure (Next.js)",
        "body": "my-app/\n├── app/\n│   ├── layout.tsx        # Root layout with fonts\n│   ├── page.tsx          # Home page\n│   ├── globals.css       # Tailwind + CSS variables\n│   └── api/health/route.ts\n├── components/\n│   ├── ui/               # Button, Input, Card\n│   └── layout/           # Header, Footer, Sidebar\n├── hooks/                # useDebounce, useLocalStorage\n├── lib/                  # utils (cn), constants\n├── types/                # TypeScript interfaces\n├── tailwind.config.ts\n├── next.config.js\n└── package.json"
      },
      {
        "title": "Component Generation",
        "body": "Generate React components with TypeScript, tests, and Storybook stories."
      },
      {
        "title": "Workflow: Create a New Component",
        "body": "Generate a client component:\npython scripts/component_generator.py Button --dir src/components/ui\n\n\n\nGenerate a server component:\npython scripts/component_generator.py ProductCard --type server\n\n\n\nGenerate with test and story files:\npython scripts/component_generator.py UserProfile --with-test --with-story\n\n\n\nGenerate a custom hook:\npython scripts/component_generator.py FormValidation --type hook"
      },
      {
        "title": "Generator Options",
        "body": "OptionDescription--type clientClient component with 'use client' (default)--type serverAsync server component--type hookCustom React hook--with-testInclude test file--with-storyInclude Storybook story--flatCreate in output dir without subdirectory--dry-runPreview without creating files"
      },
      {
        "title": "Generated Component Example",
        "body": "'use client';\n\nimport { useState } from 'react';\nimport { cn } from '@/lib/utils';\n\ninterface ButtonProps {\n  className?: string;\n  children?: React.ReactNode;\n}\n\nexport function Button({ className, children }: ButtonProps) {\n  return (\n    <div className={cn('', className)}>\n      {children}\n    </div>\n  );\n}"
      },
      {
        "title": "Bundle Analysis",
        "body": "Analyze package.json and project structure for bundle optimization opportunities."
      },
      {
        "title": "Workflow: Optimize Bundle Size",
        "body": "Run the analyzer on your project:\npython scripts/bundle_analyzer.py /path/to/project\n\n\n\nReview the health score and issues:\nBundle Health Score: 75/100 (C)\n\nHEAVY DEPENDENCIES:\n  moment (290KB)\n    Alternative: date-fns (12KB) or dayjs (2KB)\n\n  lodash (71KB)\n    Alternative: lodash-es with tree-shaking\n\n\n\nApply the recommended fixes by replacing heavy dependencies.\n\n\nRe-run with verbose mode to check import patterns:\npython scripts/bundle_analyzer.py . --verbose"
      },
      {
        "title": "Bundle Score Interpretation",
        "body": "ScoreGradeAction90-100ABundle is well-optimized80-89BMinor optimizations available70-79CReplace heavy dependencies60-69DMultiple issues need attention0-59FCritical bundle size problems"
      },
      {
        "title": "Heavy Dependencies Detected",
        "body": "The analyzer identifies these common heavy packages:\n\nPackageSizeAlternativemoment290KBdate-fns (12KB) or dayjs (2KB)lodash71KBlodash-es with tree-shakingaxios14KBNative fetch or ky (3KB)jquery87KBNative DOM APIs@mui/materialLargeshadcn/ui or Radix UI"
      },
      {
        "title": "React Patterns",
        "body": "Reference: references/react_patterns.md"
      },
      {
        "title": "Compound Components",
        "body": "Share state between related components:\n\nconst Tabs = ({ children }) => {\n  const [active, setActive] = useState(0);\n  return (\n    <TabsContext.Provider value={{ active, setActive }}>\n      {children}\n    </TabsContext.Provider>\n  );\n};\n\nTabs.List = TabList;\nTabs.Panel = TabPanel;\n\n// Usage\n<Tabs>\n  <Tabs.List>\n    <Tabs.Tab>One</Tabs.Tab>\n    <Tabs.Tab>Two</Tabs.Tab>\n  </Tabs.List>\n  <Tabs.Panel>Content 1</Tabs.Panel>\n  <Tabs.Panel>Content 2</Tabs.Panel>\n</Tabs>"
      },
      {
        "title": "Custom Hooks",
        "body": "Extract reusable logic:\n\nfunction useDebounce<T>(value: T, delay = 500): T {\n  const [debouncedValue, setDebouncedValue] = useState(value);\n\n  useEffect(() => {\n    const timer = setTimeout(() => setDebouncedValue(value), delay);\n    return () => clearTimeout(timer);\n  }, [value, delay]);\n\n  return debouncedValue;\n}\n\n// Usage\nconst debouncedSearch = useDebounce(searchTerm, 300);"
      },
      {
        "title": "Render Props",
        "body": "Share rendering logic:\n\nfunction DataFetcher({ url, render }) {\n  const [data, setData] = useState(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));\n  }, [url]);\n\n  return render({ data, loading });\n}\n\n// Usage\n<DataFetcher\n  url=\"/api/users\"\n  render={({ data, loading }) =>\n    loading ? <Spinner /> : <UserList users={data} />\n  }\n/>"
      },
      {
        "title": "Next.js Optimization",
        "body": "Reference: references/nextjs_optimization_guide.md"
      },
      {
        "title": "Server vs Client Components",
        "body": "Use Server Components by default. Add 'use client' only when you need:\n\nEvent handlers (onClick, onChange)\nState (useState, useReducer)\nEffects (useEffect)\nBrowser APIs\n\n// Server Component (default) - no 'use client'\nasync function ProductPage({ params }) {\n  const product = await getProduct(params.id);  // Server-side fetch\n\n  return (\n    <div>\n      <h1>{product.name}</h1>\n      <AddToCartButton productId={product.id} />  {/* Client component */}\n    </div>\n  );\n}\n\n// Client Component\n'use client';\nfunction AddToCartButton({ productId }) {\n  const [adding, setAdding] = useState(false);\n  return <button onClick={() => addToCart(productId)}>Add</button>;\n}"
      },
      {
        "title": "Image Optimization",
        "body": "import Image from 'next/image';\n\n// Above the fold - load immediately\n<Image\n  src=\"/hero.jpg\"\n  alt=\"Hero\"\n  width={1200}\n  height={600}\n  priority\n/>\n\n// Responsive image with fill\n<div className=\"relative aspect-video\">\n  <Image\n    src=\"/product.jpg\"\n    alt=\"Product\"\n    fill\n    sizes=\"(max-width: 768px) 100vw, 50vw\"\n    className=\"object-cover\"\n  />\n</div>"
      },
      {
        "title": "Data Fetching Patterns",
        "body": "// Parallel fetching\nasync function Dashboard() {\n  const [user, stats] = await Promise.all([\n    getUser(),\n    getStats()\n  ]);\n  return <div>...</div>;\n}\n\n// Streaming with Suspense\nasync function ProductPage({ params }) {\n  return (\n    <div>\n      <ProductDetails id={params.id} />\n      <Suspense fallback={<ReviewsSkeleton />}>\n        <Reviews productId={params.id} />\n      </Suspense>\n    </div>\n  );\n}"
      },
      {
        "title": "Accessibility and Testing",
        "body": "Reference: references/frontend_best_practices.md"
      },
      {
        "title": "Accessibility Checklist",
        "body": "Semantic HTML: Use proper elements (<button>, <nav>, <main>)\nKeyboard Navigation: All interactive elements focusable\nARIA Labels: Provide labels for icons and complex widgets\nColor Contrast: Minimum 4.5:1 for normal text\nFocus Indicators: Visible focus states\n\n// Accessible button\n<button\n  type=\"button\"\n  aria-label=\"Close dialog\"\n  onClick={onClose}\n  className=\"focus-visible:ring-2 focus-visible:ring-blue-500\"\n>\n  <XIcon aria-hidden=\"true\" />\n</button>\n\n// Skip link for keyboard users\n<a href=\"#main-content\" className=\"sr-only focus:not-sr-only\">\n  Skip to main content\n</a>"
      },
      {
        "title": "Testing Strategy",
        "body": "// Component test with React Testing Library\nimport { render, screen } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\ntest('button triggers action on click', async () => {\n  const onClick = vi.fn();\n  render(<Button onClick={onClick}>Click me</Button>);\n\n  await userEvent.click(screen.getByRole('button'));\n  expect(onClick).toHaveBeenCalledTimes(1);\n});\n\n// Test accessibility\ntest('dialog is accessible', async () => {\n  render(<Dialog open={true} title=\"Confirm\" />);\n\n  expect(screen.getByRole('dialog')).toBeInTheDocument();\n  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');\n});"
      },
      {
        "title": "Common Next.js Config",
        "body": "// next.config.js\nconst nextConfig = {\n  images: {\n    remotePatterns: [{ hostname: \"cdnexamplecom\" }],\n    formats: ['image/avif', 'image/webp'],\n  },\n  experimental: {\n    optimizePackageImports: ['lucide-react', '@heroicons/react'],\n  },\n};"
      },
      {
        "title": "Tailwind CSS Utilities",
        "body": "// Conditional classes with cn()\nimport { cn } from '@/lib/utils';\n\n<button className={cn(\n  'px-4 py-2 rounded',\n  variant === 'primary' && 'bg-blue-500 text-white',\n  disabled && 'opacity-50 cursor-not-allowed'\n)} />"
      },
      {
        "title": "TypeScript Patterns",
        "body": "// Props with children\ninterface CardProps {\n  className?: string;\n  children: React.ReactNode;\n}\n\n// Generic component\ninterface ListProps<T> {\n  items: T[];\n  renderItem: (item: T) => React.ReactNode;\n}\n\nfunction List<T>({ items, renderItem }: ListProps<T>) {\n  return <ul>{items.map(renderItem)}</ul>;\n}"
      },
      {
        "title": "Resources",
        "body": "React Patterns: references/react_patterns.md\nNext.js Optimization: references/nextjs_optimization_guide.md\nBest Practices: references/frontend_best_practices.md"
      }
    ],
    "body": "Senior Frontend\n\nFrontend development patterns, performance optimization, and automation tools for React/Next.js applications.\n\nTable of Contents\nProject Scaffolding\nComponent Generation\nBundle Analysis\nReact Patterns\nNext.js Optimization\nAccessibility and Testing\nProject Scaffolding\n\nGenerate a new Next.js or React project with TypeScript, Tailwind CSS, and best practice configurations.\n\nWorkflow: Create New Frontend Project\n\nRun the scaffolder with your project name and template:\n\npython scripts/frontend_scaffolder.py my-app --template nextjs\n\n\nAdd optional features (auth, api, forms, testing, storybook):\n\npython scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api\n\n\nNavigate to the project and install dependencies:\n\ncd my-app && npm install\n\n\nStart the development server:\n\nnpm run dev\n\nScaffolder Options\nOption\tDescription\n--template nextjs\tNext.js 14+ with App Router and Server Components\n--template react\tReact + Vite with TypeScript\n--features auth\tAdd NextAuth.js authentication\n--features api\tAdd React Query + API client\n--features forms\tAdd React Hook Form + Zod validation\n--features testing\tAdd Vitest + Testing Library\n--dry-run\tPreview files without creating them\nGenerated Structure (Next.js)\nmy-app/\n├── app/\n│   ├── layout.tsx        # Root layout with fonts\n│   ├── page.tsx          # Home page\n│   ├── globals.css       # Tailwind + CSS variables\n│   └── api/health/route.ts\n├── components/\n│   ├── ui/               # Button, Input, Card\n│   └── layout/           # Header, Footer, Sidebar\n├── hooks/                # useDebounce, useLocalStorage\n├── lib/                  # utils (cn), constants\n├── types/                # TypeScript interfaces\n├── tailwind.config.ts\n├── next.config.js\n└── package.json\n\nComponent Generation\n\nGenerate React components with TypeScript, tests, and Storybook stories.\n\nWorkflow: Create a New Component\n\nGenerate a client component:\n\npython scripts/component_generator.py Button --dir src/components/ui\n\n\nGenerate a server component:\n\npython scripts/component_generator.py ProductCard --type server\n\n\nGenerate with test and story files:\n\npython scripts/component_generator.py UserProfile --with-test --with-story\n\n\nGenerate a custom hook:\n\npython scripts/component_generator.py FormValidation --type hook\n\nGenerator Options\nOption\tDescription\n--type client\tClient component with 'use client' (default)\n--type server\tAsync server component\n--type hook\tCustom React hook\n--with-test\tInclude test file\n--with-story\tInclude Storybook story\n--flat\tCreate in output dir without subdirectory\n--dry-run\tPreview without creating files\nGenerated Component Example\n'use client';\n\nimport { useState } from 'react';\nimport { cn } from '@/lib/utils';\n\ninterface ButtonProps {\n  className?: string;\n  children?: React.ReactNode;\n}\n\nexport function Button({ className, children }: ButtonProps) {\n  return (\n    <div className={cn('', className)}>\n      {children}\n    </div>\n  );\n}\n\nBundle Analysis\n\nAnalyze package.json and project structure for bundle optimization opportunities.\n\nWorkflow: Optimize Bundle Size\n\nRun the analyzer on your project:\n\npython scripts/bundle_analyzer.py /path/to/project\n\n\nReview the health score and issues:\n\nBundle Health Score: 75/100 (C)\n\nHEAVY DEPENDENCIES:\n  moment (290KB)\n    Alternative: date-fns (12KB) or dayjs (2KB)\n\n  lodash (71KB)\n    Alternative: lodash-es with tree-shaking\n\n\nApply the recommended fixes by replacing heavy dependencies.\n\nRe-run with verbose mode to check import patterns:\n\npython scripts/bundle_analyzer.py . --verbose\n\nBundle Score Interpretation\nScore\tGrade\tAction\n90-100\tA\tBundle is well-optimized\n80-89\tB\tMinor optimizations available\n70-79\tC\tReplace heavy dependencies\n60-69\tD\tMultiple issues need attention\n0-59\tF\tCritical bundle size problems\nHeavy Dependencies Detected\n\nThe analyzer identifies these common heavy packages:\n\nPackage\tSize\tAlternative\nmoment\t290KB\tdate-fns (12KB) or dayjs (2KB)\nlodash\t71KB\tlodash-es with tree-shaking\naxios\t14KB\tNative fetch or ky (3KB)\njquery\t87KB\tNative DOM APIs\n@mui/material\tLarge\tshadcn/ui or Radix UI\nReact Patterns\n\nReference: references/react_patterns.md\n\nCompound Components\n\nShare state between related components:\n\nconst Tabs = ({ children }) => {\n  const [active, setActive] = useState(0);\n  return (\n    <TabsContext.Provider value={{ active, setActive }}>\n      {children}\n    </TabsContext.Provider>\n  );\n};\n\nTabs.List = TabList;\nTabs.Panel = TabPanel;\n\n// Usage\n<Tabs>\n  <Tabs.List>\n    <Tabs.Tab>One</Tabs.Tab>\n    <Tabs.Tab>Two</Tabs.Tab>\n  </Tabs.List>\n  <Tabs.Panel>Content 1</Tabs.Panel>\n  <Tabs.Panel>Content 2</Tabs.Panel>\n</Tabs>\n\nCustom Hooks\n\nExtract reusable logic:\n\nfunction useDebounce<T>(value: T, delay = 500): T {\n  const [debouncedValue, setDebouncedValue] = useState(value);\n\n  useEffect(() => {\n    const timer = setTimeout(() => setDebouncedValue(value), delay);\n    return () => clearTimeout(timer);\n  }, [value, delay]);\n\n  return debouncedValue;\n}\n\n// Usage\nconst debouncedSearch = useDebounce(searchTerm, 300);\n\nRender Props\n\nShare rendering logic:\n\nfunction DataFetcher({ url, render }) {\n  const [data, setData] = useState(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));\n  }, [url]);\n\n  return render({ data, loading });\n}\n\n// Usage\n<DataFetcher\n  url=\"/api/users\"\n  render={({ data, loading }) =>\n    loading ? <Spinner /> : <UserList users={data} />\n  }\n/>\n\nNext.js Optimization\n\nReference: references/nextjs_optimization_guide.md\n\nServer vs Client Components\n\nUse Server Components by default. Add 'use client' only when you need:\n\nEvent handlers (onClick, onChange)\nState (useState, useReducer)\nEffects (useEffect)\nBrowser APIs\n// Server Component (default) - no 'use client'\nasync function ProductPage({ params }) {\n  const product = await getProduct(params.id);  // Server-side fetch\n\n  return (\n    <div>\n      <h1>{product.name}</h1>\n      <AddToCartButton productId={product.id} />  {/* Client component */}\n    </div>\n  );\n}\n\n// Client Component\n'use client';\nfunction AddToCartButton({ productId }) {\n  const [adding, setAdding] = useState(false);\n  return <button onClick={() => addToCart(productId)}>Add</button>;\n}\n\nImage Optimization\nimport Image from 'next/image';\n\n// Above the fold - load immediately\n<Image\n  src=\"/hero.jpg\"\n  alt=\"Hero\"\n  width={1200}\n  height={600}\n  priority\n/>\n\n// Responsive image with fill\n<div className=\"relative aspect-video\">\n  <Image\n    src=\"/product.jpg\"\n    alt=\"Product\"\n    fill\n    sizes=\"(max-width: 768px) 100vw, 50vw\"\n    className=\"object-cover\"\n  />\n</div>\n\nData Fetching Patterns\n// Parallel fetching\nasync function Dashboard() {\n  const [user, stats] = await Promise.all([\n    getUser(),\n    getStats()\n  ]);\n  return <div>...</div>;\n}\n\n// Streaming with Suspense\nasync function ProductPage({ params }) {\n  return (\n    <div>\n      <ProductDetails id={params.id} />\n      <Suspense fallback={<ReviewsSkeleton />}>\n        <Reviews productId={params.id} />\n      </Suspense>\n    </div>\n  );\n}\n\nAccessibility and Testing\n\nReference: references/frontend_best_practices.md\n\nAccessibility Checklist\nSemantic HTML: Use proper elements (<button>, <nav>, <main>)\nKeyboard Navigation: All interactive elements focusable\nARIA Labels: Provide labels for icons and complex widgets\nColor Contrast: Minimum 4.5:1 for normal text\nFocus Indicators: Visible focus states\n// Accessible button\n<button\n  type=\"button\"\n  aria-label=\"Close dialog\"\n  onClick={onClose}\n  className=\"focus-visible:ring-2 focus-visible:ring-blue-500\"\n>\n  <XIcon aria-hidden=\"true\" />\n</button>\n\n// Skip link for keyboard users\n<a href=\"#main-content\" className=\"sr-only focus:not-sr-only\">\n  Skip to main content\n</a>\n\nTesting Strategy\n// Component test with React Testing Library\nimport { render, screen } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\ntest('button triggers action on click', async () => {\n  const onClick = vi.fn();\n  render(<Button onClick={onClick}>Click me</Button>);\n\n  await userEvent.click(screen.getByRole('button'));\n  expect(onClick).toHaveBeenCalledTimes(1);\n});\n\n// Test accessibility\ntest('dialog is accessible', async () => {\n  render(<Dialog open={true} title=\"Confirm\" />);\n\n  expect(screen.getByRole('dialog')).toBeInTheDocument();\n  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');\n});\n\nQuick Reference\nCommon Next.js Config\n// next.config.js\nconst nextConfig = {\n  images: {\n    remotePatterns: [{ hostname: \"cdnexamplecom\" }],\n    formats: ['image/avif', 'image/webp'],\n  },\n  experimental: {\n    optimizePackageImports: ['lucide-react', '@heroicons/react'],\n  },\n};\n\nTailwind CSS Utilities\n// Conditional classes with cn()\nimport { cn } from '@/lib/utils';\n\n<button className={cn(\n  'px-4 py-2 rounded',\n  variant === 'primary' && 'bg-blue-500 text-white',\n  disabled && 'opacity-50 cursor-not-allowed'\n)} />\n\nTypeScript Patterns\n// Props with children\ninterface CardProps {\n  className?: string;\n  children: React.ReactNode;\n}\n\n// Generic component\ninterface ListProps<T> {\n  items: T[];\n  renderItem: (item: T) => React.ReactNode;\n}\n\nfunction List<T>({ items, renderItem }: ListProps<T>) {\n  return <ul>{items.map(renderItem)}</ul>;\n}\n\nResources\nReact Patterns: references/react_patterns.md\nNext.js Optimization: references/nextjs_optimization_guide.md\nBest Practices: references/frontend_best_practices.md"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/alirezarezvani/senior-frontend",
    "publisherUrl": "https://clawhub.ai/alirezarezvani/senior-frontend",
    "owner": "alirezarezvani",
    "version": "2.1.1",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/senior-frontend",
    "downloadUrl": "https://openagent3.xyz/downloads/senior-frontend",
    "agentUrl": "https://openagent3.xyz/skills/senior-frontend/agent",
    "manifestUrl": "https://openagent3.xyz/skills/senior-frontend/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/senior-frontend/agent.md"
  }
}