feat: adiciona 12 plugins Descomplicar ao marketplace
Plugins: automacao, crm-ops, design-media, dev-tools, gestao, infraestrutura, marketing, negocio, perfex-dev, project-manager, wordpress + hello-plugin (existente). Totais: 83 skills, 44 agents, 12 datasets.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
722
dev-tools/skills/nextjs/SKILL.md
Normal file
722
dev-tools/skills/nextjs/SKILL.md
Normal file
@@ -0,0 +1,722 @@
|
||||
---
|
||||
name: nextjs
|
||||
description: Next.js development best practices and patterns. App router, server components,
|
||||
API routes, and deployment. Use when user mentions "nextjs", "next.js", "react server",
|
||||
"app router", "next deployment".
|
||||
author: Descomplicar® Crescimento Digital
|
||||
version: 2.0.0
|
||||
quality_score: 75
|
||||
user_invocable: true
|
||||
allowed-tools: Glob
|
||||
---
|
||||
|
||||
# /nextjs - Next.js Development
|
||||
|
||||
Desenvolvimento Next.js moderno (13+) com App Router e Server Components.
|
||||
|
||||
## Quando Usar
|
||||
|
||||
- Criar aplicações Next.js
|
||||
- Migrar de Pages para App Router
|
||||
- Implementar Server Components
|
||||
- Configurar Server Actions
|
||||
- Optimizar SEO e performance
|
||||
|
||||
## 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
|
||||
├── globals.css # Global styles
|
||||
├── (auth)/ # Route group (não afecta URL)
|
||||
│ ├── login/page.tsx
|
||||
│ └── register/page.tsx
|
||||
├── dashboard/
|
||||
│ ├── layout.tsx # Nested layout
|
||||
│ ├── page.tsx
|
||||
│ └── [id]/
|
||||
│ └── page.tsx # Dynamic route
|
||||
└── api/
|
||||
└── route.ts # API route
|
||||
```
|
||||
|
||||
## Server vs Client Components
|
||||
|
||||
### Server Component (default)
|
||||
|
||||
```tsx
|
||||
// ✅ PADRÃO - Runs on server
|
||||
async function ProductsPage() {
|
||||
// Pode fazer fetch directo
|
||||
const products = await db.product.findMany();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{products.map(p => (
|
||||
<ProductCard key={p.id} product={p} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductsPage;
|
||||
```
|
||||
|
||||
**Vantagens:**
|
||||
- Acesso directo a BD
|
||||
- Menos JavaScript no cliente
|
||||
- SEO melhor
|
||||
- Dados sempre frescos
|
||||
|
||||
### Client Component
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
// ✅ Para interactividade
|
||||
function Counter() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
return (
|
||||
<button onClick={() => setCount(c => c + 1)}>
|
||||
{count}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Quando usar:**
|
||||
- useState, useEffect, useContext
|
||||
- Event listeners (onClick, onChange)
|
||||
- Browser APIs (localStorage, window)
|
||||
- Custom hooks
|
||||
|
||||
## Data Fetching Patterns
|
||||
|
||||
### 1. Static (SSG)
|
||||
|
||||
```tsx
|
||||
// Default behaviour - cache infinito
|
||||
async function Page() {
|
||||
const data = await fetch('https://api.example.com/data', {
|
||||
cache: 'force-cache' // Explícito (mas é default)
|
||||
});
|
||||
|
||||
return <div>{data.title}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Dynamic (SSR)
|
||||
|
||||
```tsx
|
||||
// Sempre fetch fresco
|
||||
async function Page() {
|
||||
const data = await fetch('https://api.example.com/data', {
|
||||
cache: 'no-store' // NUNCA cache
|
||||
});
|
||||
|
||||
return <div>{data.title}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Revalidate (ISR)
|
||||
|
||||
```tsx
|
||||
// Cache com revalidação automática
|
||||
async function Page() {
|
||||
const data = await fetch('https://api.example.com/data', {
|
||||
next: { revalidate: 60 } // Revalida a cada 60s
|
||||
});
|
||||
|
||||
return <div>{data.title}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
## Server Actions
|
||||
|
||||
```tsx
|
||||
// app/actions.ts
|
||||
'use server';
|
||||
|
||||
import { revalidatePath } from 'next/cache';
|
||||
import { db } from '@/lib/db';
|
||||
|
||||
export async function createPost(formData: FormData) {
|
||||
const title = formData.get('title') as string;
|
||||
const content = formData.get('content') as string;
|
||||
|
||||
await db.post.create({
|
||||
data: { title, content }
|
||||
});
|
||||
|
||||
revalidatePath('/posts');
|
||||
}
|
||||
|
||||
// app/create-post/page.tsx
|
||||
import { createPost } from '@/app/actions';
|
||||
|
||||
export default function CreatePost() {
|
||||
return (
|
||||
<form action={createPost}>
|
||||
<input name="title" required />
|
||||
<textarea name="content" required />
|
||||
<button type="submit">Create</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Layouts e Loading States
|
||||
|
||||
### Root Layout
|
||||
|
||||
```tsx
|
||||
// app/layout.tsx
|
||||
import './globals.css';
|
||||
import { Inter } from 'next/font/google';
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] });
|
||||
|
||||
export const metadata = {
|
||||
title: 'My App',
|
||||
description: 'Description'
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="pt">
|
||||
<body className={inter.className}>
|
||||
<nav>...</nav>
|
||||
{children}
|
||||
<footer>...</footer>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Loading UI
|
||||
|
||||
```tsx
|
||||
// app/dashboard/loading.tsx
|
||||
export default function Loading() {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
// Wrapper automático em <Suspense>
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```tsx
|
||||
// app/error.tsx
|
||||
'use client';
|
||||
|
||||
export default function Error({
|
||||
error,
|
||||
reset
|
||||
}: {
|
||||
error: Error;
|
||||
reset: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<h2>Something went wrong!</h2>
|
||||
<button onClick={reset}>Try again</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Routing Avançado
|
||||
|
||||
### Parallel Routes
|
||||
|
||||
```tsx
|
||||
// app/layout.tsx
|
||||
export default function Layout({
|
||||
children,
|
||||
modal,
|
||||
sidebar
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
modal: React.ReactNode;
|
||||
sidebar: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{sidebar}
|
||||
{children}
|
||||
{modal}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// app/@sidebar/page.tsx
|
||||
// app/@modal/page.tsx
|
||||
```
|
||||
|
||||
### Intercepting Routes
|
||||
|
||||
```tsx
|
||||
// app/feed/page.tsx - Lista de fotos
|
||||
// app/photo/[id]/page.tsx - Página completa da foto
|
||||
// app/@modal/(.)photo/[id]/page.tsx - Modal da foto (intercepta)
|
||||
|
||||
// Navegar via <Link> abre modal
|
||||
// Refresh ou URL directo abre página completa
|
||||
```
|
||||
|
||||
## Middleware
|
||||
|
||||
```tsx
|
||||
// middleware.ts
|
||||
import { NextResponse } from 'next/server';
|
||||
import type { NextRequest } from 'next/server';
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
const token = request.cookies.get('token');
|
||||
|
||||
// Auth guard
|
||||
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
|
||||
return NextResponse.redirect(new URL('/login', request.url));
|
||||
}
|
||||
|
||||
// Custom header
|
||||
const response = NextResponse.next();
|
||||
response.headers.set('x-custom-header', 'value');
|
||||
return response;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ['/dashboard/:path*', '/api/:path*']
|
||||
};
|
||||
```
|
||||
|
||||
## Performance Rules (Vercel Engineering)
|
||||
|
||||
57 regras priorizadas por impacto. Fonte: Vercel Engineering react-best-practices.
|
||||
|
||||
### 1. Eliminating Waterfalls (CRITICAL)
|
||||
|
||||
```tsx
|
||||
// ❌ ERRADO: Awaits sequenciais (waterfall)
|
||||
const session = await getSession()
|
||||
const config = await getConfig()
|
||||
const user = await getUser(session.userId)
|
||||
|
||||
// ✅ CORRECTO: Paralelo com Promise.all()
|
||||
const [session, config] = await Promise.all([
|
||||
getSession(),
|
||||
getConfig()
|
||||
])
|
||||
const user = await getUser(session.userId) // depende de session
|
||||
|
||||
// ✅ CORRECTO: Suspense boundaries estratégicos
|
||||
async function Page() {
|
||||
return (
|
||||
<Layout>
|
||||
<Suspense fallback={<HeaderSkeleton />}>
|
||||
<Header />
|
||||
</Suspense>
|
||||
<Suspense fallback={<ContentSkeleton />}>
|
||||
<SlowContent />
|
||||
</Suspense>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
// ✅ CORRECTO: Defer await até necessário
|
||||
async function handler(req) {
|
||||
const dataPromise = fetchData() // inicia imediatamente
|
||||
if (req.method === 'HEAD') return new Response() // early return sem await
|
||||
const data = await dataPromise // só espera quando precisa
|
||||
return Response.json(data)
|
||||
}
|
||||
```
|
||||
|
||||
**Regras:**
|
||||
- `async-defer-await`: Mover await para onde é realmente necessário
|
||||
- `async-dependency-parallel`: Usar `better-all` para dependências parciais
|
||||
- `async-prevent-waterfall`: Iniciar promises antes de awaitar
|
||||
- `async-promise-all`: `Promise.all()` para operações independentes
|
||||
- `async-suspense-boundaries`: Suspense para UI progressiva
|
||||
|
||||
### 2. Bundle Size (CRITICAL)
|
||||
|
||||
```tsx
|
||||
// ❌ ERRADO: Barrel file imports
|
||||
import { Button, Icon } from '@mui/material' // carrega tudo
|
||||
|
||||
// ✅ CORRECTO: Import directo
|
||||
import Button from '@mui/material/Button'
|
||||
|
||||
// ✅ CORRECTO: optimizePackageImports (Next.js 13.5+)
|
||||
// next.config.js
|
||||
module.exports = {
|
||||
experimental: {
|
||||
optimizePackageImports: ['lucide-react', '@mui/material', 'lodash']
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ CORRECTO: Dynamic imports para componentes pesados
|
||||
const MonacoEditor = dynamic(() => import('./MonacoEditor'), {
|
||||
ssr: false,
|
||||
loading: () => <EditorSkeleton />
|
||||
})
|
||||
|
||||
// ✅ CORRECTO: Preload em hover/focus
|
||||
function FeatureButton() {
|
||||
return (
|
||||
<button
|
||||
onMouseEnter={() => import('./HeavyFeature')}
|
||||
onClick={openFeature}
|
||||
>
|
||||
Open Feature
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Regras:**
|
||||
- `bundle-barrel-imports`: Evitar barrel files (index.js re-exports)
|
||||
- `bundle-conditional-loading`: Carregar módulos só quando feature activa
|
||||
- `bundle-defer-third-party`: `next/dynamic` com `ssr: false` para analytics
|
||||
- `bundle-dynamic-imports`: Lazy-load componentes pesados (>50KB)
|
||||
- `bundle-preload-intent`: Preload em hover para UX instantânea
|
||||
|
||||
### 3. Server-Side Performance (HIGH)
|
||||
|
||||
```tsx
|
||||
// ✅ Server Actions: autenticar SEMPRE (são endpoints públicos!)
|
||||
'use server'
|
||||
async function updateProfile(formData: FormData) {
|
||||
const session = await auth() // 1. Autenticar
|
||||
if (!session) throw new Error('Unauthorized')
|
||||
const data = schema.parse(formData) // 2. Validar input
|
||||
await db.user.update({ where: { id: session.userId }, data }) // 3. Executar
|
||||
revalidatePath('/profile')
|
||||
}
|
||||
|
||||
// ✅ Minimizar serialização RSC - só campos necessários
|
||||
async function UserCard({ userId }: { userId: string }) {
|
||||
const user = await db.user.findUnique({ where: { id: userId } })
|
||||
// Passa só o necessário, não o objecto inteiro com 50+ campos
|
||||
return <ClientCard name={user.name} avatar={user.avatar} />
|
||||
}
|
||||
|
||||
// ✅ React.cache() para deduplicação per-request
|
||||
const getUser = cache(async (id: string) => {
|
||||
return db.user.findUnique({ where: { id } })
|
||||
})
|
||||
|
||||
// ✅ after() para operações não-bloqueantes
|
||||
import { after } from 'next/server'
|
||||
async function submitForm(data: FormData) {
|
||||
const result = await processForm(data)
|
||||
after(async () => {
|
||||
await logAnalytics(result) // executa APÓS resposta enviada
|
||||
})
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
**Regras:**
|
||||
- `server-auth-actions`: Autenticar Server Actions como API routes
|
||||
- `server-avoid-duplicate-serialization`: Transformar dados no cliente
|
||||
- `server-lru-cache`: LRUCache para dados cross-request
|
||||
- `server-minimize-serialization`: Só campos necessários em RSC props
|
||||
- `server-parallel-composition`: Composição paralela de Server Components
|
||||
- `server-react-cache`: `React.cache()` para deduplicação per-request
|
||||
- `server-after`: `after()` para logging/analytics não-bloqueante
|
||||
|
||||
### 4. Client-Side Data Fetching (MEDIUM-HIGH)
|
||||
|
||||
```tsx
|
||||
// ✅ SWR para deduplicação automática
|
||||
const { data, isLoading } = useSWR('/api/user', fetcher)
|
||||
|
||||
// ✅ Passive event listeners para scroll performance
|
||||
element.addEventListener('scroll', handler, { passive: true })
|
||||
|
||||
// ✅ localStorage versionado com try-catch
|
||||
const key = 'userConfig:v2'
|
||||
try {
|
||||
const data = JSON.parse(localStorage.getItem(key) ?? '{}')
|
||||
} catch { /* incognito mode, quota exceeded */ }
|
||||
```
|
||||
|
||||
### 5. Re-render Optimization (MEDIUM)
|
||||
|
||||
```tsx
|
||||
// ✅ Derived state: calcular durante render, NÃO em useEffect
|
||||
function FilteredList({ items, query }: Props) {
|
||||
const filtered = items.filter(i => i.name.includes(query)) // derive!
|
||||
return <List items={filtered} />
|
||||
}
|
||||
|
||||
// ✅ Functional setState para evitar stale closures
|
||||
setItems(curr => [...curr, ...newItems]) // ✅
|
||||
// setItems([...items, ...newItems]) // ❌ stale closure
|
||||
|
||||
// ✅ Lazy state initialization
|
||||
const [index] = useState(() => buildSearchIndex(items)) // computa 1x
|
||||
|
||||
// ✅ useTransition para updates não-urgentes
|
||||
const [isPending, startTransition] = useTransition()
|
||||
startTransition(() => setSearchResults(results))
|
||||
|
||||
// ✅ Extrair defaults não-primitivos para module scope
|
||||
const EMPTY_ARRAY: string[] = [] // ✅ fora do componente
|
||||
const NOOP = () => {} // ✅ fora do componente
|
||||
function Component({ items = EMPTY_ARRAY, onClick = NOOP }) { ... }
|
||||
|
||||
// ✅ Dependências de effect: primitivos, não objectos
|
||||
useEffect(() => { fetchUser(userId) }, [userId]) // ✅ primitivo
|
||||
// useEffect(() => { ... }, [user]) // ❌ objecto = nova ref cada render
|
||||
```
|
||||
|
||||
### 6. Rendering Performance (MEDIUM)
|
||||
|
||||
```tsx
|
||||
// ✅ CSS content-visibility para listas longas
|
||||
// .message { content-visibility: auto; contain-intrinsic-size: 0 80px; }
|
||||
|
||||
// ✅ Hoist static JSX fora do componente
|
||||
const skeleton = <div className="skeleton h-4 w-full" /> // module scope
|
||||
|
||||
// ✅ Conditional rendering explícito (evitar && com falsy)
|
||||
{count > 0 ? <Badge>{count}</Badge> : null} // ✅
|
||||
// {count && <Badge>{count}</Badge>} // ❌ renderiza "0"
|
||||
|
||||
// ✅ useTransition em vez de useState manual para loading
|
||||
const [isPending, startTransition] = useTransition()
|
||||
// const [isLoading, setIsLoading] = useState(false) // ❌ manual
|
||||
|
||||
// ✅ Hydration: inline script para evitar flicker
|
||||
// <script dangerouslySetInnerHTML={{ __html: `
|
||||
// document.documentElement.classList.add(
|
||||
// localStorage.getItem('theme') === 'dark' ? 'dark' : 'light'
|
||||
// )
|
||||
// `}} />
|
||||
```
|
||||
|
||||
### 7. JavaScript Performance (LOW-MEDIUM)
|
||||
|
||||
```tsx
|
||||
// ✅ Index Maps para lookups repetidos O(1) vs O(n)
|
||||
const userMap = new Map(users.map(u => [u.id, u]))
|
||||
orders.map(o => ({ ...o, user: userMap.get(o.userId) }))
|
||||
|
||||
// ✅ Set para membership checks
|
||||
const allowedIds = new Set(['a', 'b', 'c'])
|
||||
if (allowedIds.has(id)) { ... } // O(1) vs .includes() O(n)
|
||||
|
||||
// ✅ toSorted() para imutabilidade (React-safe)
|
||||
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name))
|
||||
// items.sort() // ❌ muta o array original
|
||||
|
||||
// ✅ Early return para evitar processamento desnecessário
|
||||
function validate(items: Item[]) {
|
||||
for (const item of items) {
|
||||
if (!item.valid) return { error: item.id } // sai cedo
|
||||
}
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
// ✅ Combinar iterações de array
|
||||
const { active, expired } = items.reduce((acc, item) => {
|
||||
if (item.active) acc.active.push(item)
|
||||
else acc.expired.push(item)
|
||||
return acc
|
||||
}, { active: [], expired: [] })
|
||||
// Em vez de items.filter(active) + items.filter(expired) = 2 iterações
|
||||
```
|
||||
|
||||
### 8. Advanced Patterns (LOW)
|
||||
|
||||
```tsx
|
||||
// ✅ Init uma vez, não por mount (Strict Mode remonta)
|
||||
let didInit = false
|
||||
function App() {
|
||||
useEffect(() => {
|
||||
if (didInit) return
|
||||
didInit = true
|
||||
initializeAnalytics()
|
||||
}, [])
|
||||
}
|
||||
|
||||
// ✅ useEffectEvent para callbacks estáveis em effects
|
||||
const onTick = useEffectEvent((value) => {
|
||||
console.log(value) // sempre valor mais recente
|
||||
})
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => onTick(count), 1000)
|
||||
return () => clearInterval(id)
|
||||
}, []) // sem dependência de count!
|
||||
```
|
||||
|
||||
### Resumo de Impacto
|
||||
|
||||
| Prioridade | Categoria | Regras | Ganho |
|
||||
|---|---|---|---|
|
||||
| CRITICAL | Waterfalls | 5 | 2-10x latência |
|
||||
| CRITICAL | Bundle Size | 5 | 200-800ms load |
|
||||
| HIGH | Server-Side | 7 | RSC payload, TTI |
|
||||
| MEDIUM-HIGH | Client Fetch | 4 | Request dedup |
|
||||
| MEDIUM | Re-renders | 12 | UI responsiveness |
|
||||
| MEDIUM | Rendering | 9 | Paint performance |
|
||||
| LOW-MEDIUM | JS Perf | 12 | CPU cycles |
|
||||
| LOW | Advanced | 3 | Init correctness |
|
||||
|
||||
---
|
||||
|
||||
## Optimizações
|
||||
|
||||
### Images
|
||||
|
||||
```tsx
|
||||
import Image from 'next/image';
|
||||
|
||||
<Image
|
||||
src="/photo.jpg"
|
||||
width={500}
|
||||
height={300}
|
||||
alt="Photo"
|
||||
priority // LCP image
|
||||
placeholder="blur"
|
||||
blurDataURL="data:image/..."
|
||||
/>
|
||||
```
|
||||
|
||||
### Fonts
|
||||
|
||||
```tsx
|
||||
import { Inter, Roboto_Mono } from 'next/font/google';
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ['latin'],
|
||||
display: 'swap',
|
||||
});
|
||||
|
||||
const robotoMono = Roboto_Mono({
|
||||
subsets: ['latin'],
|
||||
weight: ['400', '700'],
|
||||
});
|
||||
```
|
||||
|
||||
### Metadata (SEO)
|
||||
|
||||
```tsx
|
||||
// app/page.tsx
|
||||
export const metadata = {
|
||||
title: 'Home',
|
||||
description: 'Home page',
|
||||
openGraph: {
|
||||
title: 'Home',
|
||||
description: 'Home page',
|
||||
images: ['/og-image.jpg'],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Vercel (recomendado)
|
||||
|
||||
```bash
|
||||
npm install -g vercel
|
||||
vercel
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```dockerfile
|
||||
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"]
|
||||
```
|
||||
|
||||
### Static Export
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
module.exports = {
|
||||
output: 'export',
|
||||
trailingSlash: true,
|
||||
};
|
||||
```
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# Output: out/
|
||||
```
|
||||
|
||||
## Datasets Dify
|
||||
|
||||
| Dataset | ID | Prioridade |
|
||||
|---------|----|-----------:|
|
||||
| **Desenvolvimento de Software** | `e7c7decc-0ded-4351-ab14-b110b3c38ec9` | 1 |
|
||||
| **TI (Tecnologia da Informação)** | `7f63ec0c-6321-488c-b107-980140199850` | 1 |
|
||||
|
||||
---
|
||||
|
||||
**Versão**: 1.0.0 | **Autor**: Descomplicar®
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Quando NÃO Usar
|
||||
|
||||
- Para tarefas fora do domínio de especialização desta skill
|
||||
- Quando outra skill mais específica está disponível
|
||||
- Para operações que requerem confirmação manual do utilizador
|
||||
|
||||
|
||||
## Protocolo
|
||||
|
||||
1. Analisar requisitos da tarefa
|
||||
2. Verificar disponibilidade de ferramentas necessárias
|
||||
3. Executar operações de forma incremental
|
||||
4. Validar resultados antes de concluir
|
||||
5. Reportar status e próximos passos
|
||||
|
||||
|
||||
## Exemplos
|
||||
|
||||
### Exemplo 1: Uso Básico
|
||||
```
|
||||
Input: [descrição da tarefa]
|
||||
Output: [resultado esperado]
|
||||
```
|
||||
|
||||
### Exemplo 2: Uso Avançado
|
||||
```
|
||||
Input: [caso complexo]
|
||||
Output: [resultado detalhado]
|
||||
```
|
||||
Reference in New Issue
Block a user