2026 · Next.js 16 · React 19 · Cloudflare Workers · TypeScript

Song Saver

High-performance, edge-rendered downloader landing on Feature-Sliced Design — secret-free client behind a strict CSP.

Role
Solo engineer — architecture, implementation
Year
2026
Stack
Next.js 16 · React 19 · Cloudflare Workers · TypeScript
Song Saver — cover

The problem

A downloader product needs a landing that is fast everywhere, ranks well, and never leaks API secrets to the browser. The classic setup — client-side calls to a third-party lookup API with a key in the bundle — fails all three at once.

The approach

The client stays completely secret-free: every Spotify lookup is proxied server-side through Cloudflare Workers, with KV caching so repeat requests never leave the edge, and binding-based rate limiting so abuse is throttled before it reaches origin. A strict Content Security Policy is enforced end-to-end — if a script isn't in the policy, it doesn't run.

Song Saver landing — edge-rendered downloader hero

Edge proxying: the client holds no secrets; KV absorbs repeat lookups; bindings rate-limit per identity.

The cache, tuned per endpoint

Caching at the edge is where the real engineering lives. Every endpoint got its own TTL decision, reasoned from the shape of the data:

  • Track / album / playlist / artist lookups — 24 h. Metadata is stable for days; there's nothing time-sensitive in the response.
  • Download URLs — 6 h. These are signed by the upstream and expire — the TTL deliberately sits below the observed link lifetime, so a cache hit can never hand you a dead URL.
  • Search — 1 h. Results turn over fast, and long-tail queries would burn the daily KV write budget for nothing.
  • Previews — 10 min, same signed-URL logic against Deezer's ~15-minute expiry.
  • Artist pagination, YouTube oEmbed — not cached at all. High cardinality or free-and-fast upstreams; caching them would waste writes the Spotify entries need.

And the golden rule wired through the wrapper: a cache miss must never break the user flow — every KV call swallows its own errors and falls through to the origin.

Architecture, testing, shipping

The front end is built on Feature-Sliced Design with a strictly-typed TypeScript codebase, SCSS Modules for scoped styling, and next-intl for 10 locales (with regional aliases resolved in middleware). Analytics runs through a typed event layer — a discriminated union of every event name and payload, so a renamed event is a compile error, not a lost metric. The whole thing deploys to Cloudflare via @opennextjs/cloudflare through three environments (dev → stage → prod), each with its own domain, secrets and bindings.

There's even a domain-migration runbook in the repo — the four files that hardcode the domain, the backup-domain warm-up plan, and a ~20-minute recovery target if a takedown ever forces a move. Boring documentation that you only appreciate the day you need it.

The outcome

An edge-rendered landing at songsaver.org where the heaviest asset is the truth: secrets never ship, lookups are cached at the edge, and the architecture doubles as a template for any future tool that talks to third-party APIs.