AZ
All writing
2 min read

Rewriting a .NET Blazor app in Go without losing parity

godotnetnextjsrewritesiwe
Part of the projectNFTMixer (Go)A C# / .NET 6 Blazor generative-NFT builder rewritten as a Go API + Next.js frontend, targeting functional parity.View project

"Rewrite it in Go" is a satisfying sentence. It is also, in this case, mostly a lie — and noticing that early is what made the rewrite tractable.

Blazor Server is the UI

The original NFTMixer is a C#/.NET 6 Blazor Server app. Its .razor files are not templates — Blazor Server is a stateful framework that renders on the server and pushes DOM diffs to the browser over a websocket. Go has no equivalent. So while the generation engine, compositing, database access, S3, and wallet auth all port to Go cleanly, roughly 70% of the work was frontend, rebuilt from scratch in Next.js. Budgeting for that up front is the difference between a plan and a surprise.

Parity means behaviour, not files

Full parity does not mean porting every file. Several things were deliberately left behind because they were dead or dangerous:

  • an unauthenticated full-database-dump endpoint,
  • unfinished IPFS publishing that never actually uploaded,
  • entire generations of superseded components that were referenced but unreachable.

Porting those would have been faithfully reproducing debt.

Fixing the things that were simply broken

The most interesting part of a rewrite is the bugs you refuse to carry over. The original's "authentication" believed whatever wallet the browser claimed — no signature, anywhere:

Old flow:  browser says "I am 0xADMIN…"  →  server believes it.
New flow:  server issues nonce  →  wallet signs  →  server RECOVERS the address
           from the signature (go-ethereum).  Same effort, actually secure.

Alongside real SIWE, ownership is now derived from the session rather than a URL parameter, and sessions expire via a Mongo TTL index instead of living forever in an in-memory map.

Deliberate parity breaks

A rewrite is also a chance to be correct where the original was wrong: metadata now follows the OpenSea standard instead of a flat dictionary, and every layer is resized to the output dimensions so non-uniform art composites without misalignment. Those are intentional divergences — parity with the intent, not the mistake.

Back to the projectNFTMixer (Go)See the full case study and related write-ups.View project