Files
claude-plugins/dev-tools/skills/nextjs/SKILL.md
T
ealmeida faef9b47dc fix(project-manager): remover Dify KB das descriptions, marcar nota TODO
Dify foi removido 06-03-2026. Skills brainstorm/discover ainda referenciam-no
no corpo. Bump v1.2 + nota top-of-file. Reescrita workflow para próxima sessão.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 04:52:03 +01:00

4.9 KiB

name, description
name description
nextjs Desenvolvimento Next.js moderno (13+) com App Router, Server Components, rotas API e deployment seguindo padroes Descomplicar.

/nextjs - Next.js Development

Desenvolvimento Next.js moderno (13+) com App Router e Server Components.


Contexto NotebookLM

mcp__notebooklm__notebook_query({
  notebook_id: "24947ffa-0019-448a-a340-2f4a275d2eb1",
  query: "<adaptar ao contexto do pedido>"
})

Regra #48 - Dev Container (OBRIGATÓRIO)

TODOS os projectos Next.js devem ser desenvolvidos no container dev.

SSH:  server="dev"  (mcp__ssh-unified__ssh_execute)
Path: /root/Dev/<projecto>
Sync: auto -> /media/ealmeida/Dados/Dev/<projecto> (Syncthing)

Workflow:

  1. mcp__ssh-unified__ssh_execute server:"dev" command:"mkdir -p /root/Dev/<projecto>"
  2. Desenvolver e testar no container
  3. npm run build no container antes de deploy
  4. Deploy via EasyPanel
  5. Syncthing propaga automaticamente

NUNCA: npx create-next-app directamente no PC local para projectos colaborativos.


App Router Structure

app/
├── layout.tsx          # Root layout (obrigatório)
├── page.tsx            # Home page
├── loading.tsx         # Loading UI (Suspense)
├── error.tsx           # Error boundary
├── not-found.tsx       # 404 page
├── (auth)/             # Route group (não afecta URL)
│   ├── login/page.tsx
│   └── register/page.tsx
├── dashboard/
│   ├── layout.tsx
│   ├── page.tsx
│   └── [id]/page.tsx   # Dynamic route
└── api/route.ts        # API route

Server vs Client Components

Server Component (default)

async function ProductsPage() {
  const products = await db.product.findMany();
  return <div>{products.map(p => <ProductCard key={p.id} product={p} />)}</div>;
}

Client Component

'use client';
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Data Fetching Patterns

// Static (SSG) - default
const data = await fetch('https://api.example.com/data', { cache: 'force-cache' });

// Dynamic (SSR)
const data = await fetch('https://api.example.com/data', { cache: 'no-store' });

// ISR - revalidação automática
const data = await fetch('https://api.example.com/data', { next: { revalidate: 60 } });

Server Actions

// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';

export async function createPost(formData: FormData) {
  const title = formData.get('title') as string;
  await db.post.create({ data: { title } });
  revalidatePath('/posts');
}

// Uso no form:
<form action={createPost}>
  <input name="title" required />
  <button type="submit">Create</button>
</form>

Routing Avançado

Middleware

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token');
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}

export const config = { matcher: ['/dashboard/:path*'] };

Optimizações

Images

import Image from 'next/image';
<Image src="/photo.jpg" width={500} height={300} alt="Photo" priority />

Metadata (SEO)

export const metadata = {
  title: 'Home',
  description: 'Home page',
  openGraph: { title: 'Home', images: ['/og-image.jpg'] },
};

Performance (Prioridades)

Prioridade Categoria Ganho
CRITICAL Eliminar Waterfalls (Promise.all) 2-10x latência
CRITICAL Bundle Size (dynamic imports) 200-800ms load
HIGH Server-Side (auth actions, React.cache) RSC payload
MEDIUM Re-renders (derived state, functional setState) Responsividade

Para todas as 57 regras com exemplos de código: ver references/performance-rules.md


Deployment

Docker

FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package*.json ./
RUN npm ci --production
EXPOSE 3000
CMD ["npm", "start"]

Datasets Dify

Dataset ID
Desenvolvimento de Software e7c7decc-0ded-4351-ab14-b110b3c38ec9
TI 7f63ec0c-6321-488c-b107-980140199850

Referências

  • references/performance-rules.md - 57 regras de performance com exemplos completos

Versão 1.0.0 | Descomplicar®


Healing Log

Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.

{"date":"","issue":"","fix":"","source":"user|auto"}

Adicionar nova linha após cada erro corrigido.