dRadio development update: what changed since February 2026

Laravel PostgreSQL Bulma Radio Website Nginx SEO radio.dubbeh.net

It has been a long time since the last proper dRadio update. The previous post was back in February, when most of the visible work was around getting non-HTTPS streams playing reliably through the proxy, improving stream selection, cleaning up tags and reducing logo bandwidth.

That version now feels like a very different project.

Since then there have been several thousand commits touching almost every part of dRadio: playback, the public directory, accounts, ratings, administration, the database, station identity, locations, enrichment, SEO and the runtime architecture itself. This is the useful overview rather than a commit-by-commit changelog.

Playback moved well beyond the original HTTPS proxy

The secure stream proxy is still an important part of dRadio, but playback has had a lot more work since February.

  • Legacy HTTP radio streams can still be played without browser mixed-content failures.
  • HLS / M3U8 support was hardened, including nested playlists and more stable mountpoint handling.
  • HLS.js is available as a browser fallback where native HLS playback is missing.
  • Stream checks can inspect HLS manifests and recover useful codec and bitrate information.
  • Playback selection has been tightened around current stream health rather than simply trusting whichever URL arrived first.
  • Proxy authentication and failure behaviour have been hardened repeatedly so broken or hostile upstream responses fail safely.
  • Now-playing and playback APIs have been separated into narrower paths instead of making station pages do all of the work themselves.

The goal is still simple from the visitor's point of view: press play and let dRadio deal with the ugly differences between upstream radio servers.

The directory became a proper discovery system

The old catalogue already had basic country, tag, language and codec pages. Since February that has grown into a much broader browse system.

The current public routes cover genres, countries, regions, localities, languages and tags, including nested genre paths and combinations between several facets. That makes it possible to move through the catalogue rather than relying on search alone.

Other discovery work includes:

  • dedicated top-level browse hubs;
  • nested location pages;
  • related facet links;
  • similar-station suggestions;
  • random station discovery;
  • search suggestions;
  • saved and recently visited stations;
  • public station statistics and rankings;
  • much stricter canonical and legacy-route handling.

A directory this large is only useful if it can be narrowed down quickly, so this has been one of the biggest public-facing changes.

Accounts, ratings and station feedback arrived

dRadio gained a real account system in March, followed by a set of features that need a stable user identity.

The current application supports registration, login, password reset and email verification, along with:

  • station ratings;
  • saved stations;
  • recently visited stations;
  • station claim requests;
  • correction requests;
  • repair reports for bad listings or broken data.

Cloudflare Turnstile is used on the public forms where it is useful, and public submissions do not directly overwrite the station catalogue. They go through validation and review instead.

That distinction matters because station data is assembled from multiple sources and a seemingly harmless edit can otherwise overwrite better information.

The public UI went through a few iterations before settling on Bulma

There was quite a bit of UI experimentation during the first half of the year.

Tailwind and DaisyUI were introduced for one of the redesign attempts, followed by a more custom neon-style frontend. I eventually moved away from that direction and started a clean Bulma migration at the end of April.

The current public frontend is Bulma with dRadio's own CSS, Blade templates and JavaScript on top. Tailwind is no longer part of the current application.

That change was less about chasing another framework and more about getting back to a smaller, more predictable CSS foundation that is easy to customise without fighting a large component abstraction layer.

The admin side was rebuilt — and Filament was deliberately removed

The administration side went through an even bigger transition.

Filament and Livewire were introduced in March and a large part of the station workspace was migrated onto them during April. That experiment ultimately did not fit dRadio very well, particularly around station field values, form state and the requirement that editing a station must never create or persist unintended values simply because they were present in UI state.

At the beginning of May I started replacing that stack with a custom Bulma-based operator workspace. By 5 May the main admin routes had been cut over and the Filament/Livewire fallback runtime was removed completely.

The current admin is therefore not Filament. It is a controller-backed Laravel application using Blade, Bulma and purpose-built forms and components. Station details, streams, genres, claims, corrections, repair queues, user access and other operator tools all go through that custom UI.

That gives the application much tighter control over what a form actually means and what gets written when an operator saves it.

PostgreSQL became the database foundation

The PostgreSQL work started as a formal migration programme in May and turned into one of the largest changes dRadio has had.

This was not just a database-driver swap. Station, stream, tag, location, rating, evidence and projection ownership all had to be reviewed so the application could use PostgreSQL properly rather than carrying old assumptions forward.

The migration work included:

  • a clean PostgreSQL migration baseline;
  • explicit extension/readiness checks;
  • removal of retired MariaDB tooling;
  • tighter relational ownership for current station data;
  • more set-based catalogue operations;
  • better indexes for the actual public and maintenance query shapes;
  • migration and replay tooling for the live catalogue;
  • extensive work to keep public reads bounded while background jobs do the expensive maintenance.

The current project targets PHP 8.5, Laravel 13 and PostgreSQL.

One of the most noticeable operational results has been moving large catalogue tasks into a database that is much better suited to the way dRadio now works.

Ratings and public statistics became first-class features

Station ratings were added during the PostgreSQL migration work and later simplified so the individual rating events and the current aggregate have clear owners.

The public site also gained station statistics and ranking pages. Those are built from published snapshots rather than forcing every visitor to trigger large live aggregates.

That same idea — expensive work happens once, ordinary reads stay cheap — is now used in several parts of the application.

Station identity and duplicate handling were rebuilt

Internet radio directories contain a lot of conflicting identity data. The same station may appear through several providers with different names, URLs, logos and streams, while unrelated stations can share generic metadata.

