Architecture
One package, granular by subpath rather than by sub-package, plus companions for anything heavy. This page shows why the split runs where it does — and recomputes the numbers behind that decision on every build.
- 77
- core components
- 136
- export paths
- 0
- runtime dependencies in the core
- 12
- packages in the family
Why the catalogue groups are not package boundaries
The catalogue splits components into groups — actions, forms, data, navigation — and those groups look like ready-made packages. They are not: the groups answer «where do I look for a component», while the dependency graph answers «who renders whom», and the two do not coincide.
- 78
- edges in the render graph
- 56 (72%)
- of them cross group boundaries
- 4
- graph depth
- 32
- components with no dependencies
Edges that cross a group boundary
GrAutocompleteformsGrChipdataGrAvatardataGrSkeletonfeedbackGrBreadcrumbsnavigationGrLinkactionsGrChipdataGrBadgefeedbackGrCollapseoverlaysGrCarddataGrCollapseoverlaysGrIcondata
What everything else is built from
Cut the package along the groups and these components end up in every piece — or behind a peer dependency of every piece.
GrIcondatarendered by 15 dependentsGrButtonactionsrendered by 13 dependentsGrSkeletonfeedbackrendered by 6 dependentsGrInputformsrendered by 5 dependentsGrChipdatarendered by 3 dependents
Every figure in this section is computed from the installed package: dependencies come from the granular provider, groups from the registry. The library’s own document quotes the same argument measured at an older version — that is exactly why this page measures rather than quotes.
How an import reaches the bundle
Granularity is not a promise about tree-shaking. It is the shape of the package: a subpath per component, an entry per subpath, and CSS inside the component’s own chunk.
- You import a subpath
- the bundler takes that entry and its graph
- the component’s CSS travels in the same chunk
- the UnoCSS preset emits utilities for the components you listed, and for nothing else
The core and the companions
The core ships the general-purpose components. Anything that carries a heavy dependency, belongs to a domain of its own, or is needed by a minority lives in a companion package with a peer on the core.
That is the one condition under which the decision «one package» is revisited: a family of components acquires a heavy external dependency the rest do not need. Charts, dates, rich text, media and the dashboard left for exactly that reason.
@feugene/granularity-chrono@feugene/granularity-media@feugene/granularity-charts@feugene/granularity-code@feugene/granularity-dashboard@feugene/granularity-editor@feugene/granularity-forms-schema
Where the library ends
It is not an application framework. Routing, data fetching, state and the build are yours; the design system gives components, foundations and the preset that ties them together — and stops there on purpose.
Read further
The full argument, with the history of the decision, is in the library repository.
Why the package is not split — the library’s own documentHow this is measuredComponent catalogue
Computed at build time from @feugene/granularity 0.41.0