Docs / Framework Adapters

Framework Adapters

Arcis has built-in adapters for the most popular web frameworks. The core functions are framework-agnostic, so Arcis also works with any framework that isn't listed here.

Install in your backend project, not the frontend. All the snippets below are server-side. The .env with ARCIS_KEY goes next to the server entry point. Do not prefix the key with NEXT_PUBLIC_, VITE_, or REACT_APP_. Those bundle into client JS.

Express (Node.js)

The primary Node.js adapter. Works with Express 4 and 5.

import express from 'express';
import { arcis } from '@arcis/node';
import 'dotenv/config';

const app = express();
app.use(express.json());
app.use(arcis({ block: true }));

NestJS (Node.js)

First-party adapter at @arcis/node/nestjs. @nestjs/common is type-only, so non-NestJS users pay nothing.

// app.module.ts
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { ArcisModule, ArcisMiddleware } from '@arcis/node/nestjs';

@Module({ imports: [ArcisModule.forRoot({ block: true })] })
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(ArcisMiddleware).forRoutes('*');
  }
}

SvelteKit (Node.js)

First-party adapter at @arcis/node/sveltekit. Returns a SvelteKit Handle for src/hooks.server.ts.

// src/hooks.server.ts
import { arcisHandle } from '@arcis/node/sveltekit';

export const handle = arcisHandle({
  rateLimit: { max: 100 },
  bot: true,
});

// Or compose with other handles via SvelteKit's `sequence` helper:
// import { sequence } from '@sveltejs/kit/hooks';
// export const handle = sequence(arcisHandle(), authHandle);

Astro (Node.js)

First-party adapter at @arcis/node/astro. Returns an Astro MiddlewareHandler for src/middleware.ts.

// src/middleware.ts
import { onRequest as arcisOnRequest } from '@arcis/node/astro';

export const onRequest = arcisOnRequest({
  rateLimit: { max: 100 },
  bot: true,
});

Nuxt (Node.js, h3)

First-party adapter at @arcis/node/nuxt. Wrap with defineEventHandler in a Nitro server middleware.

// server/middleware/arcis.ts
import { defineEventHandler } from 'h3';
import { arcisHandler } from '@arcis/node/nuxt';

export default defineEventHandler(arcisHandler({
  rateLimit: { max: 100 },
}));

Fastify (Node.js)

First-party async plugin at @arcis/node/fastify. Registers onRequest (rate-limit + bot) and onSend (security headers).

import Fastify from 'fastify';
import { arcisFastify } from '@arcis/node/fastify';

const app = Fastify();
await app.register(arcisFastify, { rateLimit: { max: 100 }, bot: true });

Koa (Node.js)

First-party adapter at @arcis/node/koa. (ctx, next) middleware shape: rate-limit + bot before next(); security headers after.

import Koa from 'koa';
import { arcisKoa } from '@arcis/node/koa';

const app = new Koa();
app.use(arcisKoa({ rateLimit: { max: 100 }, bot: true }));

Hono (Node.js, Workers, Deno, Bun)

First-party adapter at @arcis/node/hono. Web Fetch native, type-only hono import — runs on any runtime Hono targets (Cloudflare Workers, Deno Deploy, Bun, AWS Lambda, Node).

import { Hono } from 'hono';
import { arcisHono } from '@arcis/node/hono';

const app = new Hono();
app.use('*', arcisHono({ rateLimit: { max: 100 }, bot: true }));
app.get('/', (c) => c.text('Hello'));

Next.js (Node.js)

First-party adapter at @arcis/node/nextjs. arcisMiddleware is Edge Middleware (Web Fetch native, returns Response | undefined). arcisProtect wraps an App Router route handler with a security-headers post-pass.

// middleware.ts (Edge runtime)
import { arcisMiddleware } from '@arcis/node/nextjs';

export const middleware = arcisMiddleware({
  rateLimit: { max: 100 },
  bot: true,
});

Bun (Node.js)

