Fixed postcss plugin resolution for consumers of the design system config - #29185
Conversation
…nfig - admin-x-settings re-exports the design system's postcss.config.cjs, but the config named its plugins as strings. postcss-load-config resolves string plugin names relative to the searchPath (the consuming package), not the file that declared them, so it looked for postcss-import, @tailwindcss/postcss and autoprefixer under apps/admin-x-settings, which does not declare them. Under pnpm's strict isolation they are not linked there, so the lookup failed with "Loading PostCSS Plugin failed: Cannot find module 'postcss-import'". - Requiring the plugins in the config file itself anchors resolution to the design system, which does declare all three. The plugin list is now passed as instances, so no string resolution happens at the consumer at all. - Preferred over adding postcss-import et al as devDependencies of every consumer: that papers over the resolution bug and would have to be repeated for each new package that reuses this config. - Preferred over deleting the config: it is not vestigial. The design system and admin-x-settings still build standalone bundles through postcss, and the pipeline expands `@import 'tailwindcss/utilities.css'` into ~470kB of CSS. Dropping it would silently strip every utility class from those bundles. - Verified the emitted CSS is unchanged: the postcss product is byte-identical and admin-x-settings/dist is unchanged across all 31 files.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe PostCSS configuration file for admin-x-design-system was modified to change how plugins are declared. Instead of an object mapping plugin names to configuration, the file now requires each plugin (postcss-import, 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx run @tryghost/admin-x-settings:test:acceptance |
✅ Succeeded | 9m 22s | View ↗ |
nx run-many --target=build --projects=tag:publi... |
✅ Succeeded | 1s | View ↗ |
nx run-many -t test:unit -p @tryghost/admin-x-d... |
✅ Succeeded | 2m 41s | View ↗ |
nx run ghost-admin:test |
✅ Succeeded | 2m 39s | View ↗ |
nx run-many -t lint -p @tryghost/admin-x-design... |
✅ Succeeded | 1m 42s | View ↗ |
nx run @tryghost/admin:build |
✅ Succeeded | 8s | View ↗ |
nx run @tryghost/activitypub:test:acceptance |
✅ Succeeded | 45s | View ↗ |
nx run ghost:build:assets |
✅ Succeeded | 2s | View ↗ |
nx run ghost:build:tsc |
✅ Succeeded | 7s | View ↗ |
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗
☁️ Nx Cloud last updated this comment at 2026-07-08 20:32:25 UTC

apps/admin-x-settings/postcss.config.cjsre-exports the design system's config. That config named its plugins as strings, andpostcss-load-configresolves string plugin names relative to the searchPath — the directory the consuming build discovered a config in — not the file that declared the list.So the plugin names resolve from
apps/admin-x-settings, which declares none ofpostcss-import,@tailwindcss/postcssorautoprefixer. Under pnpm's strict isolation they are not linked there, and none of the three resolve from that directory.Why now, if the build is green?
It is currently masked. The plugins genuinely cannot be resolved from
admin-x-settings— that is verifiable with arequire.resolveprobe from that directory — so today's successful build depends on the loader not using the consumer as its anchor. That is one loader change away from breaking, and it broke in a real working tree.The fix
require()the three plugins insideapps/admin-x-design-system/postcss.config.cjsand pass instances rather than names, so resolution is anchored to the package that declares them. No string resolution happens at the consumer at all.postcss(fn)auto-invokes factories carrying.postcss === true, which all three do, sopostcssImport()is exactly equivalent to'postcss-import': {}.Alternatives rejected:
postcss-importet al as devDependencies of each consumer — papers over the resolution bug and has to be repeated for every package that reuses the config.apps/admin's@tailwindcss/vitesetup;admin-x-settingsstill builds a standalone bundle throughadminXViteConfig, which has no Tailwind plugin. Itssrc/styles/index.cssdoes@import 'tailwindcss/utilities.css', and postcss expands that into ~470 kB of real utilities. Deleting the config would silently strip every utility class from that bundle.Verification
pnpm --filter @tryghost/admin-x-settings build— exit 0pnpm --filter @tryghost/admin-x-settings lintandpnpm --filter @tryghost/admin-x-design-system lint— exit 0NX_NO_CLOUD=true pnpm nx build @tryghost/admin --skip-nx-cache— exit 0, all 15 dependent tasks genuinely executed. (The plainnx reset && nx buildrun replayed 9/16 tasks from Nx Cloud's remote cache, which would have masked a failure.)apps/admin-x-settings/distmatch before and after.Same three plugins, same order, same empty options — only where they resolve from has changed.