Yo, listen up, fellas, ’cause we got a real doozy of a project on our hands. You know, that adult streaming site that’s been making waves with over 50 million unique visitors per month? That fella built it by a single developer who prioritized functionality over maintainability, like a bossin’ cowboy on a horse. But boy, let me tell you, the design was a mess, ain’t it? The site was built on an outdated platform, using technologies that were way out of date, like Python Flask and Jinja templates. And let me tell ya, it was a real challenge to strike a balance between modernization and stability, but we did it, folks.
First up, we brought in the UX designer to refresh the design, giving us a chance to get familiar with the existing codebase and understand the features. We learned that the site was already running on a Python Flask backend with Jinja templates and jQuery handling client-side interactions, but the site was running on a Python backend with Jinja templates and jQuery handling client-side interactions, which was a no-go. We needed a server-rendered, static-style approach, and that’s where HTMX came in.
The AHA Stack was the perfect solution, a
Our client, a leading company in the adult streaming industry, acquired a highly successful indie website with over 50 million unique visitors per month (SimilarWeb). The site had been built by a single developer who prioritized functionality over maintainability.
While the features were mostly bug-free, the design was outdated, and the code relied on aging technologies. The priority had been shipping fixes and features quickly, rather than long-term maintainability.
The main goal of our project was to deliver a modern, responsive, and maintainable site while ensuring business continuity, reducing risk, and making developer onboarding faster and easier.
The Challenge: Balancing Modernization with Stability
Working with the UX designer, our first quick win was a design refresh. This allowed us to become familiar with the existing codebase and features, while also buying time to identify deeper technical issues and plan a technology path forward.
The site ran on a Python Flask backend with Jinja templates and jQuery handling client-side interactions. Although migrating to an SPA framework was tempting, we quickly ruled it out: it would have been excessive for the project’s needs and introduced unnecessary complexity. Instead, we chose to stay with a server-rendered, static-style approach.
The Technology Shift: Introducing the AHA Stack
The solution was inspired by the AHA Stack (Astro, HTMX, Alpine.js). In our case, Astro was replaced by the existing Jinja templates.
The philosophy was simple: build with the web’s core technologies (HTML, HTTP, CSS, JS), avoid fragile dependencies, and prevent the app from breaking with every API or framework shift (as demonstrated plasticly in the classic https://motherfuckingwebsite.com).
Why HTMX? Lightweight Server-Driven Interactions
To keep the site fast and accessible – even on low-end devices – we minimized JavaScript. Since the site was already server-rendered, HTMX was a natural fit.
HTMX allows sending HTML snippets directly over the wire, following HATEOAS principles, and swapping DOM elements without needing JSON parsing or heavy client-side logic. It strikes a balance between old-school full-page reloads and modern SPA complexity.
Why Alpine.js? Simple State Management Without an SPA
HTMX alone was not enough: we needed lightweight state management and interaction handling. jQuery was an option, but it felt outdated and unattractive to new developers.
We adopted Alpine.js, a dependency-free, intuitive library that complements HTMX perfectly. After a proof-of-concept rewrite of a key page, Alpine proved to be efficient, easy to learn, and expressive enough for our use cases.
By progressively rewriting less critical pages first, then moving to core routes and new business features, we introduced Alpine incrementally. This minimized disruption, made feature requests easy to integrate, and preserved stability.
Implementation Hurdles and Solutions
Migrating to the AHA stack required adjustments:
- Combining modern modular JavaScript with legacy non-modular code.
- Adding TypeScript for type safety while managing untyped legacy code.
- Updating backend handlers to return conditional HTML snippets for both old and new functionality.
Despite these challenges, the benefits were clear. Alpine components had well-defined boundaries, making unit testing with Jest straightforward.
Lessons Learned from Using Alpine.js
While Alpine was a joy to use, we discovered important nuances:
- Using a class-based approach kept types manageable, but required careful handling of constructor vs. init lifecycle methods.
- Passing backend/template values into Alpine components needed special attention, e.g.:
<div x-data=”horizontalScroller(‘value of my_var’)”>
Alpine.data(‘horizontalScroller’, (my_var: string | null) => new HorizontalScroller(my_var));
- Always let init manage component setup, and rely on $nextTick to ensure logic executes after the component is mounted.
Conclusion: Choosing Stability Over Complexity
This project reinforced a key insight: if you don’t need an SPA, don’t build one.
Fundamental web technologies – HTML, HTTP, CSS – are stable and long-lasting. HTMX and Alpine build directly on top of them, dependency-free, while still offering an SPA-like development experience. The result was intuitive, testable, and maintainable code that ensured the platform could scale with both users and developers.
The post Case Study: Modernizing a High-Traffic Streaming Platform with the AHA Stack (HTMX & Alpine.js) appeared first on RisingStack Engineering.