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

@device-router/middleware-hono

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-hono

Hono middleware for DeviceRouter — device classification and rendering hints, edge-compatible

latest
Source
npmnpm
Version
1.0.1
Version published
Maintainers
1
Created
Source

@device-router/middleware-hono

Hono middleware for DeviceRouter. Adds device classification and rendering hints to every request. Edge-compatible.

Installation

pnpm add @device-router/middleware-hono @device-router/storage

For automatic probe injection:

pnpm add @device-router/probe

Quick start

import { Hono } from 'hono';
import { createDeviceRouter } from '@device-router/middleware-hono';
import { MemoryStorageAdapter } from '@device-router/storage';

const app = new Hono();
const { middleware, probeEndpoint } = createDeviceRouter({
  storage: new MemoryStorageAdapter(),
});

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

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

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

export default app;

How it works

  • Probe endpoint receives device signals from the browser and stores a classified profile
  • Middleware reads the session cookie, loads the profile from storage, and sets it on the Hono context via c.set('deviceProfile', profile)
  • Your route handlers use c.get('deviceProfile') to access tiers and hints

Probe auto-injection

Automatically inject the probe <script> into HTML responses:

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

app.use('*', injectionMiddleware);

Streaming responses: Injection reads the entire response body as text. If your handler returns a ReadableStream, the response is buffered into memory before injection. For streaming HTML, add the probe <script> tag to your HTML shell manually instead.

Custom thresholds

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

Options

OptionTypeDefaultDescription
storageStorageAdapter(required)Storage backend for profiles
cookieNamestring'device-router-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
probePathstringCustom probe endpoint path
probeNoncestring | ((c: Context) => string)CSP nonce for injected script
fallbackProfileFallbackProfileFallback profile for first requests
classifyFromHeadersbooleanfalseClassify from UA/Client Hints
onEventOnEventCallbackObservability callback for logging/metrics

Observability

Pass an onEvent callback to receive events for classification, storage, bot rejection, and errors:

const { middleware, probeEndpoint } = createDeviceRouter({
  storage,
  onEvent: (event) => {
    console.log(`[device-router] ${event.type}`, event);
  },
});

See the Observability guide for details.

Type-safe context

Use the DeviceRouterEnv type for full type safety:

import type { DeviceRouterEnv } from '@device-router/middleware-hono';

const app = new Hono<DeviceRouterEnv>();
// c.get('deviceProfile') is now typed

Standalone usage

Use the individual pieces when you need fine-grained control over each component:

import {
  createMiddleware,
  createProbeEndpoint,
  createInjectionMiddleware,
  loadProbeScript,
} from '@device-router/middleware-hono';

// Use only what you need
const middleware = createMiddleware({ storage, thresholds });
const endpoint = createProbeEndpoint({ storage, ttl: 3600 });
const injection = createInjectionMiddleware({
  probeScript: loadProbeScript(),
});

app.use('*', injection);
app.use('*', middleware);
app.post('/device-router/probe', endpoint);

loadProbeScript() reads the @device-router/probe bundle and optionally rewrites the endpoint URL via { probePath }. Thresholds passed to createMiddleware() are validated at creation time.

Exports

  • createDeviceRouter(options) — All-in-one setup returning { middleware, probeEndpoint, injectionMiddleware? }
  • createMiddleware(options) — Standalone middleware (validates thresholds)
  • createProbeEndpoint(options) — Standalone probe endpoint handler
  • createInjectionMiddleware(options) — Standalone injection middleware
  • loadProbeScript(options?) — Load the minified probe script for use with createInjectionMiddleware()
  • DeviceRouterEnv — Hono env type for typed context access

Compatibility

  • Hono 4.x
  • Node.js >= 20, edge runtimes

License

MIT

Keywords

device-router

FAQs

Package last updated on 04 Mar 2026

Related posts