@xlock/node
v0.1.1
Published
x-lock bot protection — invisible middleware for Express, Fastify, Koa, Next.js, and Hono
Maintainers
Readme
@xlock/node
Invisible bot protection middleware for Node.js. Drop-in replacement for reCAPTCHA, Turnstile, and hCaptcha — no visual challenges, no user friction.
Supports Express, Fastify, Koa, Next.js, and Hono.
Install
npm install @xlock/nodeQuick Start
Express
import { xlockMiddleware } from "@xlock/node/express";
app.use("/api/auth", xlockMiddleware({
siteKey: "sk_...",
flows: [
{
slug: "login",
name: "Login",
flowType: "auth",
match: [{ method: "POST", pathPattern: "/api/auth/login" }],
},
],
}));Fastify
import { xlockPlugin } from "@xlock/node/fastify";
fastify.register(xlockPlugin, {
siteKey: "sk_...",
routes: ["/api/auth/*"],
});Next.js
// middleware.ts
import { withXlock } from "@xlock/node/next";
export const middleware = withXlock({
siteKey: process.env.NEXT_PUBLIC_XLOCK_SITE_KEY!,
flows: [
{
slug: "checkout",
match: [{ method: "POST", pathPattern: "/api/checkout" }],
},
],
});
export const config = { matcher: ["/api/:path*"] };Hono
import { xlockMiddleware } from "@xlock/node/hono";
app.use("/api/auth/*", xlockMiddleware({ siteKey: "sk_..." }));Koa
import { xlockMiddleware } from "@xlock/node/koa";
router.post("/api/auth/login", xlockMiddleware({ siteKey: "sk_..." }), loginHandler);Direct Verification
import { verify } from "@xlock/node";
const result = await verify("https://api.x-lock.dev", "sk_...", token, {
method: "POST",
path: "/api/login",
flowHint: "login",
});
if (result.blocked) {
console.log("Blocked:", result.reason);
}Configuration
All middleware accepts these options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| siteKey | string | XLOCK_SITE_KEY env | Your x-lock site key |
| apiUrl | string | https://api.x-lock.dev | x-lock API endpoint |
| failOpen | boolean | true | Allow requests through on API errors |
| flows | Flow[] | [] | SDK-canonical flow declarations used to attach flowHint |
SDK-Canonical Flows
Declare flows in code, then register the module with the x-lock control plane:
import { defineFlowModule, registerFlowModule } from "@xlock/node";
await registerFlowModule({
apiKey: process.env.XLOCK_API_KEY!,
...defineFlowModule({
siteKey: process.env.XLOCK_SITE_KEY!,
appName: "web",
moduleVersion: "2026.04.14",
flows: [
{
slug: "login",
name: "Login",
flowType: "auth",
match: [{ method: "POST", pathPattern: "/api/login" }],
},
{
slug: "checkout",
name: "Checkout",
flowType: "payment",
match: [{ method: "POST", pathPattern: "/api/checkout" }],
},
],
}),
});Notes:
- Registration goes to the control plane at
https://x-lock.cloud/api/sdk/flow-modules/register. - Use a service account API key with the
flows:writescope. - Runtime enforcement still goes to
https://api.x-lock.dev. - The dashboard renders registered modules read-only; flow structure stays canonical in code.
How It Works
- Your frontend loads the x-lock script (invisible to users)
- x-lock runs proof-of-work + behavioral analysis in the background
- The script attaches a token to requests via the
x-lockheader - This middleware verifies the token server-side before your route handler runs
No CAPTCHAs. No clicking fire hydrants. No Google tracking.
Migrating from reCAPTCHA
- const { RecaptchaEnterpriseServiceClient } = require("@google-cloud/recaptcha-enterprise");
+ import { xlockMiddleware } from "@xlock/node/express";
- app.post("/login", async (req, res) => {
- const score = await recaptcha.assessToken(req.body.token);
- if (score < 0.5) return res.status(403).json({ error: "Bot detected" });
- // handle login
- });
+ app.post("/login", xlockMiddleware({ siteKey: "sk_..." }), (req, res) => {
+ // handle login — x-lock already verified the request
+ });License
MIT
