claudient 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/.claude-plugin/plugin.json +42 -0
  2. package/CONTEXT.md +58 -0
  3. package/README.md +165 -0
  4. package/agents/build-resolvers/de/python-resolver.md +64 -0
  5. package/agents/build-resolvers/de/typescript-resolver.md +65 -0
  6. package/agents/build-resolvers/es/python-resolver.md +64 -0
  7. package/agents/build-resolvers/es/typescript-resolver.md +65 -0
  8. package/agents/build-resolvers/fr/python-resolver.md +64 -0
  9. package/agents/build-resolvers/fr/typescript-resolver.md +65 -0
  10. package/agents/build-resolvers/nl/python-resolver.md +64 -0
  11. package/agents/build-resolvers/nl/typescript-resolver.md +65 -0
  12. package/agents/build-resolvers/python-resolver.md +62 -0
  13. package/agents/build-resolvers/typescript-resolver.md +63 -0
  14. package/agents/core/architect.md +64 -0
  15. package/agents/core/code-reviewer.md +78 -0
  16. package/agents/core/de/architect.md +66 -0
  17. package/agents/core/de/code-reviewer.md +80 -0
  18. package/agents/core/de/planner.md +63 -0
  19. package/agents/core/de/security-reviewer.md +93 -0
  20. package/agents/core/es/architect.md +66 -0
  21. package/agents/core/es/code-reviewer.md +80 -0
  22. package/agents/core/es/planner.md +63 -0
  23. package/agents/core/es/security-reviewer.md +93 -0
  24. package/agents/core/fr/architect.md +66 -0
  25. package/agents/core/fr/code-reviewer.md +80 -0
  26. package/agents/core/fr/planner.md +63 -0
  27. package/agents/core/fr/security-reviewer.md +93 -0
  28. package/agents/core/nl/architect.md +66 -0
  29. package/agents/core/nl/code-reviewer.md +80 -0
  30. package/agents/core/nl/planner.md +63 -0
  31. package/agents/core/nl/security-reviewer.md +93 -0
  32. package/agents/core/planner.md +61 -0
  33. package/agents/core/security-reviewer.md +91 -0
  34. package/guides/agent-orchestration.md +231 -0
  35. package/guides/de/agent-orchestration.md +174 -0
  36. package/guides/de/getting-started.md +164 -0
  37. package/guides/de/hooks-cookbook.md +160 -0
  38. package/guides/de/memory-management.md +153 -0
  39. package/guides/de/security.md +180 -0
  40. package/guides/de/skill-authoring.md +214 -0
  41. package/guides/de/token-optimization.md +156 -0
  42. package/guides/es/agent-orchestration.md +174 -0
  43. package/guides/es/getting-started.md +164 -0
  44. package/guides/es/hooks-cookbook.md +160 -0
  45. package/guides/es/memory-management.md +153 -0
  46. package/guides/es/security.md +180 -0
  47. package/guides/es/skill-authoring.md +214 -0
  48. package/guides/es/token-optimization.md +156 -0
  49. package/guides/fr/agent-orchestration.md +174 -0
  50. package/guides/fr/getting-started.md +164 -0
  51. package/guides/fr/hooks-cookbook.md +227 -0
  52. package/guides/fr/memory-management.md +169 -0
  53. package/guides/fr/security.md +180 -0
  54. package/guides/fr/skill-authoring.md +214 -0
  55. package/guides/fr/token-optimization.md +158 -0
  56. package/guides/getting-started.md +164 -0
  57. package/guides/hooks-cookbook.md +423 -0
  58. package/guides/memory-management.md +192 -0
  59. package/guides/nl/agent-orchestration.md +174 -0
  60. package/guides/nl/getting-started.md +164 -0
  61. package/guides/nl/hooks-cookbook.md +160 -0
  62. package/guides/nl/memory-management.md +153 -0
  63. package/guides/nl/security.md +180 -0
  64. package/guides/nl/skill-authoring.md +214 -0
  65. package/guides/nl/token-optimization.md +156 -0
  66. package/guides/security.md +229 -0
  67. package/guides/skill-authoring.md +226 -0
  68. package/guides/token-optimization.md +169 -0
  69. package/hooks/lifecycle/cost-tracker.md +49 -0
  70. package/hooks/lifecycle/cost-tracker.sh +59 -0
  71. package/hooks/lifecycle/pre-compact-save.md +56 -0
  72. package/hooks/lifecycle/pre-compact-save.sh +37 -0
  73. package/hooks/lifecycle/session-start.md +50 -0
  74. package/hooks/lifecycle/session-start.sh +47 -0
  75. package/hooks/post-tool-use/audit-log.md +53 -0
  76. package/hooks/post-tool-use/audit-log.sh +53 -0
  77. package/hooks/post-tool-use/prettier.md +53 -0
  78. package/hooks/post-tool-use/prettier.sh +49 -0
  79. package/hooks/pre-tool-use/block-dangerous.md +48 -0
  80. package/hooks/pre-tool-use/block-dangerous.sh +76 -0
  81. package/hooks/pre-tool-use/git-push-confirm.md +46 -0
  82. package/hooks/pre-tool-use/git-push-confirm.sh +36 -0
  83. package/mcp/configs/github.json +11 -0
  84. package/mcp/configs/postgres.json +11 -0
  85. package/mcp/de/recommended-servers.md +170 -0
  86. package/mcp/es/recommended-servers.md +170 -0
  87. package/mcp/fr/recommended-servers.md +170 -0
  88. package/mcp/nl/recommended-servers.md +170 -0
  89. package/mcp/recommended-servers.md +168 -0
  90. package/package.json +45 -0
  91. package/prompts/project-starters/de/fastapi-project.md +62 -0
  92. package/prompts/project-starters/de/nextjs-project.md +82 -0
  93. package/prompts/project-starters/es/fastapi-project.md +62 -0
  94. package/prompts/project-starters/es/nextjs-project.md +82 -0
  95. package/prompts/project-starters/fastapi-project.md +60 -0
  96. package/prompts/project-starters/fr/fastapi-project.md +62 -0
  97. package/prompts/project-starters/fr/nextjs-project.md +82 -0
  98. package/prompts/project-starters/nextjs-project.md +80 -0
  99. package/prompts/project-starters/nl/fastapi-project.md +62 -0
  100. package/prompts/project-starters/nl/nextjs-project.md +82 -0
  101. package/prompts/system-prompts/ai-product.md +80 -0
  102. package/prompts/system-prompts/data-pipeline.md +76 -0
  103. package/prompts/system-prompts/de/ai-product.md +82 -0
  104. package/prompts/system-prompts/de/data-pipeline.md +78 -0
  105. package/prompts/system-prompts/de/saas-backend.md +71 -0
  106. package/prompts/system-prompts/es/ai-product.md +82 -0
  107. package/prompts/system-prompts/es/data-pipeline.md +78 -0
  108. package/prompts/system-prompts/es/saas-backend.md +71 -0
  109. package/prompts/system-prompts/fr/ai-product.md +82 -0
  110. package/prompts/system-prompts/fr/data-pipeline.md +78 -0
  111. package/prompts/system-prompts/fr/saas-backend.md +71 -0
  112. package/prompts/system-prompts/nl/ai-product.md +82 -0
  113. package/prompts/system-prompts/nl/data-pipeline.md +78 -0
  114. package/prompts/system-prompts/nl/saas-backend.md +71 -0
  115. package/prompts/system-prompts/saas-backend.md +69 -0
  116. package/prompts/task-specific/changelog.md +81 -0
  117. package/prompts/task-specific/de/changelog.md +83 -0
  118. package/prompts/task-specific/de/debugging.md +78 -0
  119. package/prompts/task-specific/de/pr-description.md +69 -0
  120. package/prompts/task-specific/debugging.md +76 -0
  121. package/prompts/task-specific/es/changelog.md +83 -0
  122. package/prompts/task-specific/es/debugging.md +78 -0
  123. package/prompts/task-specific/es/pr-description.md +69 -0
  124. package/prompts/task-specific/fr/changelog.md +83 -0
  125. package/prompts/task-specific/fr/debugging.md +78 -0
  126. package/prompts/task-specific/fr/pr-description.md +69 -0
  127. package/prompts/task-specific/nl/changelog.md +83 -0
  128. package/prompts/task-specific/nl/debugging.md +78 -0
  129. package/prompts/task-specific/nl/pr-description.md +69 -0
  130. package/prompts/task-specific/pr-description.md +67 -0
  131. package/rules/common/coding-style.md +45 -0
  132. package/rules/common/de/coding-style.md +47 -0
  133. package/rules/common/de/git.md +48 -0
  134. package/rules/common/de/performance.md +40 -0
  135. package/rules/common/de/security.md +45 -0
  136. package/rules/common/de/testing.md +45 -0
  137. package/rules/common/es/coding-style.md +47 -0
  138. package/rules/common/es/git.md +48 -0
  139. package/rules/common/es/performance.md +40 -0
  140. package/rules/common/es/security.md +45 -0
  141. package/rules/common/es/testing.md +45 -0
  142. package/rules/common/fr/coding-style.md +47 -0
  143. package/rules/common/fr/git.md +48 -0
  144. package/rules/common/fr/performance.md +40 -0
  145. package/rules/common/fr/security.md +45 -0
  146. package/rules/common/fr/testing.md +45 -0
  147. package/rules/common/git.md +46 -0
  148. package/rules/common/nl/coding-style.md +47 -0
  149. package/rules/common/nl/git.md +48 -0
  150. package/rules/common/nl/performance.md +40 -0
  151. package/rules/common/nl/security.md +45 -0
  152. package/rules/common/nl/testing.md +45 -0
  153. package/rules/common/performance.md +38 -0
  154. package/rules/common/security.md +43 -0
  155. package/rules/common/testing.md +43 -0
  156. package/rules/language-specific/de/go.md +48 -0
  157. package/rules/language-specific/de/python.md +38 -0
  158. package/rules/language-specific/de/typescript.md +51 -0
  159. package/rules/language-specific/es/go.md +48 -0
  160. package/rules/language-specific/es/python.md +38 -0
  161. package/rules/language-specific/es/typescript.md +51 -0
  162. package/rules/language-specific/fr/go.md +48 -0
  163. package/rules/language-specific/fr/python.md +38 -0
  164. package/rules/language-specific/fr/typescript.md +51 -0
  165. package/rules/language-specific/go.md +46 -0
  166. package/rules/language-specific/nl/go.md +48 -0
  167. package/rules/language-specific/nl/python.md +38 -0
  168. package/rules/language-specific/nl/typescript.md +51 -0
  169. package/rules/language-specific/python.md +36 -0
  170. package/rules/language-specific/typescript.md +49 -0
  171. package/scripts/cli.js +161 -0
  172. package/scripts/link-skills.sh +35 -0
  173. package/scripts/list-skills.sh +34 -0
  174. package/skills/ai-engineering/agent-construction.md +285 -0
  175. package/skills/ai-engineering/claude-api.md +248 -0
  176. package/skills/ai-engineering/de/agent-construction.md +287 -0
  177. package/skills/ai-engineering/de/claude-api.md +250 -0
  178. package/skills/ai-engineering/es/agent-construction.md +287 -0
  179. package/skills/ai-engineering/es/claude-api.md +250 -0
  180. package/skills/ai-engineering/fr/agent-construction.md +287 -0
  181. package/skills/ai-engineering/fr/claude-api.md +250 -0
  182. package/skills/ai-engineering/nl/agent-construction.md +287 -0
  183. package/skills/ai-engineering/nl/claude-api.md +250 -0
  184. package/skills/backend/dotnet/csharp.md +304 -0
  185. package/skills/backend/dotnet/de/csharp.md +306 -0
  186. package/skills/backend/dotnet/es/csharp.md +306 -0
  187. package/skills/backend/dotnet/fr/csharp.md +306 -0
  188. package/skills/backend/dotnet/nl/csharp.md +306 -0
  189. package/skills/backend/go/de/go.md +307 -0
  190. package/skills/backend/go/es/go.md +307 -0
  191. package/skills/backend/go/fr/go.md +307 -0
  192. package/skills/backend/go/go.md +305 -0
  193. package/skills/backend/go/nl/go.md +307 -0
  194. package/skills/backend/nodejs/de/nestjs.md +274 -0
  195. package/skills/backend/nodejs/de/nextjs.md +222 -0
  196. package/skills/backend/nodejs/es/nestjs.md +274 -0
  197. package/skills/backend/nodejs/es/nextjs.md +222 -0
  198. package/skills/backend/nodejs/fr/nestjs.md +274 -0
  199. package/skills/backend/nodejs/fr/nextjs.md +222 -0
  200. package/skills/backend/nodejs/nestjs.md +272 -0
  201. package/skills/backend/nodejs/nextjs.md +220 -0
  202. package/skills/backend/nodejs/nl/nestjs.md +274 -0
  203. package/skills/backend/nodejs/nl/nextjs.md +222 -0
  204. package/skills/backend/python/de/django.md +285 -0
  205. package/skills/backend/python/de/fastapi.md +244 -0
  206. package/skills/backend/python/django.md +283 -0
  207. package/skills/backend/python/es/django.md +285 -0
  208. package/skills/backend/python/es/fastapi.md +244 -0
  209. package/skills/backend/python/fastapi.md +242 -0
  210. package/skills/backend/python/fr/django.md +285 -0
  211. package/skills/backend/python/fr/fastapi.md +244 -0
  212. package/skills/backend/python/nl/django.md +285 -0
  213. package/skills/backend/python/nl/fastapi.md +244 -0
  214. package/skills/data-ml/dbt-data-pipelines.md +155 -0
  215. package/skills/data-ml/de/dbt-data-pipelines.md +157 -0
  216. package/skills/data-ml/de/pandas-polars.md +147 -0
  217. package/skills/data-ml/de/pytorch-tensorflow.md +171 -0
  218. package/skills/data-ml/es/dbt-data-pipelines.md +157 -0
  219. package/skills/data-ml/es/pandas-polars.md +147 -0
  220. package/skills/data-ml/es/pytorch-tensorflow.md +171 -0
  221. package/skills/data-ml/fr/dbt-data-pipelines.md +157 -0
  222. package/skills/data-ml/fr/pandas-polars.md +147 -0
  223. package/skills/data-ml/fr/pytorch-tensorflow.md +171 -0
  224. package/skills/data-ml/nl/dbt-data-pipelines.md +157 -0
  225. package/skills/data-ml/nl/pandas-polars.md +147 -0
  226. package/skills/data-ml/nl/pytorch-tensorflow.md +171 -0
  227. package/skills/data-ml/pandas-polars.md +145 -0
  228. package/skills/data-ml/pytorch-tensorflow.md +169 -0
  229. package/skills/database/de/graphql.md +181 -0
  230. package/skills/database/es/graphql.md +181 -0
  231. package/skills/database/fr/graphql.md +181 -0
  232. package/skills/database/graphql.md +179 -0
  233. package/skills/database/nl/graphql.md +181 -0
  234. package/skills/devops-infra/de/docker.md +133 -0
  235. package/skills/devops-infra/de/github-actions.md +179 -0
  236. package/skills/devops-infra/de/kubernetes.md +129 -0
  237. package/skills/devops-infra/de/terraform.md +130 -0
  238. package/skills/devops-infra/docker.md +131 -0
  239. package/skills/devops-infra/es/docker.md +133 -0
  240. package/skills/devops-infra/es/github-actions.md +179 -0
  241. package/skills/devops-infra/es/kubernetes.md +129 -0
  242. package/skills/devops-infra/es/terraform.md +130 -0
  243. package/skills/devops-infra/fr/docker.md +133 -0
  244. package/skills/devops-infra/fr/github-actions.md +179 -0
  245. package/skills/devops-infra/fr/kubernetes.md +129 -0
  246. package/skills/devops-infra/fr/terraform.md +130 -0
  247. package/skills/devops-infra/github-actions.md +177 -0
  248. package/skills/devops-infra/kubernetes.md +127 -0
  249. package/skills/devops-infra/nl/docker.md +133 -0
  250. package/skills/devops-infra/nl/github-actions.md +179 -0
  251. package/skills/devops-infra/nl/kubernetes.md +129 -0
  252. package/skills/devops-infra/nl/terraform.md +130 -0
  253. package/skills/devops-infra/terraform.md +128 -0
  254. package/skills/finance-payments/de/stripe.md +187 -0
  255. package/skills/finance-payments/es/stripe.md +187 -0
  256. package/skills/finance-payments/fr/stripe.md +187 -0
  257. package/skills/finance-payments/nl/stripe.md +187 -0
  258. package/skills/finance-payments/stripe.md +185 -0
  259. package/workflows/code-review.md +151 -0
  260. package/workflows/de/code-review.md +153 -0
  261. package/workflows/de/debugging-session.md +146 -0
  262. package/workflows/de/feature-development.md +155 -0
  263. package/workflows/de/new-project-bootstrap.md +175 -0
  264. package/workflows/de/refactor-safely.md +150 -0
  265. package/workflows/debugging-session.md +144 -0
  266. package/workflows/es/code-review.md +153 -0
  267. package/workflows/es/debugging-session.md +146 -0
  268. package/workflows/es/feature-development.md +155 -0
  269. package/workflows/es/new-project-bootstrap.md +175 -0
  270. package/workflows/es/refactor-safely.md +150 -0
  271. package/workflows/feature-development.md +153 -0
  272. package/workflows/fr/code-review.md +153 -0
  273. package/workflows/fr/debugging-session.md +146 -0
  274. package/workflows/fr/feature-development.md +155 -0
  275. package/workflows/fr/new-project-bootstrap.md +175 -0
  276. package/workflows/fr/refactor-safely.md +150 -0
  277. package/workflows/new-project-bootstrap.md +173 -0
  278. package/workflows/nl/code-review.md +153 -0
  279. package/workflows/nl/debugging-session.md +146 -0
  280. package/workflows/nl/feature-development.md +155 -0
  281. package/workflows/nl/new-project-bootstrap.md +175 -0
  282. package/workflows/nl/refactor-safely.md +150 -0
  283. package/workflows/refactor-safely.md +148 -0
