Public API Means Public Promise In short: is a commitment to maintain every file it touches. Name your exports one by one, and the things you did not name stay yours to change. In an Angular library, is the most consequential file in the package. Angular's own documentation puts it plainly: anything exported from this file is made public when your library is imported into an application. It is also the file people treat as paperwork. Create a component, add to make the warning go away, move on. Read that export again as what it actually is. It says: I will maintain this. I will document it. I will not change it without a major version bump. Export everything, and you have promised to maintain everything. The accidental promise has an internal helper for sorting dates and an internal row component: The lazy version: Now a developer on the billing team needs to sort invoice dates. Their editor offers from . It does exactly what they need. They use it. Why wouldn't they? It was exported. Six months later you rewrite the table's sorting to use and delete . Your library's tests pass. You publish. The billing app fails to build. You broke a promise you did not know you had made — and from the billing team's point of view, you shipped a breaking change in a minor release. That is the trust failure from lesson one, arriving through the export list. The explicit version Name every export. Every one is a deliberate decision. Now is a compile error. The billing team never had the option, so they never built on it, so you never broke them. Two details worth copying: Use for types. It makes the intent explicit and lets bundlers drop the import entirely. Consumers still get full type safety. Leave the comment about what is not exported. It answers the question a maintainer will otherwise ask by reading four files: did they forget, or was that on purpose? What belongs in the public API Export Why --- --- Components and directives consumers use in templates Obviously Types appearing in an input or output signature Otherwise consumers cannot type their own code Injection tokens for configuration Part of the setup contract A style provider function The supported way to configure the library And what does not: Not exported Why --- --- Child components used only inside another component Composition detail; you will want to change it Utility and comparator functions They will get rewritten Base classes and mixins Inheritance is not an API you want to support Anything with in the name If it needed the label, it needed the privacy The type rule has one wrinkle worth stating. If a public component has this input: then must be exported. Otherwise consumers cannot declare a typed variable to pass in. A type that appears in a public signature is already public — exporting it just makes that fact honest. Configuration through a provider, not through exports A common leak is exporting a mutable config service so applications can poke at it: Export a provider function instead. The surface is one function and one options type: You can restructure everything behind that function forever, as long as the options keep meaning what they meant. Guard it Two controls, both from earlier chapters, applied here: Chapter 8 adds the third: a CI job that snapshots the public API and fails when it changes without a version bump. "But I thought exporting more just made the library more useful" This one is genuinely well-intentioned. You are trying to be helpful. Somebody might need that comparator. Why make them write it again? The reason is that an export is not a gift, it is a contract — and you sign it on their behalf without either of you noticing. The asymmetry is what makes it costly. Adding an export takes ten seconds and feels generous. Removing one requires: finding every consumer across twenty repositories, a deprecation period, a migration, a major version, and twenty teams scheduling an upgrade. You made a ten-second decision that costs a quarter to undo. And the benefit you imagined mostly does not arrive. Consumers who need a date comparator will usually write four lines rather than couple themselves to your internals. The ones who do take it are the ones who will be broken later. There is a second-order effect too. A large export list makes the library harder to use, not easier. A consumer scrolling ninety exports cannot tell which six are the design system and which eighty-four are plumbing. A small, curated list is itself documentation. Export everything Export deliberately --- --- --- Symbols consumers see 90 24 Can you refactor internals freely? No Yes Cost of removing something Major version, 20 teams Free — nobody had it "Which of these should I use?" Unanswerable Obvious Accidental breaking changes per year Several Zero Autocomplete noise for consumers High Low The rule that follows: export the smallest set that lets a consumer do their job. If someone genuinely needs an internal, that is a conversation and a deliberate promotion…