| name | arcjet |
| description | Expert guidance for Arcjet, the developer-first security platform that provides rate limiting, bot protection, email validation, and attack detection as a code-first SDK. Helps developers add security layers to Next.js, Node.js, and other JavaScript/TypeScript applications without managing infrastructure. |
| license | Apache-2.0 |
| compatibility | No special requirements |
| metadata | {"author":"terminal-skills","version":"1.0.0","category":"development","tags":["rate-limiting","bot-protection","security","waf","email-validation"]} |
Arcjet — Application Security Layer
Overview
Arcjet, the developer-first security platform that provides rate limiting, bot protection, email validation, and attack detection as a code-first SDK. Helps developers add security layers to Next.js, Node.js, and other JavaScript/TypeScript applications without managing infrastructure.
Instructions
Rate Limiting
Protect endpoints from abuse with flexible rate limiting:
import arcjet, { tokenBucket, slidingWindow, fixedWindow } from "@arcjet/next";
export const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["ip.src"],
rules: [
tokenBucket({
mode: "LIVE",
refillRate: 10,
interval: 60,
capacity: 20,
}),
],
});
export const loginLimiter = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["ip.src"],
rules: [
slidingWindow({
mode: "LIVE",
max: 5,
interval: "15m",
}),
],
});
export const apiLimiter = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["http.request.headers[\"x-api-key\"]"],
rules: [
fixedWindow({
mode: "LIVE",
max: 100,
interval: "1h",
}),
fixedWindow({
mode: "LIVE",
max: 1000,
interval: "1d",
}),
],
});
Bot Protection
Detect and block automated traffic:
import arcjet, { detectBot, shield } from "@arcjet/next";
import { NextRequest, NextResponse } from "next/server";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
shield({ mode: "LIVE" }),
detectBot({
mode: "LIVE",
allow: [
"CATEGORY:SEARCH_ENGINE",
"CATEGORY:MONITOR",
],
}),
],
});
export async function POST(request: NextRequest) {
const decision = await aj.protect(request);
if (decision.isDenied()) {
if (decision.reason.isBot()) {
return NextResponse.json(
{ : },
{ : }
);
}
(decision..()) {
.(
{ : },
{ : , : { : } }
);
}
(decision..()) {
.(
{ : },
{ : }
);
}
}
body = request.();
user = (body);
.({ user }, { : });
}
Email Validation
Validate email addresses before accepting them:
import arcjet, { validateEmail } from "@arcjet/next";
import { NextRequest, NextResponse } from "next/server";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
validateEmail({
mode: "LIVE",
block: [
"DISPOSABLE",
"INVALID",
"NO_MX_RECORDS",
],
}),
],
});
export async function POST(request: NextRequest) {
const { email } = await request.json();
const decision = await aj.protect(request, { email });
if (decision.isDenied()) {
const reason = decision.reason;
if (reason.isEmail()) {
(reason..()) {
.(
{ : },
{ : }
);
}
(reason..()) {
.(
{ : },
{ : }
);
}
}
}
(email);
.({ : });
}
Next.js Middleware Integration
Apply security rules globally via middleware:
import arcjet, { detectBot, shield, tokenBucket } from "@arcjet/next";
import { NextRequest, NextResponse } from "next/server";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["ip.src"],
rules: [
shield({ mode: "LIVE" }),
detectBot({
mode: "LIVE",
allow: ["CATEGORY:SEARCH_ENGINE", "CATEGORY:MONITOR", "CATEGORY:PREVIEW"],
}),
tokenBucket({
mode: "LIVE",
refillRate: 60,
interval: 60,
capacity: 120,
}),
],
});
export async function middleware(request: NextRequest) {
const decision = await aj.protect(request);
console.log(`[Arcjet] | | IP: `);
(decision.()) {
(decision..()) {
.({ : }, { : });
}
.({ : }, { : });
}
response = .();
response..(, decision.);
response;
}
config = {
: [
,
,
],
};
Node.js / Express Integration
Use Arcjet with Express or any Node.js framework:
import arcjet, { tokenBucket, detectBot, shield } from "@arcjet/node";
import { Request, Response, NextFunction } from "express";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["ip.src"],
rules: [
shield({ mode: "LIVE" }),
detectBot({ mode: "LIVE", allow: ["CATEGORY:SEARCH_ENGINE"] }),
tokenBucket({ mode: "LIVE", refillRate: 30, interval: 60, capacity: 60 }),
],
});
export async function arcjetMiddleware(req: Request, res: Response, next: NextFunction) {
const decision = await aj.protect(req);
if (decision.isDenied()) {
const status = decision..() ? : ;
res.(status).({
: decision..() ? : ,
});
}
();
}
app.(, arcjetMiddleware);
Installation
npm install @arcjet/next
npm install @arcjet/node
Examples
Example 1: Setting up Arcjet with a custom configuration
User request:
I just installed Arcjet. Help me configure it for my TypeScript + React workflow with my preferred keybindings.
The agent creates the configuration file with TypeScript-aware settings, configures relevant plugins/extensions for React development, sets up keyboard shortcuts matching the user's preferences, and verifies the setup works correctly.
Example 2: Extending Arcjet with custom functionality
User request:
I want to add a custom bot protection to Arcjet. How do I build one?
The agent scaffolds the extension/plugin project, implements the core functionality following Arcjet's API patterns, adds configuration options, and provides testing instructions to verify it works end-to-end.
Guidelines
- Start with DRY_RUN — Use
mode: "DRY_RUN" first to monitor traffic patterns before enforcing rules
- Layer multiple rules — Combine shield + bot detection + rate limiting; each catches different attack types
- Rate limit by the right characteristic — Use IP for public endpoints, API key for authenticated ones, user ID for per-user limits
- Allow legitimate bots — Search engines, uptime monitors, and link previews are not attacks; whitelist them
- Validate emails early — Check email validity at signup, not after sending a verification email (saves deliverability)
- Middleware for global protection — Apply shield and bot detection in middleware; add specific rate limits per route
- Monitor before enforcing — Review Arcjet dashboard logs to understand traffic patterns and tune thresholds
- Graceful degradation — If Arcjet is unavailable, your app should still work; wrap in try/catch with a permissive fallback