My HTML-to-Markdown API learned that every framework invents its own idea of a heading
I built the HTML-to-Markdown converter expecting a boring job: walk the DOM, emit # for <h1> , ## for <h2> , done. The first real-world test was a Next.js docs site, and it came back as a wall of bold text with zero heading structure. The culprit: Tailwind. The site styled <div class="text-2xl font-bold mb-4"> as its visual headings. No <h1> tags anywhere. Semantically it was a disaster, visually it was a perfectly good docs page. My converter saw divs and shrugged. The fix wasn't smarter HTML parsing — it was admitting that "heading" is a visual concept, not a tag concept. I added a heuristic pass: before the structural walk, scan for elements whose computed class names match common heading patterns ( text-xl , text-2xl , text-3xl , font-bold , font-semibold , mb- spacing tokens) and promote them. It's ugly. It's fragile. It works on maybe 80% of Tailwind sites. Then I hit a Bootstrap site that used <h1 class="h3...