Architecture decisions

Scope strategy

motif publishes thirteen packages under the @usemotif/* scope and one unscoped meta package, usemotif. It did not start there — the npm namespace changed twice, and this record is the history.

Updated 4 days agoEdit on GitHubWeb & native

Status

Accepted — amended twice. The current scope is @usemotif/*; the earlier states are recorded below because consumers still migrating across them need the history.

Context

The library was planned as motif-js, with packages under the @motif-js/* scope and a cross-platform aggregator package named @motif-js/react. Two problems surfaced after the first releases.

First, the aggregator's name was wrong. @motif-js/react was a platform-detecting re-export — it forwarded to the web or native bindings — but the name "react" implied a web coupling that did not exist, and it occupied a name users would expect to mean the DOM bindings.

Second, the meta package needed a short, unscoped name. The plan was to publish it as the unscoped motif-js. npm blocked the name at publish time — too similar to an existing motif.js package.

Decision

The scope arrived at @usemotif/* through two renames, each shipped as a major version with a codemod.

  • v2 — promote the aggregator. The cross-platform aggregator moved to the unscoped usemotif package (the pivot away from the blocked motif-js name). The npm name @motif-js/react was freed to mean the DOM bindings, which was the expected meaning. This left a split brand: scoped packages under @motif-js/*, the meta package unscoped as usemotif.
  • v3 — consolidate the scope. The split brand was a workaround, not a design. v3 moved every scoped package from @motif-js/* to @usemotif/*, keeping the meta package as usemotif. One library, one namespace.

Each rename ships a @usemotif/migrate codemod — rename-v2, rename-v3 — that rewrites import specifiers, and a migration guide. No public API moved in either rename; both were packaging changes.

Consequences

  • The current state is coherent: @usemotif/* for the thirteen siblings, usemotif for the meta package, one brand.
  • The legacy @motif-js/* packages stay on npm, frozen, carrying deprecation notices that point at the migration guides. Existing installs keep working.
  • The library carries migration tooling and two version-rename guides — v1 → v2 and v2 → v3 — as permanent fixtures. A rename is cheap to run and expensive to document away, so the documents stay.
  • The lesson is recorded so it is not repeated: check npm name availability before committing a public name, not after the first publish.