Expose published stylesheets via package.json exports#1105
Conversation
The exports field only declared JS entry points, so the stylesheets in dist/stylesheets were unreachable through bundlers that honor exports encapsulation (Vite, esbuild, webpack). Importing "@37signals/lexxy/dist/stylesheets/lexxy.css" from such a bundler fails with ERR_PACKAGE_PATH_NOT_EXPORTED even though the file ships in the package. Add clean subpath exports for the four stylesheets plus a dist/stylesheets/* passthrough so existing deep-path imports keep resolving, and document the bundler import in the CSS setup guide.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Expose Lexxy’s compiled CSS via npm package subpath exports and document how to import those styles when using JS/CSS bundlers.
Changes:
- Add multiple CSS subpath exports in
package.json(e.g.,./lexxy.css,./lexxy-editor.css). - Document bundler usage and available stylesheet entrypoints in
docs/css-setup.md.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| package.json | Exposes compiled CSS files (and a wildcard) via exports for bundler-friendly imports. |
| docs/css-setup.md | Adds instructions + a table of supported CSS import subpaths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | Import | Contents | | ||
| |-------------------------------------------|-----------------------------------------------------| | ||
| | `@37signals/lexxy/lexxy.css` | Everything (editor + rendered content) | | ||
| | `@37signals/lexxy/lexxy-content.css` | Rendered Action Text content only | | ||
| | `@37signals/lexxy/lexxy-editor.css` | Editor chrome only | | ||
| | `@37signals/lexxy/lexxy-variables.css` | CSS variables only, for theming | |
There was a problem hiding this comment.
The table uses single leading pipes (| Import | Contents |), which is valid GitHub-Flavored Markdown and renders correctly in the Files view — there are no || sequences in the source. Leaving as-is.
| "./lexxy.css": "./dist/stylesheets/lexxy.css", | ||
| "./lexxy-content.css": "./dist/stylesheets/lexxy-content.css", | ||
| "./lexxy-editor.css": "./dist/stylesheets/lexxy-editor.css", | ||
| "./lexxy-variables.css": "./dist/stylesheets/lexxy-variables.css", | ||
| "./dist/stylesheets/*": "./dist/stylesheets/*" |
There was a problem hiding this comment.
Good call — dropped the ./dist/stylesheets/* wildcard. It was only there as backward-compat insurance, but it protected nothing real: before this PR the deep path already threw ERR_PACKAGE_PATH_NOT_EXPORTED under any bundler (only . and ./helpers were exported), so there were no existing bundler consumers, and the documented unpkg/CDN usage bypasses exports entirely (raw file server). The four explicit *.css subpaths cover every documented entrypoint, so removing the wildcard keeps dist/ out of the public API surface.
Keep only the four explicit stylesheet subpaths. The wildcard exposed the internal dist/ layout as public API without protecting any real consumer: bundlers already blocked the deep path before this change, and the documented CDN/unpkg usage bypasses exports entirely.
Problem
The published CSS files (
dist/stylesheets/lexxy.css,lexxy-content.css,lexxy-editor.css,lexxy-variables.css) aren't reachable throughpackage.jsonexports — theexportsmap only declares the JS entry points (.and./helpers).When a package defines
exports, it becomes an encapsulation boundary: Node and any bundler that honors it (Vite, esbuild, webpack) will only resolve the listed subpaths. Everything else throwsERR_PACKAGE_PATH_NOT_EXPORTED— even though the file physically ships in the package. So importing the CSS from a bundler fails:The CDN example in the docs (
unpkg.com/.../dist/stylesheets/lexxy.css) still works only because a CDN is a plain file server and ignoresexports. Bundlers don't.Use case
Integrating Lexxy in a Rails app on Vite + Tailwind v4, importing the upstream CSS from npm rather than vendoring it:
Changes
Add
exportsentries for the stylesheets behind clean subpaths:@37signals/lexxy/lexxy.css, etc.)../dist/stylesheets/*passthrough keeps existing deep-path imports (e.g. the documented CDN path) resolving, so this is backward compatible..and./helpersJS exports are unchanged.The subpaths are plain string mappings; since they already end in
.css, bundlers resolve them via thedefaultcondition without needingstyle/defaultbranches.Docs
Added a "With a JavaScript bundler" section to
docs/css-setup.mdshowing the bundler import and the four exposed subpaths.Verification
yarn build:npmemits all fourdist/stylesheets/*.cssfiles — every export target points to a real file.node_modulesand resolved each specifier with Node'simport.meta.resolve(the same exports resolution bundlers use). All four new CSS subpaths and the deep path resolve; before this change they threwERR_PACKAGE_PATH_NOT_EXPORTED.yarn lintis clean.