Repository navigation
url shortener design
This document describes the URL shortener design for shareable admin deep-links. The shortener is not built in v1.0.9, it is a ready-to-build spec for a future minor release.
Admin URLs can become long when multiple params are combined:
/monitor?tab=metrics&since=6h&filter.status=critical&selected=abc123&cursor=eyJpZCI6MTAwfQ
While fully functional, these URLs are awkward to paste in Slack or copy into incident tickets. A shortener would let users share /admin/s/abc12 instead.
- Lossless, the short URL must expand to the exact original URL, including all params
- Self-contained, the shortener state lives in the admin's LokiJS database, no external service
- Operator-only, short links are scoped to the same admin instance (single-user, not multi-tenant)
- Expiring, short links expire after 30 days by default (configurable)
- No external dependency, must work fully offline
interface AdminShortLink {
id: string // 6-char alphanumeric slug (e.g., 'abc123')
fullPath: string // original path + search string (e.g., '/monitor?tab=metrics&since=6h')
createdAt: number // Unix ms
expiresAt: number // Unix ms (default: createdAt + 30d)
accessCount: number // how many times the short link was clicked
}| Method | Path | Purpose |
|---|---|---|
POST |
/api/admin/shortlink |
Create a short link; body: { path: string }; returns { slug: string }
|
GET |
/api/admin/shortlink/:slug |
Resolve a slug; returns { fullPath: string } or 404 |
GET /s/:slug
The Next.js route /app/s/[slug]/route.ts resolves the slug and returns a 302 redirect to the full path. If the slug is expired or unknown, redirects to / with a toast param ?error=link_expired.
The <CopyLinkButton /> component in <PageHeader /> gains an optional shorten mode. When NSELF_ADMIN_SHORTLINKS=true (env var, default: false):
- On click,
CopyLinkButtonfiresPOST /api/admin/shortlinkwith the current full path - On success, copies the short URL (
http://localhost:3021/s/abc123) to clipboard - Toast reads: "Short link copied. Recipient must be signed in to view."
- On failure, falls back to copying the full URL (current behavior)
When NSELF_ADMIN_SHORTLINKS=false (default), CopyLinkButton copies the full URL as it does today. No API call is made.
import { randomBytes } from 'node:crypto'
function generateSlug(len = 6): string {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
const bytes = randomBytes(len)
return Array.from(bytes)
.map((b) => chars[b % chars.length])
.join('')
}Collision probability at 6 chars (36^6 = ~2.2B combinations) is negligible for a single-operator tool.
A Next.js route handler scheduled on setInterval (or via the cron plugin if available) runs every 24h to delete expired short links from LokiJS. Alternatively, expiry is checked lazily on each resolve (if expiresAt < Date.now(), respond 404 and delete).
- Short links resolve only within the same admin instance (localhost:3021). No cross-instance sharing.
- The operator is authenticated before any short link is created (existing session check).
- Short link slugs contain no embedded path info, cannot be enumerated for path discovery without a valid session to resolve them.
-
NSELF_ADMIN_SHORTLINKSisfalseby default. Opt-in only.
When building this feature:
- Add
AdminShortLinkcollection to LokiJS schema insrc/lib/database.ts - Add
POST /api/admin/shortlink/route.tsandGET /api/admin/shortlink/[slug]/route.ts - Add
src/app/s/[slug]/route.tsfor the redirect - Update
<CopyLinkButton />to checkNSELF_ADMIN_SHORTLINKSand call the API - Add
NSELF_ADMIN_SHORTLINKStoadmin/.env.exampleandF09-ENV-VAR-INVENTORY.md - Add expiry cleanup (lazy or scheduled)
- Update this doc to reflect actual implementation
-
src/components/ui/copy-link-button.tsx, the button that will trigger shortening -
src/lib/database.ts, LokiJS schema -
.github/wiki/url-state.md, 6-param URL vocabulary anduseUrlStatehook reference
Version: 1.0.0 | Updated: 2026-10-19 11:40 UTC | GitHub