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:
@@ -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 })
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user