@nextsparkjs/ai-workflow 0.1.0-beta.100
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/LICENSE +21 -0
- package/README.md +115 -0
- package/claude/_docs/workflows-optimizations.md +359 -0
- package/claude/agents/api-tester.md +634 -0
- package/claude/agents/architecture-supervisor.md +1351 -0
- package/claude/agents/backend-developer.md +997 -0
- package/claude/agents/backend-validator.md +417 -0
- package/claude/agents/bdd-docs-writer.md +737 -0
- package/claude/agents/block-developer.md +677 -0
- package/claude/agents/code-reviewer.md +1432 -0
- package/claude/agents/db-developer.md +721 -0
- package/claude/agents/db-validator.md +407 -0
- package/claude/agents/demo-video-generator.md +493 -0
- package/claude/agents/documentation-writer.md +1268 -0
- package/claude/agents/frontend-developer.md +1234 -0
- package/claude/agents/frontend-validator.md +777 -0
- package/claude/agents/functional-validator.md +630 -0
- package/claude/agents/mock-analyst.md +387 -0
- package/claude/agents/product-manager.md +963 -0
- package/claude/agents/qa-automation.md +1762 -0
- package/claude/agents/release-manager.md +634 -0
- package/claude/agents/selectors-translator.md +262 -0
- package/claude/agents/unit-test-writer.md +785 -0
- package/claude/agents/visual-comparator.md +329 -0
- package/claude/agents/workflow-maintainer.md +352 -0
- package/claude/commands/do/README.md +88 -0
- package/claude/commands/do/create-api.md +64 -0
- package/claude/commands/do/create-entity.md +66 -0
- package/claude/commands/do/create-migration.md +64 -0
- package/claude/commands/do/create-plugin.md +56 -0
- package/claude/commands/do/create-theme.md +70 -0
- package/claude/commands/do/mock-data.md +67 -0
- package/claude/commands/do/reset-db.md +71 -0
- package/claude/commands/do/setup-scheduled-action.md +75 -0
- package/claude/commands/do/sync-code-review.md +117 -0
- package/claude/commands/do/update-selectors.md +112 -0
- package/claude/commands/do/use-skills.md +90 -0
- package/claude/commands/do/validate-blocks.md +69 -0
- package/claude/commands/how-to/README.md +261 -0
- package/claude/commands/how-to/add-metadata.md +692 -0
- package/claude/commands/how-to/add-taxonomies.md +806 -0
- package/claude/commands/how-to/add-translations.md +571 -0
- package/claude/commands/how-to/create-api.md +577 -0
- package/claude/commands/how-to/create-block.md +575 -0
- package/claude/commands/how-to/create-child-entities.md +771 -0
- package/claude/commands/how-to/create-entity.md +597 -0
- package/claude/commands/how-to/create-migrations.md +605 -0
- package/claude/commands/how-to/create-plugin.md +654 -0
- package/claude/commands/how-to/customize-app.md +481 -0
- package/claude/commands/how-to/customize-dashboard.md +553 -0
- package/claude/commands/how-to/customize-theme.md +438 -0
- package/claude/commands/how-to/define-features-flows.md +632 -0
- package/claude/commands/how-to/deploy.md +507 -0
- package/claude/commands/how-to/handle-file-uploads.md +746 -0
- package/claude/commands/how-to/implement-search.md +1001 -0
- package/claude/commands/how-to/install-plugins.md +352 -0
- package/claude/commands/how-to/manage-test-coverage.md +984 -0
- package/claude/commands/how-to/run-tests.md +400 -0
- package/claude/commands/how-to/set-app-languages.md +601 -0
- package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
- package/claude/commands/how-to/set-scheduled-actions.md +527 -0
- package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
- package/claude/commands/how-to/setup-authentication.md +388 -0
- package/claude/commands/how-to/setup-claude-code.md +440 -0
- package/claude/commands/how-to/setup-database.md +274 -0
- package/claude/commands/how-to/setup-email-providers.md +598 -0
- package/claude/commands/how-to/setup-mobile-dev.md +627 -0
- package/claude/commands/how-to/start.md +500 -0
- package/claude/commands/how-to/use-devtools.md +639 -0
- package/claude/commands/how-to/use-superadmin.md +622 -0
- package/claude/commands/session/README.md +193 -0
- package/claude/commands/session/block-create.md +190 -0
- package/claude/commands/session/block-list.md +203 -0
- package/claude/commands/session/block-update.md +192 -0
- package/claude/commands/session/block-validate.md +218 -0
- package/claude/commands/session/changelog.md +115 -0
- package/claude/commands/session/close.md +225 -0
- package/claude/commands/session/commit.md +174 -0
- package/claude/commands/session/db-entity.md +206 -0
- package/claude/commands/session/db-fix.md +212 -0
- package/claude/commands/session/db-sample.md +206 -0
- package/claude/commands/session/demo.md +178 -0
- package/claude/commands/session/doc-bdd.md +207 -0
- package/claude/commands/session/doc-feature.md +218 -0
- package/claude/commands/session/doc-read.md +225 -0
- package/claude/commands/session/execute.md +204 -0
- package/claude/commands/session/explain.md +202 -0
- package/claude/commands/session/fix-bug.md +210 -0
- package/claude/commands/session/fix-build.md +182 -0
- package/claude/commands/session/fix-test.md +189 -0
- package/claude/commands/session/pending.md +232 -0
- package/claude/commands/session/refine.md +188 -0
- package/claude/commands/session/resume.md +192 -0
- package/claude/commands/session/review.md +192 -0
- package/claude/commands/session/scope-change.md +181 -0
- package/claude/commands/session/start-blocks.md +347 -0
- package/claude/commands/session/start.md +604 -0
- package/claude/commands/session/status.md +169 -0
- package/claude/commands/session/test-fix.md +221 -0
- package/claude/commands/session/test-run.md +203 -0
- package/claude/commands/session/test-write.md +242 -0
- package/claude/commands/session/validate.md +162 -0
- package/claude/config/context.json +40 -0
- package/claude/config/github.json +69 -0
- package/claude/config/github.schema.json +106 -0
- package/claude/config/team.json +46 -0
- package/claude/config/team.schema.json +106 -0
- package/claude/config/workspace.json +43 -0
- package/claude/config/workspace.schema.json +75 -0
- package/claude/skills/README.md +228 -0
- package/claude/skills/accessibility/SKILL.md +573 -0
- package/claude/skills/api-bypass-layers/SKILL.md +550 -0
- package/claude/skills/asana-integration/SKILL.md +499 -0
- package/claude/skills/better-auth/SKILL.md +666 -0
- package/claude/skills/billing-subscriptions/SKILL.md +660 -0
- package/claude/skills/block-decision-matrix/SKILL.md +359 -0
- package/claude/skills/clickup-integration/SKILL.md +434 -0
- package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
- package/claude/skills/create-plugin/SKILL.md +425 -0
- package/claude/skills/create-theme/SKILL.md +331 -0
- package/claude/skills/cypress-api/SKILL.md +511 -0
- package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
- package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
- package/claude/skills/cypress-e2e/SKILL.md +526 -0
- package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
- package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
- package/claude/skills/cypress-selectors/SKILL.md +309 -0
- package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
- package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
- package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
- package/claude/skills/database-migrations/SKILL.md +335 -0
- package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
- package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
- package/claude/skills/design-system/SKILL.md +682 -0
- package/claude/skills/documentation/SKILL.md +540 -0
- package/claude/skills/entity-api/SKILL.md +482 -0
- package/claude/skills/entity-system/SKILL.md +635 -0
- package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
- package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
- package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
- package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
- package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
- package/claude/skills/github/SKILL.md +467 -0
- package/claude/skills/i18n-nextintl/SKILL.md +302 -0
- package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
- package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
- package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
- package/claude/skills/impact-analysis/SKILL.md +203 -0
- package/claude/skills/jest-unit/SKILL.md +306 -0
- package/claude/skills/jest-unit/references/component-testing.md +371 -0
- package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
- package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
- package/claude/skills/jira-integration/SKILL.md +539 -0
- package/claude/skills/media-library/SKILL.md +743 -0
- package/claude/skills/mock-analysis/SKILL.md +276 -0
- package/claude/skills/monorepo-architecture/SKILL.md +162 -0
- package/claude/skills/nextjs-api-development/SKILL.md +364 -0
- package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
- package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
- package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
- package/claude/skills/notion-integration/SKILL.md +641 -0
- package/claude/skills/npm-development-workflow/SKILL.md +480 -0
- package/claude/skills/page-builder-blocks/SKILL.md +530 -0
- package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
- package/claude/skills/permissions-system/SKILL.md +619 -0
- package/claude/skills/plugins/SKILL.md +340 -0
- package/claude/skills/plugins/references/plugin-templates.md +414 -0
- package/claude/skills/plugins/references/plugin-testing.md +353 -0
- package/claude/skills/plugins/references/plugin-types.md +198 -0
- package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
- package/claude/skills/pom-patterns/SKILL.md +452 -0
- package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
- package/claude/skills/rate-limiting/SKILL.md +342 -0
- package/claude/skills/react-best-practices/AGENTS.md +2410 -0
- package/claude/skills/react-best-practices/README.md +123 -0
- package/claude/skills/react-best-practices/SKILL.md +125 -0
- package/claude/skills/react-best-practices/metadata.json +15 -0
- package/claude/skills/react-best-practices/rules/_sections.md +46 -0
- package/claude/skills/react-best-practices/rules/_template.md +28 -0
- package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/claude/skills/react-patterns/SKILL.md +688 -0
- package/claude/skills/registry-system/SKILL.md +331 -0
- package/claude/skills/scheduled-actions/SKILL.md +671 -0
- package/claude/skills/scope-enforcement/SKILL.md +542 -0
- package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
- package/claude/skills/server-actions/SKILL.md +493 -0
- package/claude/skills/service-layer/SKILL.md +587 -0
- package/claude/skills/session-management/SKILL.md +266 -0
- package/claude/skills/session-management/scripts/create-session.py +166 -0
- package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
- package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
- package/claude/skills/session-management/scripts/session-archive.sh +87 -0
- package/claude/skills/session-management/scripts/session-close.sh +133 -0
- package/claude/skills/session-management/scripts/session-init.sh +225 -0
- package/claude/skills/session-management/scripts/session-list.sh +163 -0
- package/claude/skills/session-management/scripts/split-plan.sh +116 -0
- package/claude/skills/shadcn-components/SKILL.md +586 -0
- package/claude/skills/shadcn-theming/SKILL.md +446 -0
- package/claude/skills/suspense-loading/SKILL.md +280 -0
- package/claude/skills/tailwind-theming/SKILL.md +507 -0
- package/claude/skills/tanstack-query/SKILL.md +608 -0
- package/claude/skills/test-coverage/SKILL.md +239 -0
- package/claude/skills/web-design-guidelines/SKILL.md +39 -0
- package/claude/skills/zod-validation/SKILL.md +537 -0
- package/claude/templates/blocks/progress.md +86 -0
- package/claude/templates/iteration/changes.md +61 -0
- package/claude/templates/iteration/progress.md +55 -0
- package/claude/templates/log.md +31 -0
- package/claude/templates/story/context.md +77 -0
- package/claude/templates/story/pendings.md +37 -0
- package/claude/templates/story/plan.md +299 -0
- package/claude/templates/story/requirements.md +109 -0
- package/claude/templates/story/scope.json +10 -0
- package/claude/templates/story/tests.md +91 -0
- package/claude/templates/task/progress.md +58 -0
- package/claude/templates/task/requirements.md +54 -0
- package/claude/workflows/README.md +154 -0
- package/claude/workflows/blocks.md +614 -0
- package/claude/workflows/story.md +1207 -0
- package/claude/workflows/task.md +927 -0
- package/claude/workflows/tweak.md +527 -0
- package/cursor/.gitkeep +0 -0
- package/package.json +35 -0
- package/scripts/postinstall.mjs +198 -0
- package/scripts/setup.mjs +282 -0
- package/scripts/sync.mjs +209 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rate-limiting
|
|
3
|
+
description: |
|
|
4
|
+
Rate limiting patterns for all API endpoints in this Next.js application.
|
|
5
|
+
Covers distributed rate limiting with Redis, tier selection, HOC patterns, and security best practices.
|
|
6
|
+
Use this skill when creating new API endpoints or reviewing rate limiting implementation.
|
|
7
|
+
allowed-tools: Read, Glob, Grep
|
|
8
|
+
version: 1.0.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Rate Limiting Skill
|
|
12
|
+
|
|
13
|
+
Rate limiting patterns and best practices for protecting API endpoints from abuse and DDoS attacks.
|
|
14
|
+
|
|
15
|
+
## Architecture Overview
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
core/lib/
|
|
19
|
+
├── api/
|
|
20
|
+
│ └── rate-limit.ts # withRateLimitTier HOC, checkDistributedRateLimit
|
|
21
|
+
└── rate-limit-redis.ts # Redis/Upstash distributed rate limiting
|
|
22
|
+
|
|
23
|
+
packages/core/templates/app/api/ # All template routes use rate limiting
|
|
24
|
+
plugins/*/api/ # Plugin API routes
|
|
25
|
+
themes/*/api/ # Theme API routes
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## When to Use This Skill
|
|
29
|
+
|
|
30
|
+
- **ALWAYS** when creating new API endpoints
|
|
31
|
+
- Reviewing existing endpoints for rate limiting coverage
|
|
32
|
+
- Debugging rate limit responses (429 errors)
|
|
33
|
+
- Configuring Redis for distributed rate limiting
|
|
34
|
+
- Choosing appropriate rate limit tiers
|
|
35
|
+
|
|
36
|
+
## MANDATORY RULE: All Endpoints Must Have Rate Limiting
|
|
37
|
+
|
|
38
|
+
**CRITICAL:** Every `route.ts` file that exports HTTP handlers (GET, POST, PUT, PATCH, DELETE)
|
|
39
|
+
MUST use the `withRateLimitTier` HOC wrapper.
|
|
40
|
+
|
|
41
|
+
**Only exceptions:**
|
|
42
|
+
- `/api/auth/**` - Better Auth handles its own rate limiting
|
|
43
|
+
- `/api/cron/**` - Protected by Vercel cron signatures
|
|
44
|
+
- `/api/webhooks/**` - Protected by webhook signatures
|
|
45
|
+
|
|
46
|
+
## Rate Limit Tiers
|
|
47
|
+
|
|
48
|
+
| Tier | Limit | Window | Use Case |
|
|
49
|
+
|------|-------|--------|----------|
|
|
50
|
+
| `auth` | 5 | 15 min | Authentication endpoints (login, register, reset password) |
|
|
51
|
+
| `read` | 200 | 1 min | GET requests, read-only operations |
|
|
52
|
+
| `write` | 50 | 1 min | POST, PUT, PATCH, DELETE operations |
|
|
53
|
+
| `api` | 100 | 1 min | General API (default tier) |
|
|
54
|
+
| `strict` | 10 | 1 hr | Sensitive operations (bulk delete, admin actions) |
|
|
55
|
+
|
|
56
|
+
## How to Apply Rate Limiting
|
|
57
|
+
|
|
58
|
+
### Basic Usage
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// route.ts
|
|
62
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
63
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit';
|
|
64
|
+
|
|
65
|
+
// For GET (read operations)
|
|
66
|
+
export const GET = withRateLimitTier(async (request: NextRequest) => {
|
|
67
|
+
// Your handler logic
|
|
68
|
+
return NextResponse.json({ data: [] });
|
|
69
|
+
}, 'read');
|
|
70
|
+
|
|
71
|
+
// For POST (write operations)
|
|
72
|
+
export const POST = withRateLimitTier(async (request: NextRequest) => {
|
|
73
|
+
// Your handler logic
|
|
74
|
+
return NextResponse.json({ created: true }, { status: 201 });
|
|
75
|
+
}, 'write');
|
|
76
|
+
|
|
77
|
+
// For PUT/PATCH (update operations)
|
|
78
|
+
export const PUT = withRateLimitTier(async (request: NextRequest) => {
|
|
79
|
+
// Your handler logic
|
|
80
|
+
return NextResponse.json({ updated: true });
|
|
81
|
+
}, 'write');
|
|
82
|
+
|
|
83
|
+
// For DELETE
|
|
84
|
+
export const DELETE = withRateLimitTier(async (request: NextRequest) => {
|
|
85
|
+
// Your handler logic
|
|
86
|
+
return NextResponse.json({ deleted: true });
|
|
87
|
+
}, 'write');
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### With Dynamic Routes
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// [id]/route.ts
|
|
94
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
95
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit';
|
|
96
|
+
|
|
97
|
+
// Handler receives route params as second argument
|
|
98
|
+
export const GET = withRateLimitTier(async (
|
|
99
|
+
request: NextRequest,
|
|
100
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
101
|
+
) => {
|
|
102
|
+
const { id } = await params;
|
|
103
|
+
return NextResponse.json({ id });
|
|
104
|
+
}, 'read');
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### For Sensitive Operations
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// Use 'strict' tier for operations like bulk delete, admin actions
|
|
111
|
+
export const DELETE = withRateLimitTier(async (request: NextRequest) => {
|
|
112
|
+
// Bulk delete or sensitive operation
|
|
113
|
+
return NextResponse.json({ deleted: true });
|
|
114
|
+
}, 'strict');
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Tier Selection Guidelines
|
|
118
|
+
|
|
119
|
+
### Use 'read' tier for:
|
|
120
|
+
- All GET requests
|
|
121
|
+
- Search endpoints
|
|
122
|
+
- List/pagination endpoints
|
|
123
|
+
- Public data endpoints
|
|
124
|
+
- Status/health check endpoints
|
|
125
|
+
|
|
126
|
+
### Use 'write' tier for:
|
|
127
|
+
- POST (create) operations
|
|
128
|
+
- PUT/PATCH (update) operations
|
|
129
|
+
- DELETE (remove) operations
|
|
130
|
+
- Form submissions
|
|
131
|
+
- File uploads
|
|
132
|
+
|
|
133
|
+
### Use 'strict' tier for:
|
|
134
|
+
- Bulk operations (delete all, import, export)
|
|
135
|
+
- Admin-only operations
|
|
136
|
+
- Superadmin endpoints
|
|
137
|
+
- Operations with significant server load
|
|
138
|
+
- AI/LLM endpoints with high compute cost
|
|
139
|
+
|
|
140
|
+
### Use 'auth' tier for:
|
|
141
|
+
- Login attempts
|
|
142
|
+
- Registration
|
|
143
|
+
- Password reset requests
|
|
144
|
+
- Email verification resends
|
|
145
|
+
- Any authentication-related endpoint
|
|
146
|
+
|
|
147
|
+
### Use 'api' tier for:
|
|
148
|
+
- General-purpose API endpoints
|
|
149
|
+
- When unsure (default fallback)
|
|
150
|
+
- Mixed read/write operations
|
|
151
|
+
|
|
152
|
+
## Response Headers
|
|
153
|
+
|
|
154
|
+
All rate-limited responses include these headers:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
X-RateLimit-Limit: 200 # Max requests in window
|
|
158
|
+
X-RateLimit-Remaining: 150 # Requests remaining
|
|
159
|
+
X-RateLimit-Reset: 1705432100 # Unix timestamp when window resets
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
When limit is exceeded (429 response):
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
Retry-After: 45 # Seconds until retry allowed
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 429 Response Format
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"success": false,
|
|
173
|
+
"error": "Rate limit exceeded",
|
|
174
|
+
"message": "Too many requests. Please try again later.",
|
|
175
|
+
"code": "RATE_LIMIT_EXCEEDED",
|
|
176
|
+
"meta": {
|
|
177
|
+
"limit": 200,
|
|
178
|
+
"remaining": 0,
|
|
179
|
+
"resetTime": "2024-01-16T12:00:00.000Z",
|
|
180
|
+
"retryAfter": 45
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Rate Limiting Strategy
|
|
186
|
+
|
|
187
|
+
The system uses a **per-tier global limit** strategy (NOT per-endpoint):
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
User makes requests:
|
|
191
|
+
GET /api/v1/products → counts against 'read' tier
|
|
192
|
+
GET /api/v1/orders → counts against 'read' tier
|
|
193
|
+
GET /api/v1/customers → counts against 'read' tier
|
|
194
|
+
|
|
195
|
+
All 3 requests count toward the SAME 200/min 'read' limit
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Why global per-tier?**
|
|
199
|
+
- Prevents attackers from hitting multiple endpoints to bypass limits
|
|
200
|
+
- Simpler mental model for users
|
|
201
|
+
- More effective DDoS protection
|
|
202
|
+
|
|
203
|
+
## Identifier Strategy
|
|
204
|
+
|
|
205
|
+
Rate limits are tracked by:
|
|
206
|
+
|
|
207
|
+
1. **API Key** (when present): `{tier}:apikey:{first16chars}`
|
|
208
|
+
2. **IP Address** (fallback): `{tier}:ip:{clientIp}`
|
|
209
|
+
|
|
210
|
+
This allows:
|
|
211
|
+
- Per-user limits for authenticated API requests
|
|
212
|
+
- IP-based limits for unauthenticated or session-based requests
|
|
213
|
+
|
|
214
|
+
## Redis Configuration (Production)
|
|
215
|
+
|
|
216
|
+
For distributed rate limiting across multiple instances, configure Redis:
|
|
217
|
+
|
|
218
|
+
```env
|
|
219
|
+
# Upstash Redis (recommended for Vercel)
|
|
220
|
+
UPSTASH_REDIS_REST_URL=https://xxx.upstash.io
|
|
221
|
+
UPSTASH_REDIS_REST_TOKEN=xxx
|
|
222
|
+
|
|
223
|
+
# Or standard Redis
|
|
224
|
+
REDIS_URL=redis://localhost:6379
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Without Redis, the system falls back to in-memory rate limiting (single-instance only).
|
|
228
|
+
|
|
229
|
+
## Disabling Rate Limiting (Development/Testing)
|
|
230
|
+
|
|
231
|
+
To disable rate limiting completely (useful for development, testing, or debugging):
|
|
232
|
+
|
|
233
|
+
```env
|
|
234
|
+
# .env.local or .env
|
|
235
|
+
DISABLE_RATE_LIMITING=true
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
When disabled:
|
|
239
|
+
- All rate limit checks are bypassed
|
|
240
|
+
- A warning is logged once: `[RateLimit] WARNING: Rate limiting is DISABLED...`
|
|
241
|
+
- Handlers execute without rate limit headers
|
|
242
|
+
|
|
243
|
+
**WARNING:** Never disable rate limiting in production environments!
|
|
244
|
+
|
|
245
|
+
**Use cases for disabling:**
|
|
246
|
+
- Local development when hitting limits during testing
|
|
247
|
+
- Running automated tests that make many requests
|
|
248
|
+
- Debugging API behavior without rate limit interference
|
|
249
|
+
- Load testing (measure true capacity without limits)
|
|
250
|
+
|
|
251
|
+
## Anti-Patterns
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// NEVER: Skip rate limiting on public endpoints
|
|
255
|
+
export const GET = async (request: NextRequest) => {
|
|
256
|
+
// Missing withRateLimitTier - VULNERABLE TO DDOS!
|
|
257
|
+
return NextResponse.json({ data: [] });
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// NEVER: Use wrong tier (read tier for write operations)
|
|
261
|
+
export const POST = withRateLimitTier(async (request: NextRequest) => {
|
|
262
|
+
await createEntity(data); // Write operation
|
|
263
|
+
return NextResponse.json({ created: true });
|
|
264
|
+
}, 'read'); // WRONG! Should be 'write'
|
|
265
|
+
|
|
266
|
+
// NEVER: Hardcode rate limits in handlers
|
|
267
|
+
export const GET = async (request: NextRequest) => {
|
|
268
|
+
const ip = request.headers.get('x-forwarded-for');
|
|
269
|
+
if (requestCount[ip] > 100) { // Custom implementation - DON'T
|
|
270
|
+
return NextResponse.json({ error: 'Too many' }, { status: 429 });
|
|
271
|
+
}
|
|
272
|
+
// ...
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// CORRECT: Always use the HOC
|
|
276
|
+
export const GET = withRateLimitTier(async (request: NextRequest) => {
|
|
277
|
+
return NextResponse.json({ data: [] });
|
|
278
|
+
}, 'read');
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Checklist for New Endpoints
|
|
282
|
+
|
|
283
|
+
Before finalizing any API endpoint:
|
|
284
|
+
|
|
285
|
+
- [ ] Handler is wrapped with `withRateLimitTier`
|
|
286
|
+
- [ ] Appropriate tier selected based on operation type
|
|
287
|
+
- [ ] GET operations use 'read' tier
|
|
288
|
+
- [ ] POST/PUT/PATCH/DELETE use 'write' tier
|
|
289
|
+
- [ ] Sensitive operations use 'strict' tier
|
|
290
|
+
- [ ] Auth operations use 'auth' tier
|
|
291
|
+
- [ ] Import statement added: `import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'`
|
|
292
|
+
|
|
293
|
+
## Verification Commands
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# Check if a route has rate limiting
|
|
297
|
+
grep -l "withRateLimitTier" packages/core/templates/app/api/**/route.ts
|
|
298
|
+
|
|
299
|
+
# Find routes WITHOUT rate limiting (potential vulnerabilities)
|
|
300
|
+
grep -L "withRateLimitTier" packages/core/templates/app/api/**/route.ts
|
|
301
|
+
|
|
302
|
+
# Count rate-limited vs unprotected routes
|
|
303
|
+
echo "Protected:"; grep -l "withRateLimitTier" packages/core/templates/app/api/**/route.ts | wc -l
|
|
304
|
+
echo "Unprotected:"; grep -L "withRateLimitTier" packages/core/templates/app/api/**/route.ts | wc -l
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Testing Rate Limits
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Cypress test example
|
|
311
|
+
describe('Rate Limiting', () => {
|
|
312
|
+
it('should return 429 after exceeding limit', () => {
|
|
313
|
+
// Make requests up to the limit
|
|
314
|
+
for (let i = 0; i < 210; i++) {
|
|
315
|
+
cy.request({
|
|
316
|
+
method: 'GET',
|
|
317
|
+
url: '/api/v1/products',
|
|
318
|
+
headers: { 'x-api-key': Cypress.env('API_KEY') },
|
|
319
|
+
failOnStatusCode: false
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Next request should be rate limited
|
|
324
|
+
cy.request({
|
|
325
|
+
method: 'GET',
|
|
326
|
+
url: '/api/v1/products',
|
|
327
|
+
headers: { 'x-api-key': Cypress.env('API_KEY') },
|
|
328
|
+
failOnStatusCode: false
|
|
329
|
+
}).then((response) => {
|
|
330
|
+
expect(response.status).to.eq(429);
|
|
331
|
+
expect(response.body.code).to.eq('RATE_LIMIT_EXCEEDED');
|
|
332
|
+
expect(response.headers).to.have.property('retry-after');
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Related Skills
|
|
339
|
+
|
|
340
|
+
- `better-auth` - Authentication patterns (auth tier integration)
|
|
341
|
+
- `nextjs-api-development` - API route development patterns
|
|
342
|
+
- `cypress-api` - API testing with rate limit considerations
|