The interface is localized. Skill descriptions and documents are machine-translated by AI into your language; code, commands, paths and technical terms stay in the original, and the author's document governs.
Explore skills
Design & creative · SKILL.md

senior-frontend

senior-frontend

Skill de desenvolvimento frontend para aplicações React, Next.js, TypeScript e Tailwind CSS. Use quando construir componentes React, otimizar performance no Next.js, analisar tamanhos de bundle, criar scaffolding de projetos frontend, implementar acessibilidade ou revisar qualidade de código frontend.

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill documentation

GitHub

name: "senior-frontend" description: "Skill de desenvolvimento frontend para aplicações React, Next.js, TypeScript e Tailwind CSS. Use quando construir componentes React, otimizar performance no Next.js, analisar tamanhos de bundle, criar scaffolding de projetos frontend, implementar acessibilidade ou revisar qualidade de código frontend." agents:

  • claude-code

Desenvolvedor Frontend Sênior

Padrões de desenvolvimento frontend, otimização de performance e ferramentas de automação para aplicações React/Next.js.

Sumário


Scaffolding de Projeto

Gere um novo projeto Next.js ou React com TypeScript, Tailwind CSS e configurações de melhores práticas.

Workflow: Criar Novo Projeto Frontend

  1. Execute o scaffolder com o nome e template do projeto:

    python scripts/frontend_scaffolder.py my-app --template nextjs
    
  2. Adicione funcionalidades opcionais (auth, api, forms, testing, storybook):

    python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api
    
  3. Navegue até o projeto e instale as dependências:

    cd my-app && npm install
    
  4. Inicie o servidor de desenvolvimento:

    npm run dev
    

Opções do Scaffolder

OpçãoDescrição
--template nextjsNext.js 14+ com App Router e Server Components
--template reactReact + Vite com TypeScript
--features authAdicionar autenticação NextAuth.js
--features apiAdicionar React Query + cliente de API
--features formsAdicionar React Hook Form + validação Zod
--features testingAdicionar Vitest + Testing Library
--dry-runPré-visualizar arquivos sem criá-los

Estrutura Gerada (Next.js)

my-app/
├── app/
│   ├── layout.tsx        # Layout raiz com fontes
│   ├── page.tsx          # Página inicial
│   ├── globals.css       # Tailwind + variáveis CSS
│   └── api/health/route.ts
├── components/
│   ├── ui/               # Button, Input, Card
│   └── layout/           # Header, Footer, Sidebar
├── hooks/                # useDebounce, useLocalStorage
├── lib/                  # utils (cn), constants
├── types/                # interfaces TypeScript
├── tailwind.config.ts
├── next.config.js
└── package.json

Geração de Componentes

Gere componentes React com TypeScript, testes e stories Storybook.

Workflow: Criar um Novo Componente

  1. Gere um componente client:

    python scripts/component_generator.py Button --dir src/components/ui
    
  2. Gere um componente server:

    python scripts/component_generator.py ProductCard --type server
    
  3. Gere com arquivos de teste e story:

    python scripts/component_generator.py UserProfile --with-test --with-story
    
  4. Gere um hook customizado:

    python scripts/component_generator.py FormValidation --type hook
    

Opções do Generator

OpçãoDescrição
--type clientComponente client com 'use client' (padrão)
--type serverComponente server assíncrono
--type hookHook React customizado
--with-testIncluir arquivo de teste
--with-storyIncluir story do Storybook
--flatCriar no diretório de saída sem subdiretório
--dry-runPré-visualizar sem criar arquivos

Exemplo de Componente Gerado

'use client';

import { useState } from 'react';
import { cn } from '@/lib/utils';

interface ButtonProps {
  className?: string;
  children?: React.ReactNode;
}

export function Button({ className, children }: ButtonProps) {
  return (
    <div className={cn('', className)}>
      {children}
    </div>
  );
}

Análise de Bundle

Analise package.json e a estrutura do projeto para encontrar oportunidades de otimização de bundle.

Workflow: Otimizar Tamanho do Bundle

  1. Execute o analyzer no seu projeto:

    python scripts/bundle_analyzer.py /path/to/project
    
  2. Revise o score de saúde e os problemas:

    Bundle Health Score: 75/100 (C)
    
    DEPENDÊNCIAS PESADAS:
      moment (290KB)
        Alternativa: date-fns (12KB) ou dayjs (2KB)
    
      lodash (71KB)
        Alternativa: lodash-es com tree-shaking
    
  3. Aplique as correções recomendadas substituindo dependências pesadas.

  4. Re-execute com modo verbose para verificar padrões de importação:

    python scripts/bundle_analyzer.py . --verbose
    

Interpretação do Score do Bundle

ScoreNotaAção
90-100ABundle bem otimizado
80-89BPequenas otimizações disponíveis
70-79CSubstituir dependências pesadas
60-69DMúltiplos problemas precisam de atenção
0-59FProblemas críticos de tamanho de bundle

Dependências Pesadas Detectadas

O analyzer identifica estes pacotes comuns pesados:

PacoteTamanhoAlternativa
moment290KBdate-fns (12KB) ou dayjs (2KB)
lodash71KBlodash-es com tree-shaking
axios14KBfetch nativo ou ky (3KB)
jquery87KBAPIs DOM nativas
@mui/materialGrandeshadcn/ui ou Radix UI