The identity and deduplication system has therefore had a very large amount of work.

The current direction includes:

  • separating provider identity from the final public station identity;
  • treating exact stream identity as strong duplicate evidence;
  • keeping broad duplicate discovery separate from the decision to merge;
  • validating merge components before applying destructive changes;
  • preserving useful stream, location and profile state across merges;
  • keeping a merge ledger so supported merges can be reversed;
  • repairing placeholder or poisoned station identities instead of treating them as real names;
  • moving large duplicate candidate working sets into PostgreSQL instead of building catalogue-sized PHP structures.

Most visitors should never notice any of this directly. The visible result should simply be fewer duplicates and fewer stations with obviously broken identity data.

Provider data now has clearer boundaries

RadioBrowser and Shoutcast are still major catalogue sources, but provider handling is much more explicit than it was earlier in the year.

Accepted provider observations are stored separately from final station state, and the provider-specific writers no longer each make their own competing decisions about current station fields.

Provider snapshots are also retained for controlled recovery and replay instead of assuming a remote directory can always reproduce yesterday's input exactly.

In August, IPRD was added as another normal provider source rather than as a one-off import or quarantine system.

The current refactor is continuing this work by making provider-current state queryable and routing provider-derived current values through one narrow reconciliation boundary.

Tags, genres and locations are much more structured

Free-form provider tags are useful input, but they make a poor final taxonomy on their own. The tag pipeline now does much more normalisation, mapping and repair before values reach the public directory.

Location handling changed even more significantly. The project moved away from the previous geography foundation and adopted Overture as the location authority during August.

Stations now link to accepted location entities rather than carrying several competing copies of country/region/city truth. Public URLs expose the human hierarchy — country, region and locality — without leaking internal location IDs.

That work also improved multilingual and alias matching while keeping ambiguous location changes fail-closed.

Enrichment became safer and more useful

Station enrichment is now a much larger system than it was in February.

Depending on the available evidence, dRadio can use official station websites and public references to discover or improve:

  • official links;
  • social profiles;
  • logos;
  • descriptions;
  • location evidence;
  • Wikipedia and Wikidata references.

The important part is that discovery is not the same thing as authority. Finding a possible Facebook page, Wikipedia article or logo does not automatically make it the final public value.

The enrichment pipeline has accumulated a lot of safety rules around shared domains, unrelated sibling stations, redirects, multilingual pages and weak location evidence so an automated discovery does not casually poison a station profile.

Public pages are doing much less database work

Performance has been a constant theme throughout the later refactors.

Some of the changes are visible in the code only, but they affect almost every normal request:

  • public facet counts are materialised instead of repeatedly aggregated;
  • expensive browse consequences are refreshed only when relevant station state changes;
  • homepage and statistics data can come from snapshots;
  • similarity stores stable candidate relationships and hydrates volatile facts at read time;
  • large provider and duplicate operations use bounded/set-wise PostgreSQL work;
  • no-op database writes have been removed from a number of hot paths;
  • repeated DTO/config/presentation relay layers have been collapsed;
  • station and directory reads have been narrowed to the data each page actually needs.

The aim is not just benchmark numbers. It is to keep page response time predictable even while the background catalogue work becomes more sophisticated.

SEO and old URL handling had a large cleanup

There has also been a lot of work that is mostly invisible unless you look at search-engine tooling.

That includes:

  • canonical route cleanup;
  • deliberate 301 / 410 handling for retired URL shapes;
  • split station, genre and location sitemaps;
  • indexability rules for weak or fallback station identities;
  • structured breadcrumb/schema coverage;
  • IndexNow submission state;
  • Google Search Console snapshot and recovery tooling;
  • tighter control over which browse combinations are actually useful indexable pages.

On a directory that can generate a huge number of possible URL combinations, being selective is much safer than treating every filter state as a search landing page.

The project is still in a major internal refactor

The public GitHub repository does not quite show the newest local state yet.

At the time of writing my local branch is 32 commits ahead of the current GitHub head. Those commits are part of a larger A-to-Z dRadio vNext refactor focused on making the backend substantially more predictable.

The first four phases are complete locally:

  • Phase A: capture the real database/runtime performance baseline;
  • Phase B: replace architectural lock-in tests with semantic safety checks;
  • Phase C: establish queryable provider-current observations and prove parity;
  • Phase D: route provider-derived current station updates through one reconciliation seam.

Phase E is currently in progress. That phase is replacing the older profile-intent model with value-bearing human overrides and making manual station edits much more explicit about who owns a value, including clean SET, CLEAR and restore-automatic behaviour.

That work is intentionally not being rushed onto production just to keep GitHub and local perfectly synchronized. The local refactor is being validated in stages before the next deployment point.

The larger theme behind it is simplification: fewer overlapping owners, fewer hidden framework behaviours, typed inputs at boundaries, less repeated work and clearer rules about which table or service owns each piece of station state.

What comes next

The backend refactor remains the immediate priority. There are still later phases covering evidence, current-profile reconciliation, durable work, locations, streams, tags, merge/recovery paths, public reads and more cleanup before that programme is finished.

There is also a broader public UI refresh I want to revisit once the backend settles. I would rather redesign against a stable data/runtime model than keep rebuilding page components while their underlying ownership is still changing.

If you have not checked dRadio since February, have another look at radio.dubbeh.net. The player, directory, ratings, station pages and catalogue quality are all substantially further along than they were at the start of the year.

And if you find a bad station, broken stream or incorrect listing, the correction and repair-report flows are now the best way to flag it.