🔧 Programmierung 🕛 vor 3 Monaten 9 Min Lesezeit
0

Design to Code #8: The Cosmetics of Modularity

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

It was sometime in early April. Version 0.1.0 had been sitting on npm for maybe twenty-four hours. I was clicking through the documentation site I'd just deployed, riding that brief, fragile wave of pride you get right before you discover a critical bug.



The Card component page featured a standard "Copy" button on the code block. Out of pure habit, I clicked it, flipped over to a scratch test project, and ran npm install @​7onic-ui/react. The installation finished cleanly. Then, the development server lit up bright red.




CODE
Module not found: Can't resolve '@7onic-ui/react/card'






The code block on my own documentation site was instructing developers to import from a path that literally did not exist in the package they had just installed. It wasn't a typo. It wasn't a missing dependency. It was a path that had never existed and was never going to exist, simply because I had never written a package.json exports map to support it.



Anyone who copied that snippet on day one ran straight into a module-resolution error on line one.






Where the Lie Came From



The Card documentation page relied on a helper function called generateCode() to render the Playground's live preview snippets. Somewhere deep in that utility, I had written a line that looked roughly like this:




CODE
const importPath = `@7onic-ui/react/${componentName.toLowerCase()}`






It feels entirely right when you write it. It's very shadcn-style. It looks clean, professional, and mimics the architecture of a massive, modular enterprise package. The string interpolated perfectly, the syntax highlighter mapped it beautifully, and the page rendered with zero console warnings.



The only problem was that it had absolutely zero relationship to what was actually sitting inside the compiled dist/ directory.



In reality, I had built the package with a single root entry point — one lone index.ts file that re-exported every component. The package.json had "main" and "module" and "types" all pointing strictly to that one file, and that was it. There was no "exports" map, no subpaths, nothing. The npm package and the documentation site were completely misaligned, and the docs site was writing checks that the package couldn't cash.






What I Did Instead of Managing 42 Subpaths



My initial, knee-jerk instinct was to fix the documentation site by making the underlying package match its claims. I figured I'd just build the subpath infrastructure: write out the exports map — "./card": "./dist/card.js", "./button": "./dist/button.js" — and repeat that for all forty-two components. I'd configure tsup to emit every single one of them as an isolated entry point, and then commit to maintaining that list for the rest of my life.



I actually started doing this, but I stopped about four components into the refactor. The sheer volume of package.json plumbing required per component was non-trivial. Every single new component added down the line would mean another entry to write, another build target to track, and another vector for human error if I forgot to map it.



So, I decided to look at how mature UI libraries actually solve this.



shadcn/ui wasn't a valid architectural comparison because it doesn't ship via an npm registry; you're copying raw source files directly into your project. But when I looked at libraries like Mantine, Chakra UI, and Radix Themes, they all import directly from a single root: import { Button } from '@​mantine/core'. Not @​mantine/core/button. The packages I had been quietly romanticizing in my head weren't even doing what my documentation claimed I was doing.



Furthermore, the bundle-size argument didn't hold water. Running tsup with splitting: true ensures that tree-shaking handles dead code elimination gracefully at the named-export level. If a consumer imports { Button } and nothing else, the rest of the library doesn't get shipped to the client anyway.



The subpath import was entirely cosmetic. It was a vibe. It was the aesthetic of a modular architecture, not actual modularity.



I formalized this decision in an Architecture Decision Record — NO-SUBPATH-EXPORTS.md — mostly to stop future-me from having this exact same argument with himself. I established very clear re-evaluation criteria in the document: I would only revisit subpath exports if the library grew past 50 components, if a single root import began ballooning the bundle size past 100KB, or if actual production users explicitly demanded it. Right now, none of those conditions are true. We have 42 components, tree-shaking works flawlessly, and nobody has complained.



Once the ADR was settled, I fixed generateCode() to emit @​7onic-ui/react and absolutely nothing else. I cleared the build cache, reloaded the documentation page, clicked Copy, and pasted it. It worked seamlessly. It was the first time my documentation had actually agreed with my compiled package.






The One Exception (Which Arrived Three Days Later)



Of course there is an exception. There is always an exception.



On 2026-04-08 I shipped v0.2.0 and the Chart component rolled out with its own dedicated subpath: @​7onic-ui/react/chart. The ADR covering this deviation is titled CHART-SUBPATH-EXPORT.md, and it's a direct response to a real dependency bottleneck.



The Chart component relies heavily on recharts. recharts is a massive package, and most developers pulling in a core design system like . Source code on . Follow updates on X at @​7onicHQ.

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
9 Quellen
CVE-2022-44169 | Tenda AC15 15.03.05.18 formSetVirtualSer buffer overflow (EUVD-2022-47119)
1 Quelle
Best early October Prime Day deals: Save on TVs, smartwatches, and more tech
1 Quelle
I gave Claude Code $100 and 30 days to make a profit. Day 1, it built a product. Here's the pattern it used.
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Design to Code #8: The Cosmetics of Modularity

Thematisch verwandte Begriffe: Design, Code, Cosmetics, Modularity · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...