The Domain Coupling Problem: Why UI Components Shouldn't Read DTOs In short: A shared component that takes is a component only one application can use. The fix is not a union type — it is a shape the component defines itself. The real test of a component library is not whether one application likes it. It is whether a second application, with a different backend, can use it unchanged. How the coupling happens The library team builds a delivery summary card. The dispatch dashboard already has a from its API, and passing it straight in is the shortest path. This works beautifully for the dispatch dashboard. It is also, by Chapter 4's rules, already broken: is importing from , and the boundary lint should have failed. Let's follow what happens if it did not. The second application arrives The farmer portal needs the same card. Its API returns something structurally different: No . No . No — farmers care about payment, not lab clearance. A farmer has never heard of a somatic cell count. The farmer portal cannot use the component. It has three options and they all end badly. Option 1: copy it. Now there are two delivery cards. They drift within a quarter, and the design system has two answers to the same question. Option 2: a union type. This is the one that looks clever and is worst: The library now imports from two domains and contains a branch per consumer. Add a third application and it is three branches. Every consumer's backend change is now a library release. This is the god component from Chapter 4, reached by a different road. Option 3: ask the library team to add inputs. , , , , , , each optional — the over-configuration trap from Chapter 5. What went wrong The component was given a backend's shape rather than a UI shape. exists because the logistics service returns it. Its field names, its nesting, and its lifecycle belong to a team that does not know this component exists. When they rename to , your shared component breaks — and so does every application using it, including the ones that never called that service. A shared component should ask itself a different question. Not "what does the API return?" but "what do I actually render?" Looking at the markup: a title, a subtitle, a status, and a list of label/value pairs. That is the whole component. Nothing about tankers. The fix, in outline Define the shape in the library, in the library's own vocabulary: Note the name changed too. described a business purpose; describes what it draws. That is not cosmetic — a component named after a business concept invites business logic back in. Also note: no . Native control flow needs no import, and a reflexive is a common piece of AI-generated noise. Now both applications map their own data into that shape. The library never learns what a tanker is, and the next application after these two costs one mapping function. "But I thought DTOs were already good enough types" This is a fair objection. is a real TypeScript interface. It is strict, it is accurate, it is often generated from an OpenAPI schema so it cannot drift from the backend. Defining a second interface that holds much the same information looks like duplication for its own sake. The issue is not type quality. It is who owns the type and what it is for. A DTO is a description of a network payload. It is owned by the backend team, versioned with their service, and shaped by their storage and their transport concerns. It exists to move data over a wire. A presentation model is a description of what a component renders. It is owned by the library, versioned with the design system, and shaped by the UI. Three things follow from that difference: A DTO changes for reasons the UI does not care about. The logistics service splits into and for a payroll integration. That is a backend concern. If the shared card reads , this change breaks the dispatch dashboard and the farmer portal and anything else touching that component — because a payroll requirement reached the UI layer. A DTO carries fields the UI must not render. Internal ids, audit columns, pricing internals, sometimes personal data. Handing the whole object to a presentational component means every field is one careless away from a screen. A DTO has no notion of presentation. is not something to put on screen. Somebody has to decide it displays as "Awaiting lab" and shows amber. If the component decides, that decision is now in the library and applies to every consumer — including the ones for whom "PENDING LAB" means something different. That last point is the deep one. A presentation model is where the business decisions have already been made. By the time exists, someone has decided what the title says, what the status reads, and which tone it uses. The component just draws it. DTO in the component Presentation model --- --- --- Owned by The backend team The library Changes when The API changes The design changes Second app with a different API Cannot use the component Writes a mapping function Whe…