New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

@device-router/middleware-fastify

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@device-router/middleware-fastify

Fastify plugin for [DeviceRouter](https://github.com/SimplyLiz/DeviceRouter). Adds device classification and rendering hints to every request.

Source
npmnpm
Version
0.3.0
Version published
Maintainers
1
Created
Source

@device-router/middleware-fastify

Fastify plugin for DeviceRouter. Adds device classification and rendering hints to every request.

Installation

pnpm add @device-router/middleware-fastify @device-router/storage @fastify/cookie

For automatic probe injection:

pnpm add @device-router/probe

Quick start

import Fastify from 'fastify';
import cookie from '@fastify/cookie';
import { createDeviceRouter } from '@device-router/middleware-fastify';
import { MemoryStorageAdapter } from '@device-router/storage';

const app = Fastify();
const { plugin, probeEndpoint } = createDeviceRouter({
  storage: new MemoryStorageAdapter(),
});

await app.register(cookie);
await app.register(plugin);

app.post('/device-router/probe', probeEndpoint);

app.get('/', (req, reply) => {
  const profile = req.deviceProfile;

  if (profile?.hints.preferServerRendering) {
    return reply.send(renderSSR());
  }
  if (profile?.hints.deferHeavyComponents) {
    return reply.send(renderLite());
  }
  reply.send(renderFull());
});

app.listen({ port: 3000 });

How it works

  • Probe endpoint receives device signals from the browser and stores a classified profile
  • Plugin registers a preHandler hook that reads the session cookie, loads the profile from storage, and attaches it to req.deviceProfile
  • Your route handlers use req.deviceProfile.hints and req.deviceProfile.tiers to adapt responses

Probe auto-injection

Automatically inject the probe <script> into HTML responses:

const { plugin, probeEndpoint, injectionHook } = createDeviceRouter({
  storage: new MemoryStorageAdapter(),
  injectProbe: true,
  probeNonce: 'my-csp-nonce', // optional
});

When injectProbe is enabled, the plugin registers an onSend hook that injects the script before </head>.

Streaming responses: The onSend hook receives the serialized payload as a string. If you stream responses via reply.raw, the hook is bypassed and injection is skipped. Add the probe <script> tag to your HTML shell manually instead.

Custom thresholds

const { plugin, probeEndpoint } = createDeviceRouter({
  storage,
  thresholds: {
    cpu: { lowUpperBound: 4, midUpperBound: 8 },
    memory: { midUpperBound: 8 },
  },
});

Options

OptionTypeDefaultDescription
storageStorageAdapter(required)Storage backend for profiles
cookieNamestring'dr_session'Session cookie name
cookiePathstring'/'Cookie path
cookieSecurebooleanfalseSet Secure flag on the session cookie
ttlnumber86400 (24h)Profile TTL in seconds
rejectBotsbooleantrueReject bot/crawler probe submissions
thresholdsTierThresholdsBuilt-in defaultsCustom tier thresholds (validated at startup)
injectProbebooleanfalseAuto-inject probe into HTML
probePathstring—Custom probe endpoint path
probeNoncestring | ((req: FastifyRequest) => string)—CSP nonce for injected script
fallbackProfileFallbackProfile—Fallback profile for first requests
classifyFromHeadersbooleanfalseClassify from UA/Client Hints

Exports

  • createDeviceRouter(options) — All-in-one setup returning { plugin, probeEndpoint, injectionHook? }
  • createMiddleware(options) — Standalone preHandler hook
  • createProbeEndpoint(options) — Standalone probe endpoint handler
  • createInjectionHook(options) — Standalone onSend injection hook

Compatibility

  • Fastify 5.x
  • @fastify/cookie 11.x
  • Node.js >= 20

License

MIT

FAQs

Package last updated on 23 Feb 2026

Related posts