惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
博客园 - 【当耐特】
量子位
博客园 - 叶小钗
有赞技术团队
有赞技术团队
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
博客园 - 司徒正美
爱范儿
爱范儿
美团技术团队
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
罗磊的独立博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Last Week in AI
Last Week in AI
Hugging Face - Blog
Hugging Face - Blog
I
InfoQ
D
DataBreaches.Net
宝玉的分享
宝玉的分享

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I built a shopping search engine in Rust that you talk to...
Macan · 2026-06-16 · via DEV Community

Macan

Keyword search is bad at specific products. I'd know exactly what I wanted — "dark green waxed cotton jacket, under €200, not from a giant marketplace" —
and every engine buried me in Amazon listings and content-farm "best of" lists.

So I built Hubje: you describe a product in plain language and it returns real, buyable products from independent shops, ranked by how
well they match what you actually said. Here's the interesting engineering.

## Server-rendered Rust, no SPA

The whole site is Rust (axum) rendering HTML with Maud, a compile-time template macro. No
JS framework, no hydration, no API layer — handlers return HTML strings.

  fn product_card(p: &Product) -> Markup {
      html! {
          article class="rounded-2xl border border-slate-200 bg-white" {
              img src=(img_url(&p.image, 480))
                  srcset=(img_srcset(&p.image, &[240, 360, 480, 600, 800]))
                  sizes=(CARD_SIZES) loading="lazy";
              h3 class="text-sm font-semibold text-ink" { (p.title) }
          }
      }
  }

Why: a shopping site lives or dies by SEO, and SSR is trivially crawlable + fast. htmx handles the few interactive bits (live search results swap in-place)
as progressive enhancement — URLs stay real and shareable. The "framework" is the type system.

## Plain-language search

Search isn't keyword matching. It pulls live listings (via Exa) and an LLM ranks/filters them against your sentence — including soft
constraints like "under €200" or "minimalist". Same pipeline writes the one-line "why this pick" rationales and a top-3.

The genuinely fun part is the failure mode as a feature: when a description returns nothing buyable, that zero-result query is logged. Recurring gaps
auto-generate a curated buying guide page — so unmet demand turns into indexable content. The content engine feeds itself.

## CWV obsession (self-host everything)

Organic is the only growth channel I can afford, so Core Web Vitals matter. I ended up removing every third-party request:

  • Fonts — vendored the variable woff2s, @font-face with font-display: swap + unicode-range so latin-ext only loads on an accented glyph. No Google Fonts round-trip.
  • htmx — self-hosted + defer, so zero render-blocking external JS.
  • Images — a Rust /img proxy that downscales and content-negotiates the format:
  let fmt = ImgFmt::from_accept(accept_header); // webp if offered, else jpeg
  // cache key + Vary: Accept so caches don't cross-serve

WebP (libwebp via the webp crate) is ~30% smaller than JPEG and builds fine for a distroless image. Cloudflare's field data now shows LCP 100% "good".

Plus the boring-but-required stuff: canonical URLs, full OpenGraph/Twitter, JSON-LD (Product with price/availability, ItemList, FAQ, Breadcrumb, Dataset),
noindex on thin pages, a real 404, trailing-slash 301s.

## Ad-blocker-proof analytics

GA and even Cloudflare's beacon get blocked by uBlock/AdGuard — which undercounts exactly this audience. So pageviews are counted server-side in the
request middleware (cookieless, aggregate-only), with day-salted hashes for unique visitors and a curated datacenter-IP list to flag scrapers spoofing
browser UAs as bots, not humans.

## Deploy

include_str!/include_bytes! embed the CSS, fonts, htmx, and favicon straight into the binary, so the runtime image is just distroless + one static-ish
executable. Built with kaniko, deployed to a small k3s homelab cluster. The whole thing is one ~170MB binary.

## Honest tradeoffs

  • It's new — catalog coverage is thin, so niche searches sometimes return nothing.
  • Affiliate-funded (disclosed); commission never affects ranking.
  • LLM-in-the-loop search is a latency/cost tradeoff vs. a pure index; caching + a top-3-only LLM pass keeps it sane.

Try it with the most oddly-specific thing you've failed to find online and tell me if it surfaces anything sane: https://hubje.nl — feedback welcome,
especially on search quality.