@jgamaraalv/ts-dev-kit 1.0.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.
- package/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +24 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/agents/accessibility-pro.md +139 -0
- package/agents/api-builder.md +110 -0
- package/agents/code-reviewer.md +190 -0
- package/agents/database-expert.md +138 -0
- package/agents/debugger.md +241 -0
- package/agents/docker-expert.md +51 -0
- package/agents/multi-agent-coordinator.md +378 -0
- package/agents/nextjs-expert.md +136 -0
- package/agents/performance-engineer.md +138 -0
- package/agents/playwright-expert.md +126 -0
- package/agents/react-specialist.md +97 -0
- package/agents/security-scanner.md +105 -0
- package/agents/test-generator.md +221 -0
- package/agents/typescript-pro.md +253 -0
- package/agents/ux-optimizer.md +93 -0
- package/docs/rules/orchestration.md.template +126 -0
- package/package.json +28 -0
- package/skills/bullmq/SKILL.md +225 -0
- package/skills/bullmq/references/flows-and-schedulers.md +186 -0
- package/skills/bullmq/references/job-types-and-options.md +163 -0
- package/skills/bullmq/references/patterns.md +273 -0
- package/skills/bullmq/references/production.md +308 -0
- package/skills/composition-patterns/SKILL.md +58 -0
- package/skills/composition-patterns/references/architecture-avoid-boolean-props.md +87 -0
- package/skills/composition-patterns/references/architecture-compound-components.md +107 -0
- package/skills/composition-patterns/references/patterns-children-over-render-props.md +77 -0
- package/skills/composition-patterns/references/patterns-explicit-variants.md +87 -0
- package/skills/composition-patterns/references/react19-no-forwardref.md +37 -0
- package/skills/composition-patterns/references/state-context-interface.md +194 -0
- package/skills/composition-patterns/references/state-decouple-implementation.md +96 -0
- package/skills/composition-patterns/references/state-lift-state.md +126 -0
- package/skills/conventional-commits/SKILL.md +148 -0
- package/skills/docker/SKILL.md +55 -0
- package/skills/docker/references/compose-configs.md +95 -0
- package/skills/docker/references/monorepo-dockerfile.md +111 -0
- package/skills/drizzle-pg/SKILL.md +202 -0
- package/skills/drizzle-pg/references/advanced.md +299 -0
- package/skills/drizzle-pg/references/migrations.md +214 -0
- package/skills/drizzle-pg/references/queries.md +321 -0
- package/skills/drizzle-pg/references/relations.md +272 -0
- package/skills/drizzle-pg/references/schema-pg.md +256 -0
- package/skills/drizzle-pg/references/sql-operator.md +215 -0
- package/skills/fastify-best-practices/SKILL.md +143 -0
- package/skills/fastify-best-practices/references/hooks-and-lifecycle.md +122 -0
- package/skills/fastify-best-practices/references/plugins-and-encapsulation.md +137 -0
- package/skills/fastify-best-practices/references/request-reply-errors.md +189 -0
- package/skills/fastify-best-practices/references/routes-and-handlers.md +134 -0
- package/skills/fastify-best-practices/references/server-and-options.md +127 -0
- package/skills/fastify-best-practices/references/typescript-and-logging.md +223 -0
- package/skills/fastify-best-practices/references/validation-and-serialization.md +190 -0
- package/skills/ioredis/SKILL.md +51 -0
- package/skills/ioredis/references/advanced-patterns.md +312 -0
- package/skills/ioredis/references/cluster-sentinel.md +280 -0
- package/skills/ioredis/references/connection-options.md +187 -0
- package/skills/ioredis/references/core-api.md +179 -0
- package/skills/nextjs-best-practices/SKILL.md +194 -0
- package/skills/nextjs-best-practices/references/async-patterns.md +84 -0
- package/skills/nextjs-best-practices/references/bundling.md +192 -0
- package/skills/nextjs-best-practices/references/data-patterns.md +310 -0
- package/skills/nextjs-best-practices/references/debug-tricks.md +127 -0
- package/skills/nextjs-best-practices/references/directives.md +74 -0
- package/skills/nextjs-best-practices/references/error-handling.md +237 -0
- package/skills/nextjs-best-practices/references/file-conventions.md +152 -0
- package/skills/nextjs-best-practices/references/font.md +175 -0
- package/skills/nextjs-best-practices/references/functions.md +116 -0
- package/skills/nextjs-best-practices/references/hydration-error.md +86 -0
- package/skills/nextjs-best-practices/references/image.md +184 -0
- package/skills/nextjs-best-practices/references/metadata.md +305 -0
- package/skills/nextjs-best-practices/references/parallel-routes.md +299 -0
- package/skills/nextjs-best-practices/references/route-handlers.md +154 -0
- package/skills/nextjs-best-practices/references/rsc-boundaries.md +168 -0
- package/skills/nextjs-best-practices/references/runtime-selection.md +40 -0
- package/skills/nextjs-best-practices/references/scripts.md +148 -0
- package/skills/nextjs-best-practices/references/self-hosting.md +210 -0
- package/skills/nextjs-best-practices/references/suspense-boundaries.md +67 -0
- package/skills/owasp-security-review/SKILL.md +98 -0
- package/skills/owasp-security-review/references/a01-broken-access-control.md +78 -0
- package/skills/owasp-security-review/references/a02-security-misconfiguration.md +81 -0
- package/skills/owasp-security-review/references/a03-supply-chain-failures.md +65 -0
- package/skills/owasp-security-review/references/a04-cryptographic-failures.md +82 -0
- package/skills/owasp-security-review/references/a05-injection.md +106 -0
- package/skills/owasp-security-review/references/a06-insecure-design.md +76 -0
- package/skills/owasp-security-review/references/a07-authentication-failures.md +83 -0
- package/skills/owasp-security-review/references/a08-integrity-failures.md +72 -0
- package/skills/owasp-security-review/references/a09-logging-alerting-failures.md +76 -0
- package/skills/owasp-security-review/references/a10-exceptional-conditions.md +131 -0
- package/skills/postgresql/SKILL.md +50 -0
- package/skills/postgresql/references/ddl-schema.md +300 -0
- package/skills/postgresql/references/indexes.md +257 -0
- package/skills/postgresql/references/jsonb.md +261 -0
- package/skills/postgresql/references/performance.md +291 -0
- package/skills/postgresql/references/psql-cli.md +153 -0
- package/skills/postgresql/references/queries.md +287 -0
- package/skills/postgresql/references/transactions.md +280 -0
- package/skills/react-best-practices/SKILL.md +110 -0
- package/skills/react-best-practices/references/advanced-patterns.md +91 -0
- package/skills/react-best-practices/references/async-patterns.md +233 -0
- package/skills/react-best-practices/references/bundle-optimization.md +201 -0
- package/skills/react-best-practices/references/client-patterns.md +178 -0
- package/skills/react-best-practices/references/js-performance.md +210 -0
- package/skills/react-best-practices/references/rendering-performance.md +209 -0
- package/skills/react-best-practices/references/rerender-optimization.md +316 -0
- package/skills/react-best-practices/references/server-performance.md +274 -0
- package/skills/service-worker/SKILL.md +195 -0
- package/skills/service-worker/references/api-reference.md +114 -0
- package/skills/service-worker/references/caching-strategies.md +202 -0
- package/skills/service-worker/references/push-and-sync.md +261 -0
- package/skills/typescript-conventions/SKILL.md +51 -0
- package/skills/ui-ux-guidelines/SKILL.md +105 -0
- package/skills/ui-ux-guidelines/references/accessibility-and-interaction.md +74 -0
- package/skills/ui-ux-guidelines/references/forms-content-checklist.md +126 -0
- package/skills/ui-ux-guidelines/references/layout-typography-animation.md +95 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Scripts
|
|
2
|
+
|
|
3
|
+
Loading third-party scripts in Next.js.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Use next/script](#use-nextscript)
|
|
8
|
+
- [Inline Scripts Need ID](#inline-scripts-need-id)
|
|
9
|
+
- [Don't Put Script in Head](#dont-put-script-in-head)
|
|
10
|
+
- [Loading Strategies](#loading-strategies)
|
|
11
|
+
- [Google Analytics](#google-analytics)
|
|
12
|
+
- [Google Tag Manager](#google-tag-manager)
|
|
13
|
+
- [Other Third-Party Scripts](#other-third-party-scripts)
|
|
14
|
+
- [Quick Reference](#quick-reference)
|
|
15
|
+
|
|
16
|
+
## Use next/script
|
|
17
|
+
|
|
18
|
+
Always use `next/script` instead of native `<script>` tags for better performance.
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
// Bad: Native script tag
|
|
22
|
+
<script src="https://example.com/script.js"></script>;
|
|
23
|
+
|
|
24
|
+
// Good: Next.js Script component
|
|
25
|
+
import Script from "next/script";
|
|
26
|
+
|
|
27
|
+
<Script src="https://example.com/script.js" />;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Inline Scripts Need ID
|
|
31
|
+
|
|
32
|
+
Inline scripts require an `id` attribute for Next.js to track them.
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
// Bad: Missing id
|
|
36
|
+
<Script dangerouslySetInnerHTML={{ __html: 'console.log("hi")' }} />
|
|
37
|
+
|
|
38
|
+
// Good: Has id
|
|
39
|
+
<Script id="my-script" dangerouslySetInnerHTML={{ __html: 'console.log("hi")' }} />
|
|
40
|
+
|
|
41
|
+
// Good: Inline with id
|
|
42
|
+
<Script id="show-banner">
|
|
43
|
+
{`document.getElementById('banner').classList.remove('hidden')`}
|
|
44
|
+
</Script>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Don't Put Script in Head
|
|
48
|
+
|
|
49
|
+
`next/script` should not be placed inside `next/head`. It handles its own positioning.
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// Bad: Script inside Head
|
|
53
|
+
import Head from 'next/head'
|
|
54
|
+
import Script from 'next/script'
|
|
55
|
+
|
|
56
|
+
<Head>
|
|
57
|
+
<Script src="/analytics.js" />
|
|
58
|
+
</Head>
|
|
59
|
+
|
|
60
|
+
// Good: Script outside Head
|
|
61
|
+
<Head>
|
|
62
|
+
<title>Page</title>
|
|
63
|
+
</Head>
|
|
64
|
+
<Script src="/analytics.js" />
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Loading Strategies
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
// afterInteractive (default) - Load after page is interactive
|
|
71
|
+
<Script src="/analytics.js" strategy="afterInteractive" />
|
|
72
|
+
|
|
73
|
+
// lazyOnload - Load during idle time
|
|
74
|
+
<Script src="/widget.js" strategy="lazyOnload" />
|
|
75
|
+
|
|
76
|
+
// beforeInteractive - Load before page is interactive (use sparingly)
|
|
77
|
+
// Only works in app/layout.tsx or pages/_document.js
|
|
78
|
+
<Script src="/critical.js" strategy="beforeInteractive" />
|
|
79
|
+
|
|
80
|
+
// worker - Load in web worker (experimental)
|
|
81
|
+
<Script src="/heavy.js" strategy="worker" />
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Google Analytics
|
|
85
|
+
|
|
86
|
+
Use `@next/third-parties` instead of inline GA scripts.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
// Bad: Inline GA script
|
|
90
|
+
<Script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX" />
|
|
91
|
+
<Script id="ga-init">
|
|
92
|
+
{`window.dataLayer = window.dataLayer || [];
|
|
93
|
+
function gtag(){dataLayer.push(arguments);}
|
|
94
|
+
gtag('js', new Date());
|
|
95
|
+
gtag('config', 'G-XXXXX');`}
|
|
96
|
+
</Script>
|
|
97
|
+
|
|
98
|
+
// Good: Next.js component
|
|
99
|
+
import { GoogleAnalytics } from '@next/third-parties/google'
|
|
100
|
+
|
|
101
|
+
export default function Layout({ children }) {
|
|
102
|
+
return (
|
|
103
|
+
<html>
|
|
104
|
+
<body>{children}</body>
|
|
105
|
+
<GoogleAnalytics gaId="G-XXXXX" />
|
|
106
|
+
</html>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Google Tag Manager
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { GoogleTagManager } from "@next/third-parties/google";
|
|
115
|
+
|
|
116
|
+
export default function Layout({ children }) {
|
|
117
|
+
return (
|
|
118
|
+
<html>
|
|
119
|
+
<GoogleTagManager gtmId="GTM-XXXXX" />
|
|
120
|
+
<body>{children}</body>
|
|
121
|
+
</html>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Other Third-Party Scripts
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
// YouTube embed
|
|
130
|
+
import { YouTubeEmbed } from "@next/third-parties/google";
|
|
131
|
+
|
|
132
|
+
<YouTubeEmbed videoid="dQw4w9WgXcQ" />;
|
|
133
|
+
|
|
134
|
+
// Google Maps
|
|
135
|
+
import { GoogleMapsEmbed } from "@next/third-parties/google";
|
|
136
|
+
|
|
137
|
+
<GoogleMapsEmbed apiKey="YOUR_API_KEY" mode="place" q="Brooklyn+Bridge,New+York,NY" />;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Quick Reference
|
|
141
|
+
|
|
142
|
+
| Pattern | Issue | Fix |
|
|
143
|
+
| --------------------------------------------- | -------------------------- | ------------------------- |
|
|
144
|
+
| `<script src="...">` | No optimization | Use `next/script` |
|
|
145
|
+
| `<Script>` without id | Can't track inline scripts | Add `id` attribute |
|
|
146
|
+
| `<Script>` inside `<Head>` | Wrong placement | Move outside Head |
|
|
147
|
+
| Inline GA/GTM scripts | No optimization | Use `@next/third-parties` |
|
|
148
|
+
| `strategy="beforeInteractive"` outside layout | Won't work | Only use in root layout |
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Self-Hosting Next.js
|
|
2
|
+
|
|
3
|
+
Deploy Next.js outside of Vercel with confidence.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Standalone Output](#standalone-output)
|
|
8
|
+
- [ISR and Cache Handlers](#isr-and-cache-handlers)
|
|
9
|
+
- [What Works vs What Needs Setup](#what-works-vs-what-needs-setup)
|
|
10
|
+
- [Image Optimization](#image-optimization)
|
|
11
|
+
- [Environment Variables](#environment-variables)
|
|
12
|
+
- [OpenNext: Serverless Without Vercel](#opennext-serverless-without-vercel)
|
|
13
|
+
- [Pre-Deployment Checklist](#pre-deployment-checklist)
|
|
14
|
+
- [Testing Cache Handler](#testing-cache-handler)
|
|
15
|
+
|
|
16
|
+
## Standalone Output
|
|
17
|
+
|
|
18
|
+
For Docker or any containerized deployment, use standalone output:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// next.config.js
|
|
22
|
+
export default {
|
|
23
|
+
output: "standalone",
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This creates a minimal `standalone` folder with only production dependencies:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
.next/
|
|
31
|
+
├── standalone/
|
|
32
|
+
│ ├── server.js # Entry point
|
|
33
|
+
│ ├── node_modules/ # Only production deps
|
|
34
|
+
│ └── .next/ # Build output
|
|
35
|
+
└── static/ # Must be copied separately
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Key points for containers:**
|
|
39
|
+
|
|
40
|
+
- Set `HOSTNAME="0.0.0.0"` for containers
|
|
41
|
+
- Copy `public/` and `.next/static/` separately (not included in standalone)
|
|
42
|
+
- Run with `node server.js`
|
|
43
|
+
|
|
44
|
+
## ISR and Cache Handlers
|
|
45
|
+
|
|
46
|
+
### The Problem
|
|
47
|
+
|
|
48
|
+
ISR (Incremental Static Regeneration) uses filesystem caching by default. This **breaks with multiple instances**:
|
|
49
|
+
|
|
50
|
+
- Instance A regenerates page -> saves to its local disk
|
|
51
|
+
- Instance B serves stale page -> doesn't see Instance A's cache
|
|
52
|
+
- Load balancer sends users to random instances -> inconsistent content
|
|
53
|
+
|
|
54
|
+
### Solution: Custom Cache Handler
|
|
55
|
+
|
|
56
|
+
Next.js 14+ supports custom cache handlers for shared storage:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// next.config.js
|
|
60
|
+
import { resolve } from "node:path";
|
|
61
|
+
|
|
62
|
+
export default {
|
|
63
|
+
cacheHandler: resolve("./cache-handler.js"),
|
|
64
|
+
cacheMaxMemorySize: 0, // Disable in-memory cache
|
|
65
|
+
};
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### Redis Cache Handler Example
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
// cache-handler.js
|
|
72
|
+
import { Redis } from "ioredis";
|
|
73
|
+
|
|
74
|
+
const redis = new Redis(process.env.REDIS_URL);
|
|
75
|
+
const CACHE_PREFIX = "nextjs:";
|
|
76
|
+
|
|
77
|
+
export default class CacheHandler {
|
|
78
|
+
constructor(options) {
|
|
79
|
+
this.options = options;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async get(key) {
|
|
83
|
+
const data = await redis.get(CACHE_PREFIX + key);
|
|
84
|
+
if (!data) return null;
|
|
85
|
+
|
|
86
|
+
const parsed = JSON.parse(data);
|
|
87
|
+
return {
|
|
88
|
+
value: parsed.value,
|
|
89
|
+
lastModified: parsed.lastModified,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async set(key, data, ctx) {
|
|
94
|
+
const cacheData = {
|
|
95
|
+
value: data,
|
|
96
|
+
lastModified: Date.now(),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
if (ctx?.revalidate) {
|
|
100
|
+
await redis.setex(CACHE_PREFIX + key, ctx.revalidate, JSON.stringify(cacheData));
|
|
101
|
+
} else {
|
|
102
|
+
await redis.set(CACHE_PREFIX + key, JSON.stringify(cacheData));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async revalidateTag(tags) {
|
|
107
|
+
// Implement tag-based invalidation
|
|
108
|
+
// This requires tracking which keys have which tags
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## What Works vs What Needs Setup
|
|
114
|
+
|
|
115
|
+
| Feature | Single Instance | Multi-Instance | Notes |
|
|
116
|
+
| -------------------- | --------------- | ------------------- | --------------------------- |
|
|
117
|
+
| SSR | Yes | Yes | No special setup |
|
|
118
|
+
| SSG | Yes | Yes | Built at deploy time |
|
|
119
|
+
| ISR | Yes | Needs cache handler | Filesystem cache breaks |
|
|
120
|
+
| Image Optimization | Yes | Yes | CPU-intensive, consider CDN |
|
|
121
|
+
| Middleware | Yes | Yes | Runs on Node.js |
|
|
122
|
+
| Edge Runtime | Limited | Limited | Some features Node-only |
|
|
123
|
+
| `revalidatePath/Tag` | Yes | Needs cache handler | Must share cache |
|
|
124
|
+
| `next/font` | Yes | Yes | Fonts bundled at build |
|
|
125
|
+
| Draft Mode | Yes | Yes | Cookie-based |
|
|
126
|
+
|
|
127
|
+
## Image Optimization
|
|
128
|
+
|
|
129
|
+
Next.js Image Optimization works out of the box but is CPU-intensive. For scale, offload to an external loader (Cloudinary, Imgix, etc.):
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
// next.config.js
|
|
133
|
+
export default {
|
|
134
|
+
images: {
|
|
135
|
+
loader: "custom",
|
|
136
|
+
loaderFile: "./lib/image-loader.js",
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
// lib/image-loader.js
|
|
143
|
+
export default function cloudinaryLoader({ src, width, quality }) {
|
|
144
|
+
const params = ["f_auto", "c_limit", `w_${width}`, `q_${quality || "auto"}`];
|
|
145
|
+
return `https://res.cloudinary.com/demo/image/upload/${params.join(",")}${src}`;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For simple setups, tune the built-in optimizer with `minimumCacheTTL` and limited `deviceSizes`.
|
|
150
|
+
|
|
151
|
+
## Environment Variables
|
|
152
|
+
|
|
153
|
+
### Build-time vs Runtime
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
// Available at build time only (baked into bundle)
|
|
157
|
+
NEXT_PUBLIC_API_URL=https://api.example.com
|
|
158
|
+
|
|
159
|
+
// Available at runtime (server-side only)
|
|
160
|
+
DATABASE_URL=postgresql://...
|
|
161
|
+
API_SECRET=...
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Runtime Configuration
|
|
165
|
+
|
|
166
|
+
For truly dynamic config, don't use `NEXT_PUBLIC_*`. Instead:
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
// app/api/config/route.ts
|
|
170
|
+
export async function GET() {
|
|
171
|
+
return Response.json({
|
|
172
|
+
apiUrl: process.env.API_URL,
|
|
173
|
+
features: process.env.FEATURES?.split(","),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## OpenNext: Serverless Without Vercel
|
|
179
|
+
|
|
180
|
+
[OpenNext](https://open-next.js.org/) adapts Next.js for AWS Lambda, Cloudflare Workers, etc. Supports AWS Lambda + CloudFront, Cloudflare Workers, Netlify Functions, and Deno Deploy.
|
|
181
|
+
|
|
182
|
+
## Pre-Deployment Checklist
|
|
183
|
+
|
|
184
|
+
1. **Build locally first**: `npm run build` - catch errors before deploy
|
|
185
|
+
2. **Test standalone output**: `node .next/standalone/server.js`
|
|
186
|
+
3. **Set `output: 'standalone'`** for Docker
|
|
187
|
+
4. **Configure cache handler** for multi-instance ISR
|
|
188
|
+
5. **Set `HOSTNAME="0.0.0.0"`** for containers
|
|
189
|
+
6. **Copy `public/` and `.next/static/`** - not included in standalone
|
|
190
|
+
7. **Add health check endpoint**
|
|
191
|
+
8. **Test ISR revalidation** after deployment
|
|
192
|
+
9. **Monitor memory usage** - Node.js defaults may need tuning
|
|
193
|
+
|
|
194
|
+
## Testing Cache Handler
|
|
195
|
+
|
|
196
|
+
**Critical**: Test your cache handler on every Next.js upgrade:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Start multiple instances
|
|
200
|
+
PORT=3001 node .next/standalone/server.js &
|
|
201
|
+
PORT=3002 node .next/standalone/server.js &
|
|
202
|
+
|
|
203
|
+
# Trigger ISR revalidation
|
|
204
|
+
curl http://localhost:3001/api/revalidate?path=/posts
|
|
205
|
+
|
|
206
|
+
# Verify both instances see the update
|
|
207
|
+
curl http://localhost:3001/posts
|
|
208
|
+
curl http://localhost:3002/posts
|
|
209
|
+
# Should return identical content
|
|
210
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Suspense Boundaries
|
|
2
|
+
|
|
3
|
+
Client hooks that cause CSR bailout without Suspense boundaries.
|
|
4
|
+
|
|
5
|
+
## useSearchParams
|
|
6
|
+
|
|
7
|
+
Always requires Suspense boundary in static routes. Without it, the entire page becomes client-side rendered.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
// Bad: Entire page becomes CSR
|
|
11
|
+
"use client";
|
|
12
|
+
|
|
13
|
+
import { useSearchParams } from "next/navigation";
|
|
14
|
+
|
|
15
|
+
export default function SearchBar() {
|
|
16
|
+
const searchParams = useSearchParams();
|
|
17
|
+
return <div>Query: {searchParams.get("q")}</div>;
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
// Good: Wrap in Suspense
|
|
23
|
+
import { Suspense } from "react";
|
|
24
|
+
import SearchBar from "./search-bar";
|
|
25
|
+
|
|
26
|
+
export default function Page() {
|
|
27
|
+
return (
|
|
28
|
+
<Suspense fallback={<div>Loading...</div>}>
|
|
29
|
+
<SearchBar />
|
|
30
|
+
</Suspense>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## usePathname
|
|
36
|
+
|
|
37
|
+
Requires Suspense boundary when route has dynamic parameters.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// In dynamic route [slug]
|
|
41
|
+
// Bad: No Suspense
|
|
42
|
+
"use client";
|
|
43
|
+
import { usePathname } from "next/navigation";
|
|
44
|
+
|
|
45
|
+
export function Breadcrumb() {
|
|
46
|
+
const pathname = usePathname();
|
|
47
|
+
return <nav>{pathname}</nav>;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// Good: Wrap in Suspense
|
|
53
|
+
<Suspense fallback={<BreadcrumbSkeleton />}>
|
|
54
|
+
<Breadcrumb />
|
|
55
|
+
</Suspense>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If you use `generateStaticParams`, Suspense is optional.
|
|
59
|
+
|
|
60
|
+
## Quick Reference
|
|
61
|
+
|
|
62
|
+
| Hook | Suspense Required |
|
|
63
|
+
| ------------------- | -------------------- |
|
|
64
|
+
| `useSearchParams()` | Yes |
|
|
65
|
+
| `usePathname()` | Yes (dynamic routes) |
|
|
66
|
+
| `useParams()` | No |
|
|
67
|
+
| `useRouter()` | No |
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: owasp-security-review
|
|
3
|
+
description: "Review code and architectures against the OWASP Top 10:2025 — the ten most critical web application security risks. Use when: (1) reviewing code for security vulnerabilities, (2) auditing a feature or codebase against OWASP categories, (3) providing remediation guidance for identified vulnerabilities, (4) writing new code and needing secure coding patterns. Triggers: 'review for security', 'OWASP audit', 'check for vulnerabilities','security checklist', 'is this code secure', 'security review', 'fix vulnerability'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OWASP Top 10:2025 Security Review
|
|
7
|
+
|
|
8
|
+
## Quick reference
|
|
9
|
+
|
|
10
|
+
| # | Category | Key risk | Avg incidence |
|
|
11
|
+
| --- | ------------------------------------- | ---------------------------------------------------------------------- | ------------- |
|
|
12
|
+
| A01 | Broken Access Control | Unauthorized data access, privilege escalation, SSRF, CSRF | 3.74% |
|
|
13
|
+
| A02 | Security Misconfiguration | Default creds, verbose errors, missing hardening, XXE | 3.00% |
|
|
14
|
+
| A03 | Software Supply Chain Failures | Vulnerable/malicious dependencies, compromised build pipelines | 5.72% |
|
|
15
|
+
| A04 | Cryptographic Failures | Weak algorithms, hardcoded keys, missing encryption, weak hashing | 3.80% |
|
|
16
|
+
| A05 | Injection | SQLi, XSS, command injection, LDAP/XPath/EL injection | 3.08% |
|
|
17
|
+
| A06 | Insecure Design | Missing threat modeling, business logic flaws, insufficient controls | 1.86% |
|
|
18
|
+
| A07 | Authentication Failures | Credential stuffing, weak passwords, session fixation, missing MFA | 2.92% |
|
|
19
|
+
| A08 | Software/Data Integrity Failures | Unsigned updates, insecure deserialization, untrusted CDN code | 2.75% |
|
|
20
|
+
| A09 | Security Logging & Alerting Failures | Missing audit logs, no alerting, log injection, sensitive data in logs | 3.91% |
|
|
21
|
+
| A10 | Mishandling of Exceptional Conditions | Failing open, info leakage via errors, unchecked return values | 2.95% |
|
|
22
|
+
|
|
23
|
+
## Workflows
|
|
24
|
+
|
|
25
|
+
### 1. Code review for security
|
|
26
|
+
|
|
27
|
+
Systematically check the code against each relevant category:
|
|
28
|
+
|
|
29
|
+
1. **Identify the code's surface area** — Does it handle auth? User input? File uploads? External data? Crypto? Error responses?
|
|
30
|
+
2. **Select relevant categories** from the table above based on the surface area.
|
|
31
|
+
3. **Load the reference file** for each relevant category and check the code against the "What to look for" section.
|
|
32
|
+
4. **Report findings** grouped by category with severity (Critical/High/Medium/Low), the specific code location, and a concrete fix.
|
|
33
|
+
|
|
34
|
+
Priority order for review (highest impact first):
|
|
35
|
+
|
|
36
|
+
- `[CRITICAL]` Input handling code → A05 (Injection), A01 (Access Control)
|
|
37
|
+
- `[CRITICAL]` Auth/session code → A07 (Authentication), A01 (Access Control)
|
|
38
|
+
- `[HIGH]` Data storage/transmission → A04 (Cryptographic Failures)
|
|
39
|
+
- `[HIGH]` Configuration/deployment → A02 (Security Misconfiguration)
|
|
40
|
+
- `[HIGH]` Dependencies → A03 (Supply Chain)
|
|
41
|
+
- `[MEDIUM]` Error handling → A10 (Exceptional Conditions), A09 (Logging)
|
|
42
|
+
- `[MEDIUM]` Architecture/design → A06 (Insecure Design)
|
|
43
|
+
- `[MEDIUM]` Data integrity → A08 (Integrity Failures)
|
|
44
|
+
|
|
45
|
+
### 2. Security audit checklist
|
|
46
|
+
|
|
47
|
+
Generate a checklist for a feature or codebase:
|
|
48
|
+
|
|
49
|
+
1. Read the feature/codebase to understand its scope.
|
|
50
|
+
2. For each of the 10 categories, determine if it applies.
|
|
51
|
+
3. For applicable categories, load the reference file and produce a checklist of items to verify.
|
|
52
|
+
4. Output a markdown checklist grouped by category.
|
|
53
|
+
|
|
54
|
+
### 3. Remediation guidance
|
|
55
|
+
|
|
56
|
+
When a vulnerability is identified:
|
|
57
|
+
|
|
58
|
+
1. Classify it into the correct OWASP category.
|
|
59
|
+
2. Load the corresponding reference file.
|
|
60
|
+
3. Apply the prevention checklist to produce a specific, actionable fix.
|
|
61
|
+
4. Provide a code example of the fix when possible.
|
|
62
|
+
|
|
63
|
+
## Reference files
|
|
64
|
+
|
|
65
|
+
Load the relevant file when you need detailed guidance for a specific category:
|
|
66
|
+
|
|
67
|
+
- **A01 Broken Access Control** — authorization checks, IDOR, CORS, CSRF, path traversal: [references/a01-broken-access-control.md](references/a01-broken-access-control.md)
|
|
68
|
+
- **A02 Security Misconfiguration** — hardening, default creds, error messages, headers, XXE: [references/a02-security-misconfiguration.md](references/a02-security-misconfiguration.md)
|
|
69
|
+
- **A03 Supply Chain Failures** — dependency management, SBOM, build pipeline security: [references/a03-supply-chain-failures.md](references/a03-supply-chain-failures.md)
|
|
70
|
+
- **A04 Cryptographic Failures** — encryption, hashing, key management, TLS, PRNG: [references/a04-cryptographic-failures.md](references/a04-cryptographic-failures.md)
|
|
71
|
+
- **A05 Injection** — SQL, XSS, command, ORM, LDAP, template injection: [references/a05-injection.md](references/a05-injection.md)
|
|
72
|
+
- **A06 Insecure Design** — threat modeling, business logic, secure SDLC: [references/a06-insecure-design.md](references/a06-insecure-design.md)
|
|
73
|
+
- **A07 Authentication Failures** — credential stuffing, MFA, session management, password policy: [references/a07-authentication-failures.md](references/a07-authentication-failures.md)
|
|
74
|
+
- **A08 Integrity Failures** — deserialization, code signing, untrusted sources, CDN trust: [references/a08-integrity-failures.md](references/a08-integrity-failures.md)
|
|
75
|
+
- **A09 Logging & Alerting** — audit trails, log injection, alerting, sensitive data in logs: [references/a09-logging-alerting-failures.md](references/a09-logging-alerting-failures.md)
|
|
76
|
+
- **A10 Exceptional Conditions** — error handling, fail-closed, resource cleanup, info leakage: [references/a10-exceptional-conditions.md](references/a10-exceptional-conditions.md)
|
|
77
|
+
|
|
78
|
+
## Severity classification
|
|
79
|
+
|
|
80
|
+
Use these severity levels when reporting findings:
|
|
81
|
+
|
|
82
|
+
- **Critical**: Directly exploitable, leads to full system compromise or mass data breach (e.g., SQLi with no parameterization, hardcoded admin credentials, missing auth on admin endpoints).
|
|
83
|
+
- **High**: Exploitable with moderate effort, significant data exposure or privilege escalation (e.g., IDOR, weak password hashing, SSRF, deserialization of untrusted data).
|
|
84
|
+
- **Medium**: Exploitable under specific conditions, limited impact (e.g., missing CSRF protection, verbose error messages, missing security headers).
|
|
85
|
+
- **Low**: Defense-in-depth issue, minimal direct impact (e.g., missing rate limiting, incomplete logging, suboptimal crypto configuration).
|
|
86
|
+
|
|
87
|
+
## Output format
|
|
88
|
+
|
|
89
|
+
When reporting security findings, use this structure:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
### [SEVERITY] A0X: Category Name — Brief title
|
|
93
|
+
|
|
94
|
+
**Location**: `file:line`
|
|
95
|
+
**Risk**: What can go wrong and the impact.
|
|
96
|
+
**Finding**: What the code does wrong.
|
|
97
|
+
**Fix**: Specific remediation with code example.
|
|
98
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# A01:2025 Broken Access Control
|
|
2
|
+
|
|
3
|
+
The #1 risk. 40 CWEs, 3.74% avg incidence, 1.8M+ occurrences. Includes SSRF (previously separate).
|
|
4
|
+
|
|
5
|
+
## What to look for
|
|
6
|
+
|
|
7
|
+
**Missing authorization checks:**
|
|
8
|
+
|
|
9
|
+
- API endpoints without auth middleware or role checks
|
|
10
|
+
- Routes accessible without login (force browsing)
|
|
11
|
+
- Missing ownership validation — user can access/modify another user's records by changing an ID
|
|
12
|
+
- POST/PUT/DELETE endpoints with no access control
|
|
13
|
+
- Admin endpoints accessible to regular users
|
|
14
|
+
|
|
15
|
+
**IDOR (Insecure Direct Object References):**
|
|
16
|
+
|
|
17
|
+
- Sequential/predictable IDs in URLs or request bodies (`/api/users/123`)
|
|
18
|
+
- No ownership check when accessing resources by ID
|
|
19
|
+
- Database queries using user-supplied IDs without verifying the requester owns the record
|
|
20
|
+
|
|
21
|
+
**CORS misconfiguration:**
|
|
22
|
+
|
|
23
|
+
- `Access-Control-Allow-Origin: *` on authenticated endpoints
|
|
24
|
+
- Reflecting the `Origin` header without validation
|
|
25
|
+
- Allowing credentials with wildcard origins
|
|
26
|
+
|
|
27
|
+
**CSRF:**
|
|
28
|
+
|
|
29
|
+
- State-changing operations (POST/PUT/DELETE) without CSRF tokens
|
|
30
|
+
- Cookie-based auth without SameSite attribute
|
|
31
|
+
|
|
32
|
+
**Path traversal:**
|
|
33
|
+
|
|
34
|
+
- File paths constructed from user input without sanitization
|
|
35
|
+
- `../` sequences not blocked
|
|
36
|
+
- Symlink following without checks
|
|
37
|
+
|
|
38
|
+
**JWT/session issues:**
|
|
39
|
+
|
|
40
|
+
- JWTs not validated (signature, expiry, audience, issuer)
|
|
41
|
+
- Long-lived JWTs without refresh token rotation
|
|
42
|
+
- Sessions not invalidated on logout
|
|
43
|
+
- Session IDs in URLs
|
|
44
|
+
|
|
45
|
+
**SSRF:**
|
|
46
|
+
|
|
47
|
+
- Server makes HTTP requests to user-supplied URLs
|
|
48
|
+
- No allowlist for internal/external URL targets
|
|
49
|
+
- DNS rebinding not mitigated
|
|
50
|
+
|
|
51
|
+
## Prevention checklist
|
|
52
|
+
|
|
53
|
+
- [ ] Deny by default — only grant access explicitly
|
|
54
|
+
- [ ] Implement access control once, reuse everywhere (middleware/decorator pattern)
|
|
55
|
+
- [ ] Enforce record ownership in queries (`WHERE user_id = ?` with authenticated user's ID)
|
|
56
|
+
- [ ] Validate JWT claims: `aud`, `iss`, `exp`, scopes
|
|
57
|
+
- [ ] Set short JWT expiry + refresh token pattern
|
|
58
|
+
- [ ] Invalidate sessions server-side on logout
|
|
59
|
+
- [ ] Use CSRF tokens or SameSite cookies for state-changing requests
|
|
60
|
+
- [ ] Restrict CORS to specific trusted origins
|
|
61
|
+
- [ ] Disable directory listing; remove `.git`, backups from web root
|
|
62
|
+
- [ ] Log and alert on access control failures
|
|
63
|
+
- [ ] Rate-limit API and controller access
|
|
64
|
+
- [ ] For SSRF: allowlist target hosts/IPs, block internal ranges (169.254.x.x, 10.x.x.x, etc.)
|
|
65
|
+
- [ ] Include access control tests in unit/integration test suites
|
|
66
|
+
|
|
67
|
+
## Key CWEs
|
|
68
|
+
|
|
69
|
+
| CWE | Name | Common in |
|
|
70
|
+
| --- | ------------------------------------------------------- | ------------------------------ |
|
|
71
|
+
| 200 | Exposure of Sensitive Information to Unauthorized Actor | API responses leaking data |
|
|
72
|
+
| 284 | Improper Access Control | Missing auth middleware |
|
|
73
|
+
| 285 | Improper Authorization | Role check bypass |
|
|
74
|
+
| 352 | Cross-Site Request Forgery | Cookie-based auth without CSRF |
|
|
75
|
+
| 862 | Missing Authorization | Endpoints without auth |
|
|
76
|
+
| 863 | Incorrect Authorization | Flawed role logic |
|
|
77
|
+
| 918 | Server-Side Request Forgery | URL fetch from user input |
|
|
78
|
+
| 639 | Authorization Bypass Through User-Controlled Key | IDOR |
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# A02:2025 Security Misconfiguration
|
|
2
|
+
|
|
3
|
+
Moved from #5 to #2. 16 CWEs, 3.00% avg incidence, 719K+ occurrences.
|
|
4
|
+
|
|
5
|
+
## What to look for
|
|
6
|
+
|
|
7
|
+
**Default and unchanged credentials:**
|
|
8
|
+
|
|
9
|
+
- Default admin accounts still active
|
|
10
|
+
- Default passwords in config files or environment variables
|
|
11
|
+
- Database connections using default credentials
|
|
12
|
+
|
|
13
|
+
**Verbose error messages:**
|
|
14
|
+
|
|
15
|
+
- Stack traces exposed to end users
|
|
16
|
+
- Database error details in API responses
|
|
17
|
+
- Framework/library version info in error pages
|
|
18
|
+
- Missing custom error pages (default 404/500 pages)
|
|
19
|
+
|
|
20
|
+
**Unnecessary features enabled:**
|
|
21
|
+
|
|
22
|
+
- Debug mode enabled in production (`DEBUG=true`, `NODE_ENV=development`)
|
|
23
|
+
- Unused ports/services running
|
|
24
|
+
- Sample/test endpoints deployed to production
|
|
25
|
+
- Admin console publicly accessible
|
|
26
|
+
- Directory listing enabled
|
|
27
|
+
|
|
28
|
+
**Missing security headers:**
|
|
29
|
+
|
|
30
|
+
- No `Strict-Transport-Security` (HSTS)
|
|
31
|
+
- No `Content-Security-Policy` (CSP)
|
|
32
|
+
- No `X-Content-Type-Options: nosniff`
|
|
33
|
+
- No `X-Frame-Options` or `Content-Security-Policy: frame-ancestors`
|
|
34
|
+
- No `Referrer-Policy`
|
|
35
|
+
- No `Permissions-Policy`
|
|
36
|
+
|
|
37
|
+
**XXE (XML External Entity):**
|
|
38
|
+
|
|
39
|
+
- XML parsers with external entity processing enabled
|
|
40
|
+
- DTD processing not disabled
|
|
41
|
+
- SOAP services accepting XML without entity restrictions
|
|
42
|
+
|
|
43
|
+
**Cloud/infra misconfig:**
|
|
44
|
+
|
|
45
|
+
- S3 buckets or cloud storage publicly accessible
|
|
46
|
+
- Overly permissive IAM roles
|
|
47
|
+
- Security groups allowing 0.0.0.0/0 ingress
|
|
48
|
+
- Secrets/keys hardcoded or in plaintext config
|
|
49
|
+
|
|
50
|
+
**Cookie security:**
|
|
51
|
+
|
|
52
|
+
- Missing `Secure` flag on cookies in HTTPS
|
|
53
|
+
- Missing `HttpOnly` flag on session cookies
|
|
54
|
+
- Missing or incorrect `SameSite` attribute
|
|
55
|
+
- Sensitive data stored in cookies in cleartext
|
|
56
|
+
|
|
57
|
+
## Prevention checklist
|
|
58
|
+
|
|
59
|
+
- [ ] Automate environment hardening — identical config for dev/QA/prod (only credentials differ)
|
|
60
|
+
- [ ] Remove all unused features, frameworks, sample apps, documentation
|
|
61
|
+
- [ ] Set `NODE_ENV=production` (or equivalent) in production
|
|
62
|
+
- [ ] Implement custom error pages; never expose stack traces
|
|
63
|
+
- [ ] Add all security headers (HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy)
|
|
64
|
+
- [ ] Set cookie flags: `Secure`, `HttpOnly`, `SameSite=Strict` or `Lax`
|
|
65
|
+
- [ ] Disable XML external entity processing and DTDs
|
|
66
|
+
- [ ] Review cloud storage permissions (S3, GCS, Azure Blob)
|
|
67
|
+
- [ ] Use identity federation and short-lived credentials instead of static keys
|
|
68
|
+
- [ ] Automate configuration verification across all environments
|
|
69
|
+
- [ ] Disable directory listing on web servers
|
|
70
|
+
|
|
71
|
+
## Key CWEs
|
|
72
|
+
|
|
73
|
+
| CWE | Name | Common in |
|
|
74
|
+
| ---- | ---------------------------------- | ------------------------ |
|
|
75
|
+
| 16 | Configuration | Broad misconfiguration |
|
|
76
|
+
| 611 | Improper Restriction of XXE | XML parsers |
|
|
77
|
+
| 489 | Active Debug Code | Debug mode in production |
|
|
78
|
+
| 1004 | Sensitive Cookie Without HttpOnly | Session cookies |
|
|
79
|
+
| 614 | Sensitive Cookie Without Secure | HTTPS cookies |
|
|
80
|
+
| 942 | Permissive Cross-domain Policy | CORS/crossdomain.xml |
|
|
81
|
+
| 526 | Exposure via Environment Variables | Leaked env vars |
|