Skip to content

Architecture

shrtnr is a single Cloudflare Worker with its entry point at src/index.tsx. It dispatches by request host and path to the redirect, admin UI, public API, or MCP handlers.

Directory layout

shrtnr/
├── src/                    Worker source
│   ├── index.tsx           Entry point: request dispatch
│   ├── redirect.ts         Short-link redirect logic
│   ├── redirect-rules.ts   Dynamic redirect rules (_redirects migration)
│   ├── slugs.ts            Slug generation and validation
│   ├── access.ts / auth.ts Cloudflare Access JWT verification and auth
│   ├── analytics-fill.ts   Click analytics backfill
│   ├── country.ts / ua.ts / referrer.ts / fingerprint.ts  Click dimension parsing
│   ├── qr.ts               QR code generation
│   ├── title-fetch.ts      Fetch the target URL title
│   ├── normalize-url.ts    URL normalization
│   ├── api/                Public API (Hono + zod-openapi)
│   ├── db/                 D1 repository layer (repository pattern)
│   ├── services/           Business logic layer
│   ├── kv/                 KV slug cache
│   ├── mcp/                MCP server and page
│   ├── pages/              Admin UI pages (JSX/SSR)
│   ├── components/         Admin UI shared components
│   ├── i18n/               Localization (en / id / sv / zh)
│   └── __tests__/          Vitest tests
├── migrations/             D1 database migrations
├── public/                 Static assets (icons, logos, manifest)
├── scripts/                Build and release scripts
├── sdk/                    Official SDKs (typescript / python)
├── browser-extensions/     Chrome / Firefox extensions
├── docs/                   This documentation site (VitePress)
└── wrangler.jsonc          Cloudflare Worker configuration

Layered design

The app roughly splits into three layers.

API / page layer

  • src/api/: the public Bearer-token API, built on Hono with @hono/zod-openapi. router.ts mounts the links and slugs sub-apps and exposes /openapi.json and /docs.
  • src/pages/: server-rendered admin UI pages (dashboard, links, link detail, API keys, settings, redirects, custom pages).
  • src/components/: admin UI shared components (KPI cards, big charts, sparklines, range picker, etc.).

Service layer (src/services/)

Encapsulates business logic independent of the transport layer:

ModuleResponsibility
link-management.tsLink create, update, enable/disable, delete
admin-management.tsAdmin-side operations
analytics.tsClick analytics aggregation
trends.tsTrend and delta computation
result.tsUnified result/error wrapper

Data layer (src/db/)

Repository wrappers over the D1 database:

RepositoryTable
link-repository.tsLinks
slug-repository.tsSlugs
click-repository.tsClick events
api-key-repository.tsAPI keys
setting-repository.tsPer-user settings
page-repository.tsCustom pages
filters.tsAnalytics filter subqueries (bot / self-referrer / time range)

The KV layer (src/kv/slug-cache.ts) provides a high-speed cache for slug-to-link lookups.

MCP (src/mcp/)

  • server.ts: registers all MCP tools (links, slugs, QR, analytics) and is the authoritative source for the tool list.
  • page.ts: MCP-related page.

MCP sessions are hosted by the Durable Object MCP_OBJECT (class ShrtnrMCP) declared in wrangler.jsonc.

Internationalization (src/i18n/)

All user-facing strings in admin pages/components go through t(), with translations in en.ts, id.ts, sv.ts, and zh.ts. English is the source of truth and the fallback.

Released under the Apache License 2.0. Upstream built by Oddbit.