Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/eve-agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ This is an example [Vercel Eve](https://eve.vercel.com/) agent protected by
simple agent that looks up orders, consults an API, receives inbound webhook
messages, and records every guard decision with Arcjet.

> [!WARNING]
> This is a local demo, not a production authentication pattern. The
> `/webhook` channel is unauthenticated so you can POST a message from curl or
> a test client. `from(conversationId)` resolves that id to whichever session
> currently owns it, so a hosted version must authenticate the caller before
> `guardInbound` — otherwise anyone who can guess a conversation id can post
> into it.

## Features

- [AI guardrails](https://docs.arcjet.com/ai-guardrails) with the
Expand Down
9 changes: 8 additions & 1 deletion examples/eve-agent/agent/arcjet.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { launchArcjet, tokenBucket } from "@arcjet/guard";

const key = process.env.ARCJET_KEY;
if (!key) {
throw new Error(
"ARCJET_KEY is required. Copy .env.local.example to .env.local and set it.",
);
}

// Create the Arcjet client once at module scope
export const arcjet = launchArcjet({
// Get your site key from https://console.arcjet.com
key: process.env.ARCJET_KEY ?? "",
key,
});

// Define rate limit rules at module scope
Expand Down
8 changes: 4 additions & 4 deletions examples/firebase-functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import * as logger from "firebase-functions/logger";

setGlobalOptions({ maxInstances: 10, secrets: ["ARCJET_KEY"] });

let arcjetKey = process.env.ARCJET_KEY;
const arcjetKey = process.env.ARCJET_KEY;
if (!arcjetKey) {
// In your app this should be a hard error! Here for the sake of the
// example we just use an intentionally invalid key.
arcjetKey = "";
throw new Error(
"ARCJET_KEY environment variable is required. Sign up for your Arcjet key at https://console.arcjet.com",
);
}

const arcjet = arcjetNode({
Expand Down
20 changes: 4 additions & 16 deletions examples/nextjs-bot-categories/lib/arcjet.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
import arcjetNextjs, { botCategories, detectBot } from "@arcjet/next";

// Get your site key from https://console.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
let key = process.env.ARCJET_KEY;
if (!key) {
// Normally we would throw an error here, but for the sake of the example
// application we will just log a warning and use a dummy key.

console.warn("Warning: ARCJET_KEY environment variable is not set.");
console.warn(
"Please set it to your Arcjet site key to enable bot protection.",
);
key = "arcjet_dummykey";
}

// Create a base Arcjet instance for use by each handler
export const arcjet = arcjetNextjs({
key,
// Get your site key from https://console.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
key: process.env.ARCJET_KEY!,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stated goal of this PR is to stop silently disabling enforcement when ARCJET_KEY is unset, but process.env.ARCJET_KEY! only silences the TypeScript check — at runtime undefined is still passed to arcjetNextjs, so behavior depends on how the SDK handles it. Consider matching the explicit-throw pattern used in examples/eve-agent/agent/arcjet.ts and examples/firebase-functions/src/index.ts so misconfiguration fails loudly here too.

rules: [
// Detect bots with fine-grained control over which are allowed. This shows
// three ways to build the allow list: by category, by individual bot, and
Expand Down
20 changes: 4 additions & 16 deletions examples/nextjs-bot-protection/lib/arcjet.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
import arcjetNextjs, { detectBot } from "@arcjet/next";

// Get your site key from https://console.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
let key = process.env.ARCJET_KEY;
if (!key) {
// Normally we would throw an error here, but for the sake of the example
// application we will just log a warning and use a dummy key.

console.warn("Warning: ARCJET_KEY environment variable is not set.");
console.warn(
"Please set it to your Arcjet site key to enable bot protection.",
);
key = "arcjet_dummykey";
}

// Create a base Arcjet instance for use by each handler
export const arcjet = arcjetNextjs({
key,
// Get your site key from https://console.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
key: process.env.ARCJET_KEY!,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as nextjs-bot-categories: process.env.ARCJET_KEY! is a type-level assertion only. If the env var is unset, undefined reaches the SDK. Consider the explicit-throw pattern used in the eve-agent and firebase-functions examples for consistency.

rules: [
detectBot({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
Expand Down
23 changes: 21 additions & 2 deletions examples/nextjs-form/app/submit/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
import { type NextRequest, NextResponse } from "next/server";
import { formSchema } from "@/app/schema";
import arcjet from "@/lib/arcjet";
import arcjet, { detectBot, shield, slidingWindow } from "@/lib/arcjet";

const aj = arcjet
// Shield protects your app from common attacks e.g. SQL injection
.withRule(shield({ mode: "LIVE" }))
// Block automated clients from submitting the form
.withRule(
detectBot({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
allow: [], // Block all bots. See https://arcjet.com/bot-list
}),
)
// Limit how often a single IP can submit the form
.withRule(
slidingWindow({
mode: "LIVE",
interval: "10m",
max: 5,
}),
);

export async function POST(req: NextRequest) {
const json = await req.json();
Expand All @@ -17,7 +36,7 @@ export async function POST(req: NextRequest) {

// The protect method returns a decision object that contains information
// about the request.
const decision = await arcjet.protect(req);
const decision = await aj.protect(req);

console.log("Arcjet decision: ", decision);

Expand Down
15 changes: 3 additions & 12 deletions examples/nextjs-server-action/app/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,11 @@ import arcjet, {
} from "@arcjet/next";
import { redirect } from "next/navigation";

// Get your site key from https://console.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
let key = process.env.ARCJET_KEY;
if (!key) {
// Normally we would throw an error here, but for the sake of the example
// application we will just log a warning and use a dummy key.
console.warn("Warning: ARCJET_KEY environment variable is not set.");
key = "arcjet_dummykey";
}

const aj = arcjet({
// Get your site key from https://console.arcjet.com
key,
// and set it as an environment variable rather than hard coding.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same note as the other Next.js examples — process.env.ARCJET_KEY! doesn't guarantee the value is set at runtime. Consider a runtime check with a clear error message so misconfigured examples surface the problem immediately.

// See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
key: process.env.ARCJET_KEY!,
rules: [
// Shield protects your app from common attacks e.g. SQL injection
shield({ mode: "LIVE" }),
Expand Down
10 changes: 4 additions & 6 deletions examples/nuxt/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ RUN npm ci

COPY . .

# Note: Nuxt requires `ARCJET_KEY` to be set during build. Here we set it to a
# dummy value if not set to allow builds to succeed.
ENV ARCJET_KEY=${ARCJET_KEY:-ajkey_dummy}

# NOTE: Have to run postinstall as it handles automatic import resolution
RUN npm run postinstall && npm run build
# Nuxt requires `ARCJET_KEY` at build time. Keep the placeholder on this RUN
# only — do not persist it as a runtime ENV or the image ships a dummy key.
ARG ARCJET_KEY=ajkey_yourkey

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default ARG ARCJET_KEY=ajkey_yourkey still lets a build succeed with an obviously-fake key when the user forgets --build-arg ARCJET_KEY=.... That's the same failure mode this PR removes elsewhere. Would it be preferable to drop the default and let the build fail fast, or at minimum document that the placeholder means bot/rate-limit rules will be inert until the image is rebuilt with a real key?

RUN ARCJET_KEY=$ARCJET_KEY npm run postinstall && npm run build

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: file is missing a trailing newline (the diff shows \ No newline at end of file). Worth adding while touching this file.


CMD ["npm", "run", "start"]
Loading