Padrões React

Referência: references/react_patterns.md

Compound Components

Compartilhar estado entre componentes relacionados:

const Tabs = ({ children }) => {
  const [active, setActive] = useState(0);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
};

Tabs.List = TabList;
Tabs.Panel = TabPanel;

// Uso
<Tabs>
  <Tabs.List>
    <Tabs.Tab>Um</Tabs.Tab>
    <Tabs.Tab>Dois</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel>Conteúdo 1</Tabs.Panel>
  <Tabs.Panel>Conteúdo 2</Tabs.Panel>
</Tabs>

Custom Hooks

Extrair lógica reutilizável:

function useDebounce<T>(value: T, delay = 500): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

// Uso
const debouncedSearch = useDebounce(searchTerm, 300);

Render Props

Compartilhar lógica de renderização:

function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));
  }, [url]);

  return render({ data, loading });
}

// Uso
<DataFetcher
  url="/api/users"
  render={({ data, loading }) =>
    loading ? <Spinner /> : <UserList users={data} />
  }
/>

Otimização Next.js

Referência: references/nextjs_optimization_guide.md

Server vs Client Components

Use Server Components por padrão. Adicione 'use client' somente quando precisar de:

  • Handlers de eventos (onClick, onChange)
  • Estado (useState, useReducer)
  • Effects (useEffect)
  • APIs do browser
// Server Component (padrão) - sem 'use client'
async function ProductPage({ params }) {
  const product = await getProduct(params.id);  // fetch server-side

  return (
    <div>
      <h1>{product.name}</h1>
      <AddToCartButton productId={product.id} />  {/* componente client */}
    </div>
  );
}

// Client Component
'use client';
function AddToCartButton({ productId }) {
  const [adding, setAdding] = useState(false);
  return <button onClick={() => addToCart(productId)}>Adicionar</button>;
}

Otimização de Imagens

import Image from 'next/image';

// Acima da dobra - carregamento imediato
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority
/>

// Imagem responsiva com fill
<div className="relative aspect-video">
  <Image
    src="/product.jpg"
    alt="Produto"
    fill
    sizes="(max-width: 768px) 100vw, 50vw"
    className="object-cover"
  />
</div>

Padrões de Busca de Dados

// Busca em paralelo
async function Dashboard() {
  const [user, stats] = await Promise.all([
    getUser(),
    getStats()
  ]);
  return <div>...</div>;
}

// Streaming com Suspense
async function ProductPage({ params }) {
  return (
    <div>
      <ProductDetails id={params.id} />
      <Suspense fallback={<ReviewsSkeleton />}>
        <Reviews productId={params.id} />
      </Suspense>
    </div>
  );
}

Acessibilidade e Testes

Referência: references/frontend_best_practices.md

Checklist de Acessibilidade

  1. HTML Semântico: Use elementos adequados (<button>, <nav>, <main>)
  2. Navegação por Teclado: Todos os elementos interativos devem ser focusáveis
  3. Labels ARIA: Forneça labels para ícones e widgets complexos
  4. Contraste de Cores: Mínimo 4.5:1 para texto normal
  5. Indicadores de Foco: Estados de foco visíveis
// Botão acessível
<button
  type="button"
  aria-label="Fechar diálogo"
  onClick={onClose}
  className="focus-visible:ring-2 focus-visible:ring-blue-500"
>
  <XIcon aria-hidden="true" />
</button>

// Skip link para usuários de teclado
<a href="#main-content" className="sr-only focus:not-sr-only">
  Pular para o conteúdo principal
</a>

Estratégia de Testes

// Teste de componente com React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('botão dispara ação ao clicar', async () => {
  const onClick = vi.fn();
  render(<Button onClick={onClick}>Clique aqui</Button>);

  await userEvent.click(screen.getByRole('button'));
  expect(onClick).toHaveBeenCalledTimes(1);
});

// Testar acessibilidade
test('diálogo é acessível', async () => {
  render(<Dialog open={true} title="Confirmar" />);

  expect(screen.getByRole('dialog')).toBeInTheDocument();
  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');
});

Referência Rápida

Configuração Comum do Next.js

// next.config.js
const nextConfig = {
  images: {
    remotePatterns: [{ hostname: "cdnexamplecom" }],
    formats: ['image/avif', 'image/webp'],
  },
  experimental: {
    optimizePackageImports: ['lucide-react', '@heroicons/react'],
  },
};

Utilitários Tailwind CSS

// Classes condicionais com cn()
import { cn } from '@/lib/utils';

<button className={cn(
  'px-4 py-2 rounded',
  variant === 'primary' && 'bg-blue-500 text-white',
  disabled && 'opacity-50 cursor-not-allowed'
)} />

Padrões TypeScript

// Props com children
interface CardProps {
  className?: string;
  children: React.ReactNode;
}

// Componente genérico
interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
}

function List<T>({ items, renderItem }: ListProps<T>) {
  return <ul>{items.map(renderItem)}</ul>;
}

Recursos

  • Padrões React: references/react_patterns.md
  • Otimização Next.js: references/nextjs_optimization_guide.md
  • Melhores Práticas: references/frontend_best_practices.md
Saved skills