Skip to content

Expose published stylesheets via package.json exports#1105

Open
shved270189 wants to merge 2 commits into
basecamp:mainfrom
fetlife:export-stylesheets-via-package-exports
Open

Expose published stylesheets via package.json exports#1105
shved270189 wants to merge 2 commits into
basecamp:mainfrom
fetlife:export-stylesheets-via-package-exports

Conversation

@shved270189

Copy link
Copy Markdown

Problem

The published CSS files (dist/stylesheets/lexxy.css, lexxy-content.css, lexxy-editor.css, lexxy-variables.css) aren't reachable through package.json exports — the exports map 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 throws ERR_PACKAGE_PATH_NOT_EXPORTED — even though the file physically ships in the package. So importing the CSS from a bundler fails:

@import "@37signals/lexxy/dist/stylesheets/lexxy-content.css";
/* ERR_PACKAGE_PATH_NOT_EXPORTED: ... is not exported under the condition "style" */

The CDN example in the docs (unpkg.com/.../dist/stylesheets/lexxy.css) still works only because a CDN is a plain file server and ignores exports. 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:

@import "@37signals/lexxy/lexxy-content.css";

Changes

Add exports entries for the stylesheets behind clean subpaths:

"./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/*"
  • Each stylesheet gets a clean subpath (@37signals/lexxy/lexxy.css, etc.).
  • The ./dist/stylesheets/* passthrough keeps existing deep-path imports (e.g. the documented CDN path) resolving, so this is backward compatible.
  • The existing . and ./helpers JS exports are unchanged.
  • Theming/customization is unaffected — consumers still override via their own variables.

The subpaths are plain string mappings; since they already end in .css, bundlers resolve them via the default condition without needing style/default branches.

Docs

Added a "With a JavaScript bundler" section to docs/css-setup.md showing the bundler import and the four exposed subpaths.

Verification

  • yarn build:npm emits all four dist/stylesheets/*.css files — every export target points to a real file.
  • Symlinked the built package into a temp consumer's node_modules and resolved each specifier with Node's import.meta.resolve (the same exports resolution bundlers use). All four new CSS subpaths and the deep path resolve; before this change they threw ERR_PACKAGE_PATH_NOT_EXPORTED.
  • yarn lint is clean.

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.
Copilot AI review requested due to automatic review settings June 10, 2026 13:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread docs/css-setup.md
Comment on lines +28 to +33
| 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 |

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread package.json Outdated
Comment on lines +10 to +14
"./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/*"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants