Problem
The package advertises multiple consumption paths, but the current published shape is fragile:
package.json advertises ESM through module: "lib/index.js" and exports["."].import: "./lib/index.js".
- The emitted ESM files use extensionless or directory-style internal imports such as
./hellotext, ./core, ./api, and ./models, which do not resolve under Node ESM.
- The emitted CJS files live beside
.js siblings and also use extensionless internal require() calls, so Node can resolve the wrong sibling in some paths.
- The UMD bundle is useful for script tag/CDN usage, but it is currently named generically as
dist/hellotext.js, which can be confused with package ESM/CJS entries.
Reproduction checks
From this repo, the ESM path currently fails:
node --input-type=module -e "import('./lib/index.js')"
Observed failure:
ERR_MODULE_NOT_FOUND: Cannot find module './lib/hellotext' imported from './lib/index.js'
The advertised vanilla path is also affected:
node --input-type=module -e "import('./lib/vanilla.js')"
node -e "require('./lib/vanilla.cjs')"
Proposed improvements
-
Fix the actual ESM build by emitting extensionful internal imports, for example ./hellotext.js, ./core/index.js, ./api/index.js, and so on.
-
Fix the CJS build by making internal require() calls resolve .cjs siblings explicitly, or by moving CJS output into a separate folder where extensionless resolution cannot pick ESM-looking .js files.
-
Separate module formats cleanly. Prefer a structure such as dist/esm/*.js and dist/cjs/*.cjs, or use .mjs for ESM and .cjs for CommonJS.
-
Add packed-package smoke tests in CI. Run npm pack, install the generated tarball into a temporary project, then verify:
import '@hellotext/hellotext'
require('@hellotext/hellotext')
import '@hellotext/hellotext/vanilla'
require('@hellotext/hellotext/vanilla')
import '@hellotext/hellotext/styles/index.css' in a bundler fixture
- loading the UMD script path
-
Clarify browser vs Node entrypoints. The root entry starts Stimulus and writes to window, while @hellotext/hellotext/vanilla is documented as the non-browser path. Make that contract explicit in docs, exports, and tests.
-
Clean up the exports map. Keep root, ./vanilla, ./styles/index.css, and ./package.json, but make every condition precise: types, import, require, and possibly browser.
-
Reconsider the vague default export condition pointing at ./dist/hellotext.js. If the UMD bundle is a fallback only for specific consumers, document that intent or replace it with clearer conditions.
-
Align engines and Babel targets. package.json requires Node >=20, while the CJS Babel env targets Node 14. Pick the real support floor and compile accordingly.
-
Modernize the ESM output. The ESM build targets esmodules: true, but still applies transforms such as class transforms. The ESM output can likely be smaller, cleaner, and more tree-shakable.
-
Reduce package payload intentionally. npm pack --dry-run currently includes src, lib, and dist. Decide whether shipping src is intentional; if not, remove it from the files list.
-
Ship source maps for lib and dist/hellotext.js so downstream debugging works without relying on raw source being present in the package.
-
Make CSS side effects explicit. Keep CSS marked as side-effectful and ensure the docs and sideEffects field agree with the separate CSS import contract.
-
Improve type packaging. Add per-entry declaration coverage or declaration tests for @hellotext/hellotext, @hellotext/hellotext/vanilla, and @hellotext/hellotext/styles/index.css.
-
Make release packaging harder to stale. Use prepack or a release script that cleans, builds, packs, installs the tarball, smoke-tests it, and only then publishes.
-
Name CDN artifacts intentionally. Consider names like hellotext.umd.js and hellotext.umd.min.js so script-tag artifacts are clearly distinct from package module entrypoints.
Acceptance criteria
- The packed tarball works for both ESM import and CommonJS require from a fresh temporary consumer project.
@hellotext/hellotext/vanilla works in Node without touching browser globals.
- Bundler users can import the package and CSS using the documented paths.
- CDN/script-tag users still have a stable UMD artifact.
- CI verifies the packed package before release.
Problem
The package advertises multiple consumption paths, but the current published shape is fragile:
package.jsonadvertises ESM throughmodule: "lib/index.js"andexports["."].import: "./lib/index.js"../hellotext,./core,./api, and./models, which do not resolve under Node ESM..jssiblings and also use extensionless internalrequire()calls, so Node can resolve the wrong sibling in some paths.dist/hellotext.js, which can be confused with package ESM/CJS entries.Reproduction checks
From this repo, the ESM path currently fails:
node --input-type=module -e "import('./lib/index.js')"Observed failure:
The advertised vanilla path is also affected:
Proposed improvements
Fix the actual ESM build by emitting extensionful internal imports, for example
./hellotext.js,./core/index.js,./api/index.js, and so on.Fix the CJS build by making internal
require()calls resolve.cjssiblings explicitly, or by moving CJS output into a separate folder where extensionless resolution cannot pick ESM-looking.jsfiles.Separate module formats cleanly. Prefer a structure such as
dist/esm/*.jsanddist/cjs/*.cjs, or use.mjsfor ESM and.cjsfor CommonJS.Add packed-package smoke tests in CI. Run
npm pack, install the generated tarball into a temporary project, then verify:import '@hellotext/hellotext'require('@hellotext/hellotext')import '@hellotext/hellotext/vanilla'require('@hellotext/hellotext/vanilla')import '@hellotext/hellotext/styles/index.css'in a bundler fixtureClarify browser vs Node entrypoints. The root entry starts Stimulus and writes to
window, while@hellotext/hellotext/vanillais documented as the non-browser path. Make that contract explicit in docs, exports, and tests.Clean up the
exportsmap. Keep root,./vanilla,./styles/index.css, and./package.json, but make every condition precise:types,import,require, and possiblybrowser.Reconsider the vague
defaultexport condition pointing at./dist/hellotext.js. If the UMD bundle is a fallback only for specific consumers, document that intent or replace it with clearer conditions.Align
enginesand Babel targets.package.jsonrequires Node>=20, while the CJS Babel env targets Node 14. Pick the real support floor and compile accordingly.Modernize the ESM output. The ESM build targets
esmodules: true, but still applies transforms such as class transforms. The ESM output can likely be smaller, cleaner, and more tree-shakable.Reduce package payload intentionally.
npm pack --dry-runcurrently includessrc,lib, anddist. Decide whether shippingsrcis intentional; if not, remove it from thefileslist.Ship source maps for
libanddist/hellotext.jsso downstream debugging works without relying on raw source being present in the package.Make CSS side effects explicit. Keep CSS marked as side-effectful and ensure the docs and
sideEffectsfield agree with the separate CSS import contract.Improve type packaging. Add per-entry declaration coverage or declaration tests for
@hellotext/hellotext,@hellotext/hellotext/vanilla, and@hellotext/hellotext/styles/index.css.Make release packaging harder to stale. Use
prepackor a release script that cleans, builds, packs, installs the tarball, smoke-tests it, and only then publishes.Name CDN artifacts intentionally. Consider names like
hellotext.umd.jsandhellotext.umd.min.jsso script-tag artifacts are clearly distinct from package module entrypoints.Acceptance criteria
@hellotext/hellotext/vanillaworks in Node without touching browser globals.