@plutocms/core 0.43.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.44.0](https://github.com/plutocms/pluto/compare/v0.43.0...v0.44.0) (2026-11-01)
5
+
6
+
7
+ ### Features
8
+
9
+ * import the Pluto CSS by name: @plutocms/css and @plutocms/css/site ([#336](https://github.com/plutocms/pluto/issues/336)) ([4d4b404](https://github.com/plutocms/pluto/commit/4d4b404070f186167e020bdcadf4e4df5d0948ef))
10
+
4
11
  ## [0.43.0](https://github.com/plutocms/pluto/compare/v0.42.0...v0.43.0) (2026-11-01)
5
12
 
6
13
 
package/FEATURES.md CHANGED
@@ -51,7 +51,7 @@ policies shared by every project here.
51
51
  - Pluto UI tokens: the official palette (tholin, haze, heart, kuiper) and fonts (Public Sans,
52
52
  Fredoka) in `@theme`, for every app. The admin theme is generated from them.
53
53
  @.claude/skills/admin-theme/SKILL.md
54
- - Pluto site theme: the opt-in `#build/pluto-site.css` gives a public site the look of the Pluto
54
+ - Pluto site theme: the opt-in `@import '@plutocms/css/site'` gives a public site the look of the Pluto
55
55
  docs (the fonts, the shades of the app colors, a deep-space dark mode, `pluto-sky`,
56
56
  `pluto-site-header`). The official templates use it.
57
57
  @.claude/skills/single-tailwind-build/SKILL.md
@@ -67,7 +67,7 @@ policies shared by every project here.
67
67
  - Settings pages: `/admin/settings` is a section with tabs. A layer adds a tab with a `settingsPages` entry and a page file at `pages/admin/settings/<x>.vue`. The tabs show with 2 or more pages, the sidebar and the command palette list them, and a tab can need a capability (`'*'` is admin only). The capability picker groups by layer. @.claude/skills/extension-registry/SKILL.md
68
68
  - Mail: a mail driver contract (`sendPlutoMail`, `registerMailDriver`) with Resend, dev (console and Mailpit) and none drivers, plain-TypeScript email templates (test, invite) translated by a server translator, and a guided `Settings > Email` page (admin only) that checks the key, adds and verifies a domain, and tests the setup. Secrets stay in the environment. @.claude/skills/mail/SKILL.md
69
69
  - Single Tailwind build: the app owns the only Tailwind build. The pluto-css module generates
70
- `#build/pluto.css` from each layer's `pluto-layer.css`, adds a fallback entry, and warns
70
+ `#build/pluto.css` from each layer's `pluto-layer.css` (the app imports it as `@plutocms/css`), adds a fallback entry, and warns
71
71
  about a wrong CSS setup. @.claude/skills/single-tailwind-build/SKILL.md
72
72
  - Git CMS: a standalone CMS with Markdown posts in a Git repo. Out of the box it publishes to the
73
73
  local Git repo (dev only: each save is a local commit, `commit.local`); a GitHub App publishes
@@ -5,9 +5,9 @@
5
5
  *
6
6
  * @import 'tailwindcss';
7
7
  * @import '@nuxt/ui';
8
- * @import '#build/pluto.css';
8
+ * @import '@plutocms/css';
9
9
  *
10
- * `#build/pluto.css` imports this file (and the same file of every other
10
+ * `@plutocms/css` (core generates it) imports this file (and the same file of every other
11
11
  * Pluto layer). Rules for this file:
12
12
  * - Do not import tailwindcss or @nuxt/ui here.
13
13
  * - Use only @theme, @custom-variant, @utility, unlayered rules, and
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * @import 'tailwindcss';
6
6
  * @import '@nuxt/ui';
7
- * @import '#build/pluto.css';
8
- * @import '#build/pluto-site.css';
7
+ * @import '@plutocms/css';
8
+ * @import '@plutocms/css/site';
9
9
  *
10
10
  * It does not choose the colors. Set them in app.config.ts, for example
11
11
  * `ui.colors: { primary: 'tholin', secondary: 'haze', neutral: 'kuiper' }`. The rules below use
@@ -5,6 +5,12 @@ import { dirname, isAbsolute, join, relative, resolve } from 'node:path'
5
5
  /** A layer's own CSS file, by convention. See the single-tailwind-build skill. */
6
6
  export const LAYER_CSS_FILE = 'assets/css/pluto-layer.css'
7
7
 
8
+ /** The name that an app's CSS entry imports: an alias of `#build/pluto.css`. */
9
+ export const PLUTO_CSS_IMPORT = '@plutocms/css'
10
+
11
+ /** The opt-in Pluto site theme: an alias of `#build/pluto-site.css`. */
12
+ export const PLUTO_SITE_CSS_IMPORT = '@plutocms/css/site'
13
+
8
14
  function toPosix(path: string): string {
9
15
  return path.replaceAll('\\', '/')
10
16
  }
@@ -41,7 +47,8 @@ export function renderPlutoCss(files: string[], buildDir: string): string {
41
47
 
42
48
  /**
43
49
  * Renders `#build/pluto-site.css`: the opt-in Pluto site theme of core
44
- * (app/assets/css/pluto-site-theme.css). An app imports it after `#build/pluto.css`.
50
+ * (app/assets/css/pluto-site-theme.css). An app imports it (`@plutocms/css/site`)
51
+ * after `@plutocms/css`.
45
52
  */
46
53
  export function renderPlutoSiteCss(file: string, buildDir: string): string {
47
54
  return [
@@ -70,7 +77,7 @@ export function renderPlutoEntryCss(): string {
70
77
  '/* Fallback Tailwind entry: the app has no CSS entry that imports Tailwind. */',
71
78
  '@import "tailwindcss";',
72
79
  '@import "@nuxt/ui";',
73
- '@import "#build/pluto.css";',
80
+ `@import "${PLUTO_CSS_IMPORT}";`,
74
81
  '',
75
82
  ].join('\n')
76
83
  }
@@ -106,7 +113,7 @@ export interface CssEntryInfo {
106
113
  tailwind: boolean
107
114
  /** It imports `@nuxt/ui`. */
108
115
  nuxtUi: boolean
109
- /** It imports `#build/pluto.css`. */
116
+ /** It imports `@plutocms/css` (or the generated `#build/pluto.css` itself). */
110
117
  plutoCss: boolean
111
118
  }
112
119
 
@@ -145,8 +152,8 @@ export function analyzeCssEntry(
145
152
  } else if (specifier === '@nuxt/ui') {
146
153
  info.nuxtUi = true
147
154
  } else if (
148
- /(?:^|\/)pluto\.css$/.test(specifier) &&
149
- specifier.includes('#build')
155
+ specifier === PLUTO_CSS_IMPORT ||
156
+ (/(?:^|\/)pluto\.css$/.test(specifier) && specifier.includes('#build'))
150
157
  ) {
151
158
  info.plutoCss = true
152
159
  } else {
@@ -188,8 +195,7 @@ export function checkCssSetup(
188
195
  ): CssSetupReport {
189
196
  const warnings: string[] = []
190
197
  const tailwindEntries = entries.filter((entry) => entry.tailwind)
191
- const snippet =
192
- " @import 'tailwindcss';\n @import '@nuxt/ui';\n @import '#build/pluto.css';"
198
+ const snippet = ` @import 'tailwindcss';\n @import '@nuxt/ui';\n @import '${PLUTO_CSS_IMPORT}';`
193
199
 
194
200
  if (tailwindEntries.length === 0) {
195
201
  return { injectFallback: true, warnings }
@@ -214,7 +220,7 @@ export function checkCssSetup(
214
220
 
215
221
  if (!tailwindEntries.some((entry) => entry.plutoCss)) {
216
222
  warnings.push(
217
- `No CSS entry imports #build/pluto.css. The admin theme and layer tokens are missing. Start the app's CSS entry with:\n${snippet}`
223
+ `No CSS entry imports ${PLUTO_CSS_IMPORT}. The admin theme and layer tokens are missing. Start the app's CSS entry with:\n${snippet}`
218
224
  )
219
225
  }
220
226
 
@@ -1,4 +1,5 @@
1
1
  import { existsSync, readFileSync } from 'node:fs'
2
+ import { join } from 'node:path'
2
3
  import { fileURLToPath } from 'node:url'
3
4
  import {
4
5
  addTemplate,
@@ -11,6 +12,8 @@ import {
11
12
  analyzeCssEntry,
12
13
  checkCssSetup,
13
14
  findLayerCssFiles,
15
+ PLUTO_CSS_IMPORT,
16
+ PLUTO_SITE_CSS_IMPORT,
14
17
  renderPlutoCss,
15
18
  renderPlutoEntryCss,
16
19
  renderPlutoSiteCss,
@@ -27,13 +30,17 @@ export interface PlutoCssOptions {
27
30
  *
28
31
  * @import 'tailwindcss';
29
32
  * @import '@nuxt/ui';
30
- * @import '#build/pluto.css';
33
+ * @import '@plutocms/css';
31
34
  *
32
- * - `#build/pluto-site.css` (opt-in) imports the Pluto site theme of core
33
- * (app/assets/css/pluto-site-theme.css): the look of the Pluto docs for a site.
34
- * - `#build/pluto.css` imports each layer's app/assets/css/pluto-layer.css
35
- * (tokens, the admin theme). Nuxt UI already adds `@source` for every
36
- * layer's app/ dir, so this file adds no sources.
35
+ * - `@plutocms/css` is an alias of the generated `#build/pluto.css`. It imports
36
+ * each layer's app/assets/css/pluto-layer.css (tokens, the admin theme), so one
37
+ * import covers every layer of the app. Nuxt UI already adds `@source` for
38
+ * every layer's app/ dir, so this file adds no sources.
39
+ * - `@plutocms/css/site` (opt-in) is an alias of `#build/pluto-site.css`: the
40
+ * Pluto site theme of core (app/assets/css/pluto-site-theme.css), the look of
41
+ * the Pluto docs for a site.
42
+ * - The names are aliases, not npm packages, so they resolve with every package
43
+ * manager, also when the app installs only an outer layer.
37
44
  * - An app with no Tailwind entry (a layer repo run on its own, or an app
38
45
  * with no CSS) gets the fallback entry `#build/pluto-entry.css`.
39
46
  * - The module warns about a layer that registers its own Tailwind build,
@@ -59,7 +66,7 @@ export default defineNuxtModule<PlutoCssOptions>({
59
66
  })
60
67
 
61
68
  // The opt-in site theme of core. An app that wants the look of the Pluto
62
- // docs imports `#build/pluto-site.css` after `#build/pluto.css`.
69
+ // docs imports `@plutocms/css/site` after `@plutocms/css`.
63
70
  const siteTheme = fileURLToPath(
64
71
  new URL('../../app/assets/css/pluto-site-theme.css', import.meta.url)
65
72
  )
@@ -69,6 +76,18 @@ export default defineNuxtModule<PlutoCssOptions>({
69
76
  getContents: () => renderPlutoSiteCss(siteTheme, nuxt.options.buildDir),
70
77
  })
71
78
 
79
+ // The names that an app's CSS entry imports. Tailwind resolves `@import`
80
+ // through the Vite aliases. `/site` comes first: an alias also matches the
81
+ // paths under its name, so `@plutocms/css` would take `@plutocms/css/site`.
82
+ nuxt.options.alias[PLUTO_SITE_CSS_IMPORT] = join(
83
+ nuxt.options.buildDir,
84
+ 'pluto-site.css'
85
+ )
86
+ nuxt.options.alias[PLUTO_CSS_IMPORT] = join(
87
+ nuxt.options.buildDir,
88
+ 'pluto.css'
89
+ )
90
+
72
91
  addTemplate({
73
92
  filename: 'pluto-entry.css',
74
93
  write: true,
package/nuxt.config.ts CHANGED
@@ -43,7 +43,7 @@ export default defineNuxtConfig({
43
43
 
44
44
  // No `css` entry: the app's CSS entry owns the one Tailwind build, and
45
45
  // modules/pluto-css adds this layer's pluto-layer.css to it through
46
- // #build/pluto.css. See the single-tailwind-build skill.
46
+ // @plutocms/css (#build/pluto.css). See the single-tailwind-build skill.
47
47
 
48
48
  runtimeConfig: {
49
49
  // Private mail settings. Empty defaults on purpose: Nuxt reads
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plutocms/core",
3
3
  "type": "module",
4
- "version": "0.43.0",
4
+ "version": "0.44.0",
5
5
  "description": "The base layer every Pluto app extends: the admin, the content model, and the Git CMS",
6
6
  "author": "Victor Ribeiro",
7
7
  "license": "MIT",