Build1 distinct publisher2 min readPublished
The plugin compiles descendant rules for everything under the wrapper, so a component's own class list stops describing how it renders. The useful fix decides which authority owns which property before it reaches for a sandbox.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Start with the selector, because that is where the behaviour comes from. `.prose` compiles into rules that target the elements beneath it: `a`, `h2`, `ul`, `img`, and the rest of the tag vocabulary Markdown emits [6]. A hand-built CTA is, structurally, more tags in that subtree, and the plugin has no way to distinguish it from a link the Markdown pipeline produced [3]. The plugin is built for HTML you do not control [4]; embedding components you do control puts two styling authorities on the same elements [16]. Forty lines is a polite distance for a cause to sit from its effect [2].
The specificity story is the part worth testing. The modern plugin deliberately keeps specificity low using `:where()` [7], and a zero-specificity rule should lose to any class sitting on the element itself. Yet both reports above describe element-level utilities failing to take [1][10]. The writeup's account is that properties the component does not set inherit prose's values, and properties it does set are settled by CSS order [8]. Those two statements can only both hold if the utility declaration is emitted before the typography rules in your compiled stylesheet [1]. That is a fact about your build, not about the plugin, and it is the thing that decides whether this failure mode transfers to your repo at all. Check the order in the built CSS before you accept either the diagnosis or the ranking of fixes.
The framing that survives the check is ownership rather than victory [18]. Tier 1 is designing content-like embeds to cooperate: in this build the inline affiliate link is deliberately bold and underlined in the article accent [12], and the CTA settled on a light background, `text-stone-900`, and an accent border, all values prose has no opinion that conflicts with [13]. Tier 2 moves the rule to the container with element modifiers, `prose-a:text-emerald-700 prose-a:no-underline hover:prose-a:underline`, which the author calls the supported customization channel and the wrong tool for one special component [14].
Tier 3 is `not-prose`, and its cost is legible in the mechanism. Prose styles stop at the boundary [15]. That boundary cuts inward too: nothing inside the island gets the plugin's typography, so the island's owner declares headings, spacing, and link treatment by hand, including for any prose-like copy nested in a card [2]. For a product comparison card, an interactive demo, or a form, that is the correct trade, because those are not content [15]. For a component that is mostly words, you have swapped one context bug for a list of per-element declarations you now maintain.
Ranked by verification strength, evidence, and original report placement.
The author reports a CTA button rendered mid-article had underlined links and the wrong text color, and no utility class stacked on the button corrected the issues.
The cause was not the button but the prose class sitting forty lines up in the code.
The prose class from @tailwindcss/typography styles every matching element beneath it, including headings, paragraphs, and the <a> inside a custom button component rendered mid-article; prose cannot tell a hand-built CTA from a Markdown link.
On this build the article layout renders MDXRemote inside <div className="prose prose-stone max-w-none font-serif">.
prose works by descendant selectors: .prose generates rules targeting the elements beneath it (a, h2, ul, img, and others), so any matching tag in the subtree is in scope.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 29, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Two Next.js apps instead of one, because isAdmin is a privilege escalation waiting to happen1 distinct publisher
build
Three manual interventions in a month, and every guard was working as designed1 distinct publisher
build
Six MariaDB versions, one real difference: the only reason to leave 10.6 is the July 2026 clock1 distinct publisher
build
A build step instead of a backend: 1,025 records, 8 locales, no runtime API1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Verifiable mechanism, unverified surroundings
The mechanics are the strong part: descendant selectors, :where(), the not-prose boundary and its nesting caveat are all things a reader can confirm in a browser inside five minutes, and dev.to's author shows the actual wrapper markup rather than a sanitised sketch. The surroundings are thin — no Tailwind or plugin version, no compiled stylesheet to back the source-order explanation, and the one external citation is a bug report that is characterised but not linked.
No uptake signal in view
Nothing here measures who else is affected. One content site's own layout is a witness statement, not a deployment count, and how many builds pair the typography plugin with custom MDX components never comes up — nor does any download, release, or version figure that would let us size the pattern.
Body walks back the headline
"Leaking Into Your Components" promises a defect; the piece then declines to deliver one. The author calls the behaviour the feature working on markup it wasn't warned about, ranks the sandbox fix last, and volunteers that his own fourth option — deleting the plugin overnight — was a tantrum rather than a trade. The conclusions land a shade under the title's alarm, not over it.
A build post that flags its own affiliate link
The author is writing about a site he owns, and one of the two components he holds up as a success is its inline affiliate link — a small commercial thread that runs through the example and is named openly. Nothing is being sold to the reader: the recommendation is to cooperate with a free plugin that the piece also refuses to blame, which is a weak set of motives to distort.
Sure about the cause, unsure about the scope
We are comfortable with the diagnosis and much less so with its perimeter. Why a hand-built CTA inherits prose's link treatment is structural and reproducible; whether element utilities lose to source order on any given build, and whether the plugin's tracker really holds the matching report, rest on one developer's word with no versions to pin them to.