First-party adapter at @arcis/node/bun. arcisBun wraps a Bun.serve fetch handler. (For Bun + Hono, use @arcis/node/hono above — it runs on Bun unchanged.)

import { arcisBun } from '@arcis/node/bun';

Bun.serve({
  fetch: arcisBun({ rateLimit: { max: 100 }, bot: true }, async (req) => {
    return new Response('Hello');
  }),
});

FastAPI (Python)

from fastapi import FastAPI
from arcis import ArcisMiddleware
from dotenv import load_dotenv

load_dotenv()
app = FastAPI()
app.add_middleware(ArcisMiddleware, block=True)

For custom config:

from arcis import ArcisMiddleware, Config

app.add_middleware(
    ArcisMiddleware,
    config=Config(
        sanitize_xss=True,
        rate_limit_max=60,
    ),
)

Flask (Python)

from flask import Flask
from arcis import Arcis
from dotenv import load_dotenv

load_dotenv()
app = Flask(__name__)
Arcis(app, block=True)

Django (Python)

Add to MIDDLEWARE in settings.py:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'arcis.django.ArcisMiddleware',   # add this line
    'django.middleware.common.CommonMiddleware',
    # ... rest of your middleware
]

Litestar (Python)

First-party adapter at arcis.litestar.ArcisMiddleware. Pure-ASGI middleware, type-only litestar import — composes with Litestar via DefineMiddleware and with any other ASGI host (Starlette, Quart, Hypercorn) via direct instantiation.

from litestar import Litestar
from litestar.middleware.base import DefineMiddleware
from arcis.litestar import ArcisMiddleware

app = Litestar(
    middleware=[DefineMiddleware(ArcisMiddleware, block=True)],
)

Gin (Go)

package main

import (
    "github.com/gin-gonic/gin"
    arcisgin "github.com/GagancM/arcis/gin"
)

func main() {
    r := gin.Default()
    r.Use(arcisgin.Middleware(arcis.Config{Block: true}))
    r.Run()
}

Echo (Go)

package main

import (
    "github.com/labstack/echo/v4"
    arcisecho "github.com/GagancM/arcis/echo"
)

func main() {
    e := echo.New()
    e.Use(arcisecho.Middleware())
    e.Start(":8080")
}

chi (Go)

First-party adapter at github.com/GagancM/arcis/chi. Granular helpers (Headers / Sanitizer / Validate / Csrf / SecureCookies / Cors / ErrorHandler) plus the bundle middleware. Stdlib-only at runtime — composes with any router accepting func(http.Handler) http.Handler.

package main

import (
    "net/http"
    "github.com/go-chi/chi/v5"
    arcischi "github.com/GagancM/arcis/chi"
)

func main() {
    r := chi.NewRouter()
    r.Use(arcischi.MiddlewareWithConfig(arcischi.Config{Block: true}))
    http.ListenAndServe(":8080", r)
}

Fiber (Go)

First-party adapter at github.com/GagancM/arcis/fiber. Bundle middleware + standalone RateLimit helpers + WithTelemetry option, mirroring the gin/echo/chi shape.

package main

import (
    "github.com/gofiber/fiber/v2"
    arcisfiber "github.com/GagancM/arcis/fiber"
)

func main() {
    app := fiber.New()
    cfg := arcisfiber.DefaultConfig()
    cfg.Block = true
    app.Use(arcisfiber.MiddlewareWithConfig(cfg))
    app.Listen(":8080")
}

net/http (Go)

For users without a third-party router, the nethttp subpackage exposes the same middleware shape as a func(http.Handler) http.Handler decorator. Pure stdlib — no chi or fiber dep needed.

package main

import (
    "net/http"
    archttp "github.com/GagancM/arcis/nethttp"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("ok"))
    })

    cfg := archttp.DefaultConfig()
    cfg.Block = true
    var h http.Handler = mux
    h = archttp.MiddlewareWithConfig(cfg)(h)
    http.ListenAndServe(":8080", h)
}