feat: biblioteca inteligente libs/ + 5 novas skills (20 skills total)

NOVAS SKILLS:
- next-best-practices      v0.1.0  (CLEAN) — Next.js App Router, RSC, caching, data
- nextjs-patterns          v1.0.0  (CLEAN) — Next.js 15: Server Actions, route handlers
- vite                     v1.0.0  (CLEAN) — env vars, aliases, proxy, CJS compat
- uncle-bob                v1.0.0  (CLEAN) — Clean Code, SOLID, Clean Architecture
- clean-code-review        v1.0.0  (CLEAN) — naming, guard clauses, anti-patterns, refactoring
- vue                      v1.0.0  (CLEAN) — Vue framework
- vue-composition-api-best-practices v1.0.0 (CLEAN) — composables, Pinia, reactivity

BIBLIOTECA INTELIGENTE libs/ (10 dominios, 11 arquivos):
- typescript/ — TS safe + generics gotchas
- react/ — Next.js App Router + Vite config
- vue/ — Composition API + Pinia
- linux/ — System diagnostic cheatsheet
- database/ — PostgreSQL + MySQL patterns
- browser/ — Chromium CLI + E2E testing
- security/ — SAST audit (OWASP Top 10)
- best-practices/ — Clean Code + SOLID + Clean Architecture
- deploy/ — Docker multi-stack + OpenClaw ops
- + INDEX.md como guia de navegacao

