Building a Unified Filter System Across Four Frontend Pages

I’m sitting here on a Sunday evening, staring at the Trend Analysis codebase, and I realize we’ve just completed something that felt impossible two weeks ago: unified filters that finally work the same way everywhere. Let me walk you through how we got here.
The problem was classic scaling chaos. We had four different pages—Explore, Radar, Objects, and Recommendations—each with their own filter implementation. Different layouts, different behaviors, different bugs. When the product team asked for consistent filtering across all of them, my first instinct was dread. But then I remembered: sometimes constraints breed innovation.
We started with the Recommendations page, which had the most complex requirements. The backend needed server-side pagination with limit/offset, a priority matrix derived from P4 reports, and dynamic role extraction. I rewrote the recommendation_store module to handle this, ensuring that pagination wouldn’t explode our API calls. The frontend team simultaneously built a new popover layout with horizontal rule dividers—simple, but visually clean. We replaced horizontal tabs with role chips, which turned out to be far more intuitive than I expected.
But here’s where it got interesting: the Vite proxy rewrite. Our backend routes didn’t have the /api prefix, but the frontend was making requests to /api/*. Rather than refactoring the backend, we configured Vite to rewrite requests on the fly, stripping /api before forwarding. It felt like a hack at first, but it saved us weeks of backend changes and made the architecture cleaner overall.
The i18n work was tedious but necessary—new keys for filters, pagination, tooltips. Nothing glamorous, but the multilingual user base depends on it. We also fixed a subtle bug in Trend Detail where source URLs were being duplicated; switching to domainOf for display eliminated that redundancy.
On the Lab side, we optimized prompts for structured extraction, built an llm_helpers module, and improved the scoring display in Product Detail. The new table columns across Lab components gave us better visibility into the pipeline, which is always valuable when you’re trying to debug why a particular trend got labeled wrong.
One tiny thing that made me smile: we added html.unescape to both the signal mapper and the StackOverflow adapter. Those HTML entities in titles were driving everyone crazy.
By the time we tagged v0.12.0, the unified filter system was live. Four pages, one design language, consistent behavior. The product team smiled. The users stopped complaining about inconsistency.
And yes, I’d tell you a joke about NAT but I would have to translate. 😄
Metadata
- Branch:
- fix/remove-sidebar-logo
- Dev Joke
- Совет дня: перед тем как обновить NumPy, сделай бэкап. И резюме.