Case Studies
Engineering Case Study

Building an AI-assisted music platform without losing engineering discipline

I'm a senior .NET/Azure engineer. I don't really do front-end. Until recently, I had no idea what an "editorial tone" was. Then I built Changsta.com, and found out what happens when a backend engineer, working alone, uses modern AI tooling to build something entirely outside their normal area.

Type Engineering Case Study
Domain AI · Automation · Architecture
Stack .NET · Cloudflare · Azure · OpenClaw
Status Live · Personal
Vanilla JS
no framework, minimal build tooling
~£0/mo
infrastructure cost
Deterministic
recommendation scheduling
Daily
AI maintenance loop
Changsta.com homepage: dark radio-style interface showing the current mix, mood navigation, and time-of-day programming
changsta.com, the live platform. SoundCloud hosts and streams; the .NET API handles curation, mood programming, and discovery.

The actual problem with SoundCloud

SoundCloud is fine for hosting mixes. Upload a file, paste in a tracklist, share the link. What it doesn't really give you is any sense of programming: the idea that a Sunday morning at 7am calls for something different to a Friday night at midnight.

After a few years of uploading, I had a deep archive with almost no way to navigate it. Everything was sorted chronologically. Newest on top, oldest buried. No mood context, no time-of-day filtering, no way to arrive at the site and feel like you'd tuned into something rather than opened a list.

I wanted something that felt closer to a late-night radio station. Not a content feed.

The solution was to leave SoundCloud doing what it's good at (hosting, streaming, embeds, CDN) and build a separate layer on top that handled curation, mood, programming and discovery. That boundary held up throughout the whole build.

Architecture, kept deliberately boring

The stack is intentionally small. No Kubernetes, no event buses, no frontend framework. The whole thing runs on an RSS feed from SoundCloud as the live event source, blob storage for the enriched mix catalogue, an in-memory cache as the hot path, deterministic recommendation logic, and a vanilla JS/CSS/HTML frontend deployed to Cloudflare.

The last point gets the most raised eyebrows. No React, no TypeScript, no framework. There's minimal build tooling (an env injection step, a dist copy, Wrangler for local Cloudflare Worker dev) but nothing that needs babysitting. The frontend deploys anywhere, has no cold start overhead, and won't need rewriting in eighteen months because the ecosystem changed direction. For a side project with one maintainer, that simplicity has real value.

The frontend is there to make the experience work. The engineering is in the API: the catalogue model, the warmth scalar, the slot-scoring logic, the in-memory cache, the RSS merge strategy. That's where the decisions that matter actually live.

The AI components sit at the edges of this architecture, around the deterministic core.

SoundCloud RSS flows into the .NET API, which maintains the enriched catalogue in Azure Blob with an in-memory hot path. The Cloudflare frontend serves the SoundCloud iframe player. OpenClaw agents handle daily maintenance; GitHub Actions and Application Insights cover CI/CD and observability.

Recommendations without the ML infrastructure

The recommendation engine is mostly deterministic, which wasn't the obvious choice but turned out to be the right one.

The most useful field in the whole system is a warmth scalar: a float between -1.0 (cold, aggressive, late-night techno) and +1.0 (warm, euphoric, peak-hour house). Combined with BPM, it turned out to be surprisingly expressive. You can describe the feel of almost any DJ mix with just those two numbers.

From there, the Mood Compass (a 2D canvas where every mix is plotted by BPM against warmth) became the most interesting UI experiment on the site. Users drag around the space and discover nearby mixes. It's more like exploring than searching.

The radio scheduling is fully deterministic. Every hour slot has a target BPM, target warmth and target energy profile. Two people loading the page at the same time get the same station. That's intentional. Shared programming feels different to a personalised feed, and for a music context, I think that difference matters.

Where AI does appear in recommendations, it operates under a constraint I'm happy with: it can only explain a recommendation by quoting exact metadata from the mix itself. No invented reasons, no generic descriptions. If it can't ground an explanation in real evidence, it doesn't give one.
Mix metadata feeds into mood weights and the warmth scalar, which drives deterministic slot scoring and radio lane assignment. The AI endpoint is optional; it handles natural-language search and grounds every recommendation in actual mix metadata before surfacing it.
The Mood Compass: a 2D canvas plotting every mix by BPM on one axis and warmth on the other, with a ranked sidebar alongside
The Mood Compass. Drag around the space to find mixes by feel rather than by name or date. It's more like exploring than searching.

Design work I had no business doing

The more tightly I constrained the problem, the better the AI-assisted design output got. Specific typography rules, specific spacing, specific colour rules, specific artwork treatment rules. Unconstrained: generic. Constrained: usable.

The visual system for Changsta was built iteratively with Claude Design across radio layouts, compass interactions, catalogue modes and mobile interactions. I have no formal design background. The constraint discipline carried the weight.

Six-wide grid of mix cover artwork from the Changsta catalogue, showing consistent visual identity across the archive
The tighter the constraint, the better the AI-assisted design output. Unconstrained: generic. Constrained with specific rules: usable.

Operational automation with a human still in the loop

The maintenance loop is the part I'm most satisfied with. Every day, an OpenClaw agent queries the diagnostics endpoint, analyses any production failures, filters out noise, and turns real issues into GitHub tickets. A second scheduled agent picks one safe ticket, branches from develop, attempts the smallest fix it can justify, runs the build and tests, and opens a PR.

I still review everything. I control feature development, QA, and what goes to production. The agent's job is to reduce the surface area of operational overhead, not to make decisions. The same shape applies to client production systems: AI at the edges of well-defined automation, humans on anything that ships to users.

That's not a limitation. It's the design.
The maintenance loop ends at PR creation. Merge and deploy are always human decisions. The agent's job is reducing operational surface area, not taking responsibility for production.

Adjacent tools

Over time the platform accumulated a few adjacent tools. None of these are products. They're tools I built because I needed them, and they happen to work together.

What this was actually about

I wanted to find out what happens when a backend engineer, working alone, uses modern AI tooling to build something outside their normal area. Design, front-end, editorial voice, operational automation. All of it.

It works, with conditions. AI was most useful when it was operating inside constraints I'd thought about carefully: bounded inputs, grounded outputs, deterministic fallbacks. Every time I tried to use it in an open-ended way, the results were mediocre.

The platform that came out of this isn't autonomous and it isn't impressive in the way people mean when they say that about AI projects. It's just a small, sustainable thing that runs reliably, costs almost nothing to operate, and sounds exactly how I want it to sound.

That was the goal.

Tech Stack

changsta.com Web API: catalogue, recommendations, Mood Compass GitHub ↗
.NET 10 ASP.NET Core Azure App Service Azure Blob Storage SoundCloud RSS Warmth scalar Deterministic scheduling Grounded AI explanations Bicep Application Insights
Frontend
Vanilla JS CSS HTML Cloudflare Workers Wrangler SoundCloud iframe player
Operational Automation
OpenClaw (self-hosted) Mac Mini M1 GitHub Issues + PRs GitHub Actions CI/CD
Case Studies
Get in touch

Building something similar?

The most transferable part of this project isn't the music layer. It's the pattern: constrain AI tightly, use deterministic systems where they'll hold, automate operational overhead without ceding human judgment on what actually goes out.

If you're working on something in that space (constrained AI systems, recommendation architecture, operational automation), feel free to get in touch.