@@ -0,0 +1,222 @@
1
+ > 🇩🇪 Dies ist die deutsche Übersetzung. [Englische Version](../nextjs.md).
2
+
3
+ # Next.js Skill
4
+
5
+ ## Wann aktivieren
6
+ - Eine Next.js-Anwendung mit dem App Router bauen
7
+ - Zwischen Server Components und Client Components entscheiden
8
+ - Server Actions für Formularübermittlungen und Mutationen schreiben
9
+ - Route Handler einrichten (API-Endpunkte im App Router)
10
+ - Authentifizierung mit NextAuth oder einem JWT-Muster implementieren
11
+ - Middleware für Weiterleitungen und Auth Guards konfigurieren
12
+ - Datenabruf mit React `cache()` und `unstable_cache` optimieren
13
+ - Parallele Routes, abfangende Routes oder Route Groups verwenden
14
+
15
+ ## Wann NICHT verwenden
16
+ - Pages Router-Projekte — die Muster unterscheiden sich erheblich
17
+ - Reine SPAs ohne Server-Rendering (Vite + React verwenden)
18
+ - NestJS oder Express-Backends — NestJS Skill verwenden
19
+ - Statische Seiten ohne dynamische Daten (Astro verwenden)
20
+
21
+ ## Anweisungen
22
+
23
+ ### App Router Verzeichnisstruktur
24
+ ```
25
+ app/
26
+ ├── (auth)/ # Route-Gruppe — kein URL-Segment
27
+ │ ├── login/
28
+ │ │ └── page.tsx
29
+ │ └── layout.tsx # Auth-spezifisches Layout
30
+ ├── (dashboard)/
31
+ │ ├── dashboard/
32
+ │ │ ├── page.tsx # Server Component standardmäßig
33
+ │ │ └── loading.tsx # Suspense-Grenze UI
34
+ │ └── layout.tsx
35
+ ├── api/
36
+ │ └── webhooks/
37
+ │ └── stripe/
38
+ │ └── route.ts # Route Handler
39
+ ├── layout.tsx # Root-Layout (erforderlich)
40
+ └── page.tsx # Startseite
41
+ components/
42
+ ├── ui/ # Präsentational (kann Server oder Client sein)
43
+ └── forms/ # Immer Client Components (useState/Events)
44
+ lib/
45
+ ├── auth.ts
46
+ ├── db.ts
47
+ └── actions/ # Server Actions
48
+ └── user.ts
49
+ ```
50
+
51
+ ### Server vs. Client Components
52
+ ```tsx
53
+ // Server Component (Standard) — läuft auf dem Server, wird nie an den Client gesendet
54
+ // Kann: await fetch, DB lesen, Umgebungsvariablen abrufen
55
+ // Kann nicht: useState, useEffect, Browser-APIs, Event-Handler
56
+ export default async function UserProfile({ id }: { id: string }) {
57
+ const user = await db.user.findUnique({ where: { id } })
58
+ return <div>{user.name}</div>
59
+ }
60
+
61
+ // Client Component — 'use client'-Direktive hinzufügen
62
+ 'use client'
63
+ import { useState } from 'react'
64
+
65
+ export function LikeButton({ initialCount }: { initialCount: number }) {
66
+ const [count, setCount] = useState(initialCount)
67
+ return <button onClick={() => setCount(c => c + 1)}>{count} likes</button>
68
+ }
69
+ ```
70
+
71
+ Regel: standardmäßig Server Components verwenden. `'use client'` nur hinzufügen, wenn Interaktivität, Browser-APIs oder React-Hooks benötigt werden.
72
+
73
+ ### Datenabruf-Muster
74
+ ```tsx
75
+ // Server Component — direktes async/await, kein useEffect, kein useState
76
+ export default async function PostList() {
77
+ const posts = await db.post.findMany({ where: { published: true } })
78
+ return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>
79
+ }
80
+
81
+ // Deduplizierung — React cache() umschließt eine Funktion, sodass mehrere Komponenten
82
+ // bei einem Render einen gemeinsamen Fetch teilen
83
+ import { cache } from 'react'
84
+ export const getUser = cache(async (id: string) => {
85
+ return db.user.findUnique({ where: { id } })
86
+ })
87
+
88
+ // Statische Generierung mit Revalidierung
89
+ async function getProducts() {
90
+ const res = await fetch('https://api.example.com/products', {
91
+ next: { revalidate: 3600 }, // ISR — stündlich revalidieren
92
+ })
93
+ return res.json()
94
+ }
95
+ ```
96
+
97
+ ### Server Actions
98
+ ```tsx
99
+ // lib/actions/user.ts
100
+ 'use server'
101
+ import { revalidatePath } from 'next/cache'
102
+ import { z } from 'zod'
103
+
104
+ const UpdateSchema = z.object({
105
+ name: z.string().min(1),
106
+ })
107
+
108
+ export async function updateUser(formData: FormData) {
109
+ const parsed = UpdateSchema.safeParse({ name: formData.get('name') })
110
+ if (!parsed.success) return { error: parsed.error.flatten() }
111
+
112
+ await db.user.update({ where: { id: getCurrentUserId() }, data: parsed.data })
113
+ revalidatePath('/dashboard/profile')
114
+ return { success: true }
115
+ }
116
+
117
+ // In einer Server Component:
118
+ export default function ProfileForm({ user }: { user: User }) {
119
+ return (
120
+ <form action={updateUser}>
121
+ <input name="name" defaultValue={user.name} />
122
+ <button type="submit">Save</button>
123
+ </form>
124
+ )
125
+ }
126
+ ```
127
+
128
+ ### Route Handler
129
+ ```ts
130
+ // app/api/webhooks/stripe/route.ts
131
+ import { NextRequest, NextResponse } from 'next/server'
132
+ import Stripe from 'stripe'
133
+
134
+ export async function POST(req: NextRequest) {
135
+ const body = await req.text()
136
+ const sig = req.headers.get('stripe-signature')!
137
+
138
+ let event: Stripe.Event
139
+ try {
140
+ event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!)
141
+ } catch {
142
+ return NextResponse.json({ error: 'Invalid signature' }, { status: 400 })
143
+ }
144
+
145
+ if (event.type === 'checkout.session.completed') {
146
+ await handleCheckoutCompleted(event.data.object)
147
+ }
148
+
149
+ return NextResponse.json({ received: true })
150
+ }
151
+ ```
152
+
153
+ ### Middleware
154
+ ```ts
155
+ // middleware.ts (Root-Ebene)
156
+ import { NextResponse } from 'next/server'
157
+ import type { NextRequest } from 'next/server'
158
+
159
+ export function middleware(request: NextRequest) {
160
+ const token = request.cookies.get('auth-token')
161
+ if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
162
+ return NextResponse.redirect(new URL('/login', request.url))
163
+ }
164
+ return NextResponse.next()
165
+ }
166
+
167
+ export const config = {
168
+ matcher: ['/dashboard/:path*', '/api/protected/:path*'],
169
+ }
170
+ ```
171
+
172
+ ### Parallele und abfangende Routes
173
+ ```
174
+ app/
175
+ ├── @modal/ # Parallele Route — wird neben dem Hauptinhalt gerendert
176
+ │ └── (.)photo/ # Abfangende Route — fängt /photo/[id] ab
177
+ │ └── [id]/
178
+ │ └── page.tsx
179
+ ├── photo/
180
+ │ └── [id]/
181
+ │ └── page.tsx
182
+ └── layout.tsx # Akzeptiert { children, modal } als Props
183
+ ```
184
+
185
+ ### Fehler- und Lade-Grenzen
186
+ ```tsx
187
+ // app/dashboard/loading.tsx — während Suspense angezeigt
188
+ export default function Loading() {
189
+ return <DashboardSkeleton />
190
+ }
191
+
192
+ // app/dashboard/error.tsx — Fehlergrenze für dieses Segment
193
+ 'use client'
194
+ export default function Error({ error, reset }: { error: Error; reset: () => void }) {
195
+ return (
196
+ <div>
197
+ <p>{error.message}</p>
198
+ <button onClick={reset}>Retry</button>
199
+ </div>
200
+ )
201
+ }
202
+ ```
203
+
204
+ ### Umgebungsvariablen
205
+ - `NEXT_PUBLIC_*` — dem Browser ausgesetzt
206
+ - Alle anderen — nur serverseitig (in Client Components nie zugänglich)
207
+ - Niemals eine server-only Umgebungsvariable in einer Client Component importieren — sie gibt `undefined` zurück
208
+
209
+ ## Beispiel
210
+
211
+ **Benutzer:** Eine paginierte Blog-Posts-Seite bei `/blog` hinzufügen, die aus PostgreSQL abruft, mit einem "Neuer Post"-Modal, das bei `/blog/new` öffnet, aber nicht von der Posts-Liste wegnavigiert.
212
+
213
+ **Erwartete Ausgabe:**
214
+ - `app/blog/page.tsx` — Server Component, ruft Posts mit `db.post.findMany` ab, rendert `<PostList>` + `<Link href="/blog/new">`
215
+ - `app/@modal/(.)blog/new/page.tsx` — Abfangende Route zeigt eine `<NewPostModal>` Client Component
216
+ - `app/blog/new/page.tsx` — Vollseiten-Fallback für direkte Navigation
217
+ - `app/layout.tsx` — Aktualisiert, um `modal`-Parallele-Route-Slot zu akzeptieren und neben `children` zu rendern
218
+ - `lib/actions/post.ts` — `createPost` Server Action mit Zod-Validierung + `revalidatePath('/blog')`
219
+
220
+ ---
221
+
222
+ > **Mit uns arbeiten:** Claudient wird von [Uitbreiden](https://uitbreiden.com/) unterstützt — wir bauen KI-Produkte und B2B-Lösungen mit Entwickler-Communities. [uitbreiden.com](https://uitbreiden.com/)
@@ -0,0 +1,274 @@
1
+ > 🇪🇸 Esta es la traducción en español. [Versión en inglés](../nestjs.md).
2
+
3
+ # Skill de NestJS
4
+
5
+ ## Cuándo activar
6
+ - Construir una aplicación NestJS (módulos, controladores, servicios)
7
+ - Configurar guards, interceptores, pipes y filtros de excepciones
8
+ - Integrar TypeORM o Prisma con NestJS
9
+ - Implementar CQRS con comandos, queries y eventos
10
+ - Configurar microservicios (transporte TCP, Redis, RabbitMQ)
11
+ - Escribir pruebas unitarias y e2e con Jest y Supertest
12
+ - Generar documentación OpenAPI con `@nestjs/swagger`
13
+
14
+ ## Cuándo NO usar
15
+ - Rutas de API de Next.js o Fastify standalone — framework diferente
16
+ - Scripts simples de Express — la sobrecarga de NestJS no está justificada
17
+ - Funciones Lambda donde el tiempo de arranque en frío es crítico
18
+
19
+ ## Instrucciones
20
+
21
+ ### Estructura del módulo
22
+ ```
23
+ src/
24
+ ├── app.module.ts # Módulo raíz
25
+ ├── main.ts # Bootstrap
26
+ ├── common/
27
+ │ ├── decorators/
28
+ │ ├── filters/
29
+ │ ├── guards/
30
+ │ ├── interceptors/
31
+ │ └── pipes/
32
+ ├── config/
33
+ │ └── configuration.ts # Configuración de ConfigService
34
+ └── modules/
35
+ └── users/
36
+ ├── users.module.ts
37
+ ├── users.controller.ts
38
+ ├── users.service.ts
39
+ ├── dto/
40
+ │ ├── create-user.dto.ts
41
+ │ └── update-user.dto.ts
42
+ ├── entities/
43
+ │ └── user.entity.ts
44
+ └── users.service.spec.ts
45
+ ```
46
+
47
+ ### Bootstrap
48
+ ```ts
49
+ // main.ts
50
+ import { NestFactory } from '@nestjs/core'
51
+ import { AppModule } from './app.module'
52
+ import { ValidationPipe } from '@nestjs/common'
53
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'
54
+
55
+ async function bootstrap() {
56
+ const app = await NestFactory.create(AppModule)
57
+
58
+ app.useGlobalPipes(new ValidationPipe({
59
+ whitelist: true, // eliminar campos desconocidos
60
+ forbidNonWhitelisted: true,
61
+ transform: true, // auto-transformar payloads a clases DTO
62
+ }))
63
+
64
+ const config = new DocumentBuilder()
65
+ .setTitle('API')
66
+ .setVersion('1.0')
67
+ .addBearerAuth()
68
+ .build()
69
+ SwaggerModule.setup('docs', app, SwaggerModule.createDocument(app, config))
70
+
71
+ await app.listen(3000)
72
+ }
73
+ bootstrap()
74
+ ```
75
+
76
+ ### Módulo, Controlador, Servicio
77
+ ```ts
78
+ // users.module.ts
79
+ @Module({
80
+ imports: [TypeOrmModule.forFeature([User]), JwtModule.register({})],
81
+ controllers: [UsersController],
82
+ providers: [UsersService],
83
+ exports: [UsersService],
84
+ })
85
+ export class UsersModule {}
86
+
87
+ // users.controller.ts
88
+ @ApiTags('users')
89
+ @ApiBearerAuth()
90
+ @UseGuards(JwtAuthGuard)
91
+ @Controller('users')
92
+ export class UsersController {
93
+ constructor(private readonly usersService: UsersService) {}
94
+
95
+ @Post()
96
+ @HttpCode(HttpStatus.CREATED)
97
+ create(@Body() dto: CreateUserDto): Promise<UserResponseDto> {
98
+ return this.usersService.create(dto)
99
+ }
100
+
101
+ @Get(':id')
102
+ findOne(@Param('id', ParseUUIDPipe) id: string): Promise<UserResponseDto> {
103
+ return this.usersService.findOneOrFail(id)
104
+ }
105
+ }
106
+
107
+ // users.service.ts
108
+ @Injectable()
109
+ export class UsersService {
110
+ constructor(
111
+ @InjectRepository(User)
112
+ private readonly userRepo: Repository<User>,
113
+ ) {}
114
+
115
+ async create(dto: CreateUserDto): Promise<User> {
116
+ const exists = await this.userRepo.findOneBy({ email: dto.email })
117
+ if (exists) throw new ConflictException('Email already in use')
118
+ const user = this.userRepo.create({
119
+ ...dto,
120
+ password: await bcrypt.hash(dto.password, 10),
121
+ })
122
+ return this.userRepo.save(user)
123
+ }
124
+
125
+ async findOneOrFail(id: string): Promise<User> {
126
+ const user = await this.userRepo.findOneBy({ id })
127
+ if (!user) throw new NotFoundException(`User ${id} not found`)
128
+ return user
129
+ }
130
+ }
131
+ ```
132
+
133
+ ### DTOs con class-validator
134
+ ```ts
135
+ // dto/create-user.dto.ts
136
+ import { IsEmail, IsString, MinLength, IsOptional } from 'class-validator'
137
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
138
+
139
+ export class CreateUserDto {
140
+ @ApiProperty({ example: 'user@example.com' })
141
+ @IsEmail()
142
+ email: string
143
+
144
+ @ApiProperty({ minLength: 8 })
145
+ @IsString()
146
+ @MinLength(8)
147
+ password: string
148
+
149
+ @ApiPropertyOptional()
150
+ @IsOptional()
151
+ @IsString()
152
+ name?: string
153
+ }
154
+ ```
155
+
156
+ ### Guards
157
+ ```ts
158
+ // common/guards/jwt-auth.guard.ts
159
+ @Injectable()
160
+ export class JwtAuthGuard extends AuthGuard('jwt') {
161
+ handleRequest<T>(err: Error, user: T, info: Error): T {
162
+ if (err || !user) {
163
+ throw err || new UnauthorizedException(info?.message)
164
+ }
165
+ return user
166
+ }
167
+ }
168
+
169
+ // common/guards/roles.guard.ts
170
+ @Injectable()
171
+ export class RolesGuard implements CanActivate {
172
+ constructor(private reflector: Reflector) {}
173
+
174
+ canActivate(context: ExecutionContext): boolean {
175
+ const roles = this.reflector.getAllAndOverride<Role[]>('roles', [
176
+ context.getHandler(),
177
+ context.getClass(),
178
+ ])
179
+ if (!roles) return true
180
+ const { user } = context.switchToHttp().getRequest()
181
+ return roles.some(role => user.roles?.includes(role))
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### Interceptores
187
+ ```ts
188
+ // common/interceptors/transform.interceptor.ts
189
+ @Injectable()
190
+ export class TransformInterceptor<T>
191
+ implements NestInterceptor<T, { data: T; timestamp: string }>
192
+ {
193
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
194
+ return next.handle().pipe(
195
+ map(data => ({ data, timestamp: new Date().toISOString() }))
196
+ )
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### CQRS
202
+ ```ts
203
+ // Instalar: @nestjs/cqrs
204
+
205
+ // commands/create-user.command.ts
206
+ export class CreateUserCommand {
207
+ constructor(public readonly dto: CreateUserDto) {}
208
+ }
209
+
210
+ // commands/create-user.handler.ts
211
+ @CommandHandler(CreateUserCommand)
212
+ export class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
213
+ constructor(private readonly userRepo: UserRepository) {}
214
+
215
+ async execute(command: CreateUserCommand): Promise<User> {
216
+ const user = User.create(command.dto)
217
+ await this.userRepo.save(user)
218
+ return user
219
+ }
220
+ }
221
+
222
+ // En servicio/controlador:
223
+ const user = await this.commandBus.execute(new CreateUserCommand(dto))
224
+ ```
225
+
226
+ ### Testing
227
+ ```ts
228
+ // Prueba unitaria
229
+ describe('UsersService', () => {
230
+ let service: UsersService
231
+ let repo: jest.Mocked<Repository<User>>
232
+
233
+ beforeEach(async () => {
234
+ const module = await Test.createTestingModule({
235
+ providers: [
236
+ UsersService,
237
+ { provide: getRepositoryToken(User), useValue: createMockRepository() },
238
+ ],
239
+ }).compile()
240
+ service = module.get(UsersService)
241
+ repo = module.get(getRepositoryToken(User))
242
+ })
243
+
244
+ it('throws ConflictException for duplicate email', async () => {
245
+ repo.findOneBy.mockResolvedValue(existingUser)
246
+ await expect(service.create(dto)).rejects.toThrow(ConflictException)
247
+ })
248
+ })
249
+
250
+ // Prueba E2E
251
+ describe('POST /users', () => {
252
+ it('creates a user', () => {
253
+ return request(app.getHttpServer())
254
+ .post('/users')
255
+ .send({ email: 'a@b.com', password: 'password123' })
256
+ .expect(201)
257
+ })
258
+ })
259
+ ```
260
+
261
+ ## Ejemplo
262
+
263
+ **Usuario:** Agregar un módulo `Products` a una aplicación NestJS con TypeORM, incluyendo endpoints CRUD, eliminación solo para admin protegida por `RolesGuard` y documentación OpenAPI.
264
+
265
+ **Salida esperada:**
266
+ - `products.entity.ts` — entidad TypeORM con `id` (UUID), `name`, `price` (decimal), `stock`, `createdAt`
267
+ - `dto/create-product.dto.ts` — DTO class-validator con decoradores `@ApiProperty`
268
+ - `products.service.ts` — métodos CRUD usando `Repository<Product>`, lanzando `NotFoundException` en caso de ausencia
269
+ - `products.controller.ts` — todos los endpoints CRUD, `@UseGuards(JwtAuthGuard, RolesGuard)` + `@Roles(Role.Admin)` en `DELETE`
270
+ - `products.module.ts` — importa `TypeOrmModule.forFeature([Product])`
271
+
272
+ ---
273
+
274
+ > **Trabaja con nosotros:** Claudient está respaldado por [Uitbreiden](https://uitbreiden.com/) — construimos productos de IA y soluciones B2B con comunidades de desarrolladores. [uitbreiden.com](https://uitbreiden.com/)