Tulip Logo IconTulip

Package Layers

Tulip packages are grouped by architectural role, not just by package size.

Tulip packages are grouped by architectural role, not just by package size.

Atoms

Atoms are foundational packages that provide plain, reusable primitives. They have a single responsibility, avoid product-specific behavior, and do not care which Tulip module consumes them.

Atoms are allowed to be boring. They should be stable, reusable, and generic.

Current Atoms

  • @tulip-systems/core
  • @tulip-systems/ui
  • @tulip-systems/query
  • @tulip-systems/storage
  • @tulip-systems/auth

Modules

Modules are higher-level capability packages. They compose atoms into opinionated workflows, product surfaces, or domain features.

A module may be split into multiple packages when it needs separate providers, adapters, or integrations.

Current Modules

  • @tulip-systems/app
  • @tulip-systems/ai
  • @tulip-systems/commands
  • @tulip-systems/data-tables
  • @tulip-systems/drive
  • @tulip-systems/editor
  • @tulip-systems/inline

Package Families

Some modules are represented by a family of packages that share a prefix.

Drive

  • @tulip-systems/drive
  • @tulip-systems/drive-local
  • @tulip-systems/drive-google

Editor

  • @tulip-systems/editor
  • @tulip-systems/editor-storage

Dependency Direction

Preferred dependency direction:

tooling -> modules -> atoms

Rules:

  • Atoms should not depend on modules.
  • Modules may depend on atoms.
  • Modules should avoid depending on unrelated modules unless they are intentionally composing them.
  • Provider and adapter packages should stay inside the module family they support.

Example

If we build a notification system:

  • events would be an atom.
  • notifications would be a module.
  • notifications-email would be a provider or facet of the notifications module.

On this page