# urls.bid: three frontend migrations in a week (and why)

> urls.bid went Next.js → Astro 6 → TanStack Start in under two weeks. Each move solved a specific problem; here's the honest reasoning and what x402 has to do with it.

By Himanshu Maurya · 2026-06-05 · web · x402 · 2 min
Canonical: https://codingstark.com/blog/urls-bid-three-migrations/

**urls.bid** is a wallet-native link platform: custom-domain short links and gated content/downloads that return `HTTP 402` and unlock via USDC on Solana and Base, using the x402 protocol. In under two weeks the frontend moved through three frameworks — not for fun, each move fixed something.

### The migration ladder

| From | To | Why |
|---|---|---|
| — | **Next.js** | fastest way to get a full-stack app standing |
| Next.js | **Astro 6** | static-first, tiny payload for mostly-static pages |
| Astro 6 | **TanStack Start** | the app kept wanting real server logic at the edge |

Astro was the right call for a marketing-heavy surface, but urls.bid is an *app*: payment-gated links, on-chain ownership, webhook receivers. Those want first-class **server functions**, typed loaders, and route-level auth — which is exactly TanStack Start's shape.

### What actually moved

The TanStack migration was mostly deleting API routes and letting server functions absorb them, then wiring `QueryClient` caching around the slow part — on-chain reads:

```ts
export const purchaseLink = createServerFn({ method: "POST" })
  .validator(purchaseSchema)
  .handler(async ({ data }) => {
    // settle USDC via x402, record on-chain ownership, flip the link public
  });
```

The payment layer itself is published separately as `@codingstark/x402-elysia`, and deploy is GitHub Actions → Cloudflare Workers.

### The takeaway

"Three migrations" sounds like thrash, but each was a deliberate trade: reach for the framework whose *default shape* matches your app, and stop fighting the ones that assume otherwise.