.learnings/ — LRN-20260519-003 criado (biblioteca compartilhada)
This commit is contained in:
Pulse
2026-05-19 21:03:25 -03:00
parent 22d9f5b21d
commit ae39e45460
83 changed files with 13349 additions and 1 deletions
@@ -0,0 +1,81 @@
# Next.js 15 Caching Deep Dive
## The Four Caching Layers
### 1. Request Memoization (in-memory, per request)
Automatically deduplicates identical `fetch()` calls within a single render tree.
```tsx
// Both components call fetchUser(id) — only ONE network request is made
async function Avatar({ id }) { const u = await fetchUser(id); return <img src={u.avatar} /> }
async function Name({ id }) { const u = await fetchUser(id); return <span>{u.name}</span> }
```
### 2. Data Cache (persistent, cross-request)
`fetch()` responses are stored on the server and reused across requests and deployments.
```tsx
// Static — cached indefinitely
fetch(url)
fetch(url, { cache: "force-cache" })
// Time-based revalidation (ISR)
fetch(url, { next: { revalidate: 3600 } }) // revalidate every hour
// Always fresh — no caching
fetch(url, { cache: "no-store" })
fetch(url, { next: { revalidate: 0 } })
```
### 3. Full Route Cache (build-time static rendering)
Pages rendered at build time are stored as static HTML+RSC payload.
```tsx
// Force dynamic rendering for this route
export const dynamic = "force-dynamic"
// Custom revalidation period for the whole route
export const revalidate = 60
```
### 4. Router Cache (client-side, per session)
Browser caches RSC payloads for instant back/forward navigation.
- Static routes: cached for 5 minutes
- Dynamic routes: cached for 30 seconds
## On-Demand Revalidation
```ts
// Revalidate by path
import { revalidatePath } from "next/cache"
revalidatePath("/blog")
revalidatePath("/blog/[slug]", "page")
// Revalidate by cache tag
import { revalidateTag } from "next/cache"
revalidateTag("posts")
// Tagging fetches
fetch(url, { next: { tags: ["posts"] } })
```
## unstable_cache for Non-Fetch Data
```ts
import { unstable_cache } from "next/cache"
const getCachedUser = unstable_cache(
async (id: string) => db.user.findUnique({ where: { id } }),
["user"],
{ revalidate: 300, tags: ["users"] }
)
```
## Common Pitfalls
| Mistake | Fix |
|---------|-----|
| Using `fetch` inside `useEffect` | Move to Server Component or use React Query |
| Forgetting `revalidatePath` after mutations | Call in Server Action after every write |
| Over-caching user-specific data | Add `cache: "no-store"` or check `cookies()`/`headers()` |
| Sequential awaits | Use `Promise.all()` for parallel fetching |
@@ -0,0 +1,104 @@
# Next.js 15 Migration & Configuration Guide
## Upgrading to Next.js 15
```bash
npx @next/codemod@canary upgrade latest
# or manual:
npm install next@latest react@latest react-dom@latest
```
## Key Breaking Changes (14 → 15)
### 1. Async Request APIs (Breaking)
`cookies()`, `headers()`, `params`, `searchParams` are now async:
```tsx
// Before (Next.js 14)
export default function Page({ params }) {
const { id } = params
}
// After (Next.js 15)
export default async function Page({ params }) {
const { id } = await params
}
// cookies and headers
import { cookies, headers } from "next/headers"
const cookieStore = await cookies()
const headersList = await headers()
```
### 2. Caching Defaults Changed
`fetch()` no longer caches by default (was `force-cache`, now `no-store`).
Add `{ cache: "force-cache" }` or set route-level `export const fetchCache = "default-cache"` to restore.
### 3. React 19 Compatibility
Next.js 15 supports React 19. New hooks available:
- `useActionState` (replaces `useFormState`)
- `useFormStatus`
- `use()` for reading promises/context
## next.config.ts (TypeScript config)
```ts
import type { NextConfig } from "next"
const config: NextConfig = {
experimental: {
ppr: "incremental", // Partial Prerendering
reactCompiler: true, // React Compiler (auto-memoization)
},
images: {
remotePatterns: [
{ protocol: "https", hostname: "images.example.com" },
],
},
logging: {
fetches: { fullUrl: true }, // Log all fetch calls in dev
},
}
export default config
```
## Environment Variables
```bash
# .env.local
DATABASE_URL="postgresql://..."
NEXT_PUBLIC_API_URL="https://api.example.com" # exposed to browser
```
```ts
// Access server-side
process.env.DATABASE_URL
// Access client-side (only NEXT_PUBLIC_ prefix)
process.env.NEXT_PUBLIC_API_URL
```
## Turbopack (Default in Dev)
```bash
next dev # uses Turbopack by default in Next.js 15
next dev --turbopack # explicit flag (same behavior)
next build # Webpack still default for production builds
```
## TypeScript Path Aliases
```json
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"],
"@/components/*": ["./components/*"],
"@/lib/*": ["./lib/*"]
}
}
}
```
@@ -0,0 +1,122 @@
# Next.js 15 Routing Patterns
## App Router Fundamentals
| File | Purpose |
|---------------|----------------------------------------------|
| `page.tsx` | Unique UI for a route, makes it publicly accessible |
| `layout.tsx` | Shared UI; does NOT re-render on navigation |
| `template.tsx`| Like layout but re-renders on navigation |
| `loading.tsx` | Instant loading state (React Suspense) |
| `error.tsx` | Error UI boundary (must be Client Component) |
| `not-found.tsx`| 404 UI |
| `route.ts` | API endpoint (GET, POST, etc.) |
## Route Groups
```
app/
(auth)/
login/page.tsx → /login
register/page.tsx → /register
(app)/
layout.tsx ← shared auth-required layout
dashboard/page.tsx → /dashboard
```
Route groups `(name)` organize routes without affecting the URL.
## Dynamic Routes
```tsx
// app/blog/[slug]/page.tsx
export default function Post({ params }: { params: { slug: string } }) {
return <h1>{params.slug}</h1>
}
// Generate static routes at build time
export async function generateStaticParams() {
const posts = await fetchAllPosts()
return posts.map(p => ({ slug: p.slug }))
}
```
## Catch-All & Optional Catch-All
```
app/shop/[...categories]/page.tsx → /shop/a/b/c
app/shop/[[...categories]]/page.tsx → /shop AND /shop/a/b/c
```
## Parallel Routes (Advanced)
```
app/
@team/page.tsx
@analytics/page.tsx
layout.tsx ← receives { team, analytics } props
```
```tsx
// layout.tsx
export default function Layout({ children, team, analytics }) {
return (
<div>
{children}
<aside>{team}</aside>
<aside>{analytics}</aside>
</div>
)
}
```
## Intercepting Routes
```
app/
feed/page.tsx
(..)photo/[id]/page.tsx ← intercepts /photo/[id] when navigated from /feed
photo/[id]/page.tsx ← full page on direct URL visit
```
Useful for modals that maintain background context.
## Middleware
```ts
// middleware.ts (project root)
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*", "/api/protected/:path*"],
}
```
## API Routes (Route Handlers)
```ts
// app/api/posts/route.ts
import { NextRequest, NextResponse } from "next/server"
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const page = searchParams.get("page") ?? "1"
const posts = await fetchPosts(parseInt(page))
return NextResponse.json({ posts })
}
export async function POST(request: NextRequest) {
const body = await request.json()
const post = await createPost(body)
return NextResponse.json(post, { status: 201 })
}
```