Magic Word

A minimal, refined link shortener where users enter "magic words" instead of cryptic codes.

Live: magicword.val.run


Vision

Traditional link shorteners produce URLs like bit.ly/3xK7m2Q — functional but forgettable. Magic Word reimagines this as a human-first experience:

Traditional:  brand.com/promo?code=xK7m2&utm_source=twitter&utm_medium=...
Magic Word:   "The magic word is SUMMER" → redirects to your campaign

The interface is radically minimal: a single text input asking "What is the magic word?" Nothing else. Enter a word, get redirected. That's it.

Use Cases

  • Marketing campaigns: "Use magic word FREEBIE for 20% off"
  • Event access: "The magic word for the afterparty is VELVET"
  • Memorable branded links: Share "crystal-beacon" instead of a 50-character URL
  • Easter eggs: Hide content behind discoverable words

Features

Single Input, Multiple Modes

The same input field handles everything:

InputAction
summerLook up magic word → redirect
pleaseOpen create/management UI
a]Verify admin key → edit/delete UI

Tiered Pricing Model

TierFormatExamplePrice
FreeTwo-word compoundcrystal-beacon, amber-grove£0
PremiumSingle dictionary wordsummer, free, win£12/year

Free-tier compounds are surprisingly brandable ("thundercat", "moonpie") while keeping the namespace virtually unlimited (~576 combinations from current word lists).

Anti-Scraping Protection

Every lookup requires a proof-of-work computation, preventing enumeration attacks:

  1. Page load → client receives a PoW challenge (nonce + difficulty)
  2. User enters word → client computes SHA-256(nonce:word:counter) until hash has N leading zeros
  3. Submit → server verifies proof is valid AND challenge hasn't been used before
  4. One-time use → challenge marked as consumed, preventing replay

Why this works:

  • Scraping 10,000 words requires 10,000× the computation (~500ms each = 83 minutes)
  • Legitimate users experience a brief "working..." delay (acceptable UX)
  • No CAPTCHAs, no user accounts, no friction
  • Difficulty is tunable (currently 4 leading zeros ≈ 200-500ms)

Admin Keys

Each magic word gets a UUID admin key on creation. This key:

  • Is shown exactly once (on creation)
  • Allows editing the destination URL
  • Allows deleting the word
  • Can be shared with teammates
  • Requires no account or authentication system

Implementation

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Val.town Edge                         │
│  ┌─────────────────────────────────────────────────┐    │
│  │  main.tsx (HTTP handler)                        │    │
│  │  - Serves HTML UI with embedded challenge       │    │
│  │  - API routes for CRUD + PoW verification       │    │
│  │  - Server-side React rendering                  │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Val.town SQLite                                │    │
│  │  - magic_words table (word, url, admin_key_hash)│    │
│  │  - pow_challenges table (one-time use tokens)   │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘
                          │
            Client-side PoW computation
            (SHA-256 in browser, ~200-500ms)

Database Schema

CREATE TABLE magic_words ( id INTEGER PRIMARY KEY AUTOINCREMENT, word TEXT UNIQUE NOT NULL, -- "summer" or "crystal-beacon" url TEXT NOT NULL, -- destination URL admin_key_hash TEXT NOT NULL, -- SHA-256 hash of admin UUID tier TEXT NOT NULL, -- "free" or "premium" created_at DATETIME DEFAULT CURRENT_TIMESTAMP, expires_at DATETIME, -- NULL for free tier redirect_count INTEGER DEFAULT 0 -- analytics ); CREATE TABLE pow_challenges ( id TEXT PRIMARY KEY, -- UUID nonce TEXT NOT NULL, -- random string for PoW created_at DATETIME DEFAULT CURRENT_TIMESTAMP, used BOOLEAN DEFAULT FALSE -- one-time use enforcement );

API Endpoints

MethodPathPurpose
GET/Serve HTML UI with fresh PoW challenge
GET/api/challengeIssue new PoW challenge
POST/api/lookupLook up word (requires PoW proof)
POST/api/createCreate new magic word
POST/api/verify-adminVerify admin key, return word details
PUT/api/updateUpdate URL (requires admin key)
DELETE/api/deleteDelete word (requires admin key)

Tech Stack

  • Runtime: Val.town (Deno-based serverless)
  • Database: Val.town SQLite (Turso/libSQL)
  • Frontend: Server-rendered React, vanilla JS for interactions
  • Fonts: Crimson Pro (serif) + JetBrains Mono (monospace)
  • PoW: SHA-256 via Web Crypto API

Design Decisions

Why "please" for management?

It's a delightful easter egg that teaches the interface paradigm. The small cost (one reserved word) is worth the whimsy. Users remember it.

Why compound words for free tier?

Single words are valuable namespace ("free", "win", "sale") and should be monetized. Compound words like "crystal-beacon" or "amber-grove" are:

  • Still memorable and brandable
  • Virtually unlimited namespace
  • No squatting concerns
  • Actually quite pleasant to say aloud

Why PoW instead of rate limiting?

Rate limits can be bypassed with distributed IPs or slow enumeration. PoW makes enumeration economically infeasible regardless of how it's distributed. The computation cost is fundamental, not infrastructural.

Why admin keys instead of user accounts?

  • Stateless and simple
  • No email/password management
  • No password reset flows
  • Single-purpose access tokens
  • Easy to share (give key to a teammate)
  • Works offline (no session to expire)

The magic word IS the link. You share the word, not a URL. "The magic word is SUMMER" is the entire instruction. The URL is just magicword.info (or wherever it's hosted).


Future Considerations

Near-term

  • Custom domains: yourbrand.com/magic → magic word lookup
  • QR codes: Generate QR that encodes the magic word
  • Analytics dashboard: Redirect counts, referrers, geography
  • Expiry warnings: Email before premium words expire

Medium-term

  • API keys: Programmatic management for integrations
  • Bulk creation: CSV upload for campaigns
  • A/B destinations: Rotate URLs for testing
  • Time-based redirects: Different URLs by time of day

Long-term

  • Marketplace: Buy/sell/transfer premium words
  • Teams: Shared admin access with roles
  • Webhooks: Notify on redirect events
  • Custom PoW difficulty: Per-word anti-abuse settings

Local Development

This is a single-file Val.town project. To modify:

  1. Edit main.tsx in the Val.town web editor
  2. Changes deploy instantly
  3. Database persists across deployments

To run locally (if extracted):

# Would require Deno + SQLite setup # Val.town handles all this automatically deno run --allow-net --allow-env main.tsx

Credits

Built with Val.town — serverless TypeScript with built-in SQLite.

Inspired by the elegance of promo codes and the frustration of ugly URLs.


License

MIT — do whatever you want with it.