06.01 — Vercel Edge stack#

package.json#

{
  "name": "tests-workers",
  "version": "1.0.0",
  "scripts": {
    "vercel-build": "echo 'Build skipped'"
  },
  "packageManager": "pnpm@11.2.2",
  "dependencies": {
    "@upstash/redis": "^1.36.2",
    "otplib": "^13.2.1"
  },
  "devDependencies": {
    "@types/node": "^25.2.0",
    "next": "^16.1.6",
    "@vercel/node": "^5.5.28",
    "typescript": "^5.9.3"
  },
  "license": "ISC"
}
LibRole
@upstash/redis (runtime)REST Redis client (no TCP). Edge-compatible.
otplib (runtime)RFC 6238 TOTP generation.
next (dev only)Types only (NextRequest). No Next.js app.
@vercel/node (dev only)Vercel types.
@types/node (dev only)Node 22+ types.

No runtime dependency beyond @upstash/redis + otplib. Bundle is microscopic → cold start < 100ms.

vercel.json#

{
  "version": 2,
  "buildCommand": "echo 'No build required'",
  "outputDirectory": ".",
  "framework": null
}
FieldValueEffect
version: 2Vercel v2 — 
buildCommand: "echo 'No build required'"No buildTypeScript is transpiled on the fly by the Vercel runtime
outputDirectory: "."Repo rootNo dist/ to produce
framework: nullNo framework detectedVercel doesn’t auto-config

The Edge runtime#

Each endpoint declares:

export const config = { runtime: "edge" };
AspectEdge FunctionsNode Serverless
Cold start< 50ms200–500ms
Memory~128 MBup to 3 GB
Node APILimited (no fs, child_process)Full Node
GeoCo-located with the userSingle region
fetch, crypto.getRandomValues, URLNativeNative
PricingCheaperMore expensive

For 3 endpoints that do only HTTP + Redis, Edge is the right pick.

Why next is in devDependencies#

import type { NextRequest } from "next/server";

tests-workers uses Next.js for one thing: the NextRequest type. No Next.js app. Vercel publishes those types because they’re compatible with Edge Functions.

At runtime the object is a standard Request, but typed as NextRequest for autocomplete on searchParams helpers and friends.

Why Upstash rather than a classic Redis#

Classic Redis (TCP)Upstash (REST)
Persistent connectionHTTP per request
Not Edge-compatibleEdge-compatible
Faster on multi-opsSimpler on single-op
Self-hosted or managedManaged (Cloudflare-style)

Edge has no TCP socket. Upstash exposes Redis over HTTP+REST.

API_SECRET#

const API_SECRET = process.env.API_SECRET;

Read at cold start. Stays in memory for the lifetime of the worker instance (which can serve N requests).

UPSTASH_REDIS_REST_*#

// lib/redis.ts
const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL,
  token: process.env.UPSTASH_REDIS_REST_TOKEN,
});
  1. UPSTASH_REDIS_REST_URL: the HTTPS URL of the Upstash Redis.
  2. UPSTASH_REDIS_REST_TOKEN: the Bearer token to authenticate.

vercel env add ... (see README).

Why only 3 endpoints#

EndpointWhy
/api/otp?_user=<u>Generates an OTP for the MFA login test
/api/otp-historyGives Ocarina the OTP Igoristan just generated
/api/corsicadex?id=NProvides data for the “Corsican Pokédex” page

No webhook, no polling, no DB other than Redis. The bare minimum.