srcdev-nuxt-components 9.1.52 → 9.1.54

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.
@@ -8,7 +8,29 @@
8
8
  "Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:3000/)",
9
9
  "Bash(kill %1)",
10
10
  "Bash(xargs kill -9)",
11
- "Edit(/.claude/skills/components/**)"
11
+ "Edit(/.claude/skills/components/**)",
12
+ "Bash(command -v nvm)",
13
+ "Bash(command -v fnm)",
14
+ "Bash(command -v volta)",
15
+ "Bash(npm --version)",
16
+ "Bash(python3 -c ' *)",
17
+ "Bash(node -e ' *)",
18
+ "Bash(/usr/local/bin/node -e \"...\")",
19
+ "Bash(which node *)",
20
+ "Read(//usr/local/bin/**)",
21
+ "Read(//Users/simoncornforth/.nvm/versions/**)",
22
+ "Read(//opt/homebrew/**)",
23
+ "Read(//usr/**)",
24
+ "Bash(/usr/local/Cellar/node@24/24.16.0/bin/node -e ' *)",
25
+ "Bash(/usr/local/Cellar/node@24/24.16.0/bin/node --version)",
26
+ "Bash(/usr/local/Cellar/node@24/24.16.0/bin/npm --version)",
27
+ "Bash(git -C /Users/simoncornforth/websites/instepreflexology log --oneline -3)",
28
+ "Bash(git -C /Users/simoncornforth/websites/instepreflexology add package-lock.json .nvmrc)",
29
+ "Bash(git -C /Users/simoncornforth/websites/instepreflexology commit -m ' *)",
30
+ "Bash(git -C /Users/simoncornforth/websites/instepreflexology push)"
31
+ ],
32
+ "additionalDirectories": [
33
+ "/Users/simoncornforth/websites/instepreflexology"
12
34
  ]
13
35
  }
14
36
  }
@@ -41,6 +41,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
41
41
  ├── component-inline-action-button.md — InputButtonCore variant="inline" pattern for buttons embedded in custom input wrappers
42
42
  ├── vue-video-autoplay.md — autoplay on client-side navigation: use <source> child (not :src on <video>), :key, and explicit v.load()
43
43
  ├── icon-sets.md — icon set packages required by layer components, FOUC prevention, component→package map
44
+ ├── vercel-node-version.md — .nvmrc pinned to Node 24 is required; without it Vercel uses npm 10 which crashes on versionless optional stubs
44
45
  ├── robots-env-aware.md — @nuxtjs/robots: allow crawling on prod domain only, block on preview/staging via env var
45
46
  ├── new-app-scaffold.md — scaffold a new Nuxt consumer app extending this layer (package.json, nuxt.config, app structure, CLAUDE.md)
46
47
  ├── qa-panel.md — collapsible dev-only panel for toggling component props live on a page (demo pages and consuming apps)
@@ -0,0 +1,48 @@
1
+ # Vercel Node Version — .nvmrc Required
2
+
3
+ ## Overview
4
+
5
+ Every project deploying to Vercel must have a `.nvmrc` file pinned to Node 24. Without it, Vercel defaults to Node 22 (npm 10), which crashes with `npm error Invalid Version:` on platform-specific optional packages that npm 11 (Node 24) handles gracefully.
6
+
7
+ ## The problem
8
+
9
+ When `npm install` runs on macOS with Node 24, it writes stub entries into `package-lock.json` for platform-specific optional packages that don't apply to the current OS. For example:
10
+
11
+ ```json
12
+ "node_modules/oxc-transform/node_modules/@oxc-transform/binding-linux-arm-gnueabihf": {
13
+ "optional": true
14
+ }
15
+ ```
16
+
17
+ This stub has no `version` field. npm 11 (Node 24) skips it silently. npm 10 (Node 22) calls `semver.valid()` on the empty version string and throws:
18
+
19
+ ```
20
+ npm error Invalid Version:
21
+ npm error A complete log of this run can be found in: ...
22
+ Error: Command "npm install" exited with 1
23
+ ```
24
+
25
+ The build fails even though the package is optional and not needed on Vercel's Linux x86_64 runtime.
26
+
27
+ ## Fix
28
+
29
+ ### 1. Add `.nvmrc` to the project root
30
+
31
+ ```
32
+ 24
33
+ ```
34
+
35
+ Vercel reads `.nvmrc` and provisions Node 24 (npm 11), which handles the versionless stubs without error.
36
+
37
+ ### 2. Verify the file exists before every deployment
38
+
39
+ If `.nvmrc` is ever accidentally deleted, recreate it immediately. This applies to:
40
+ - `nuxt-components` (the layer)
41
+ - Every consumer app (`instepreflexology`, `luxury-locs-by-natasha-nuxt3`, etc.)
42
+
43
+ ## Notes
44
+
45
+ - The specific stub that first surfaced this was `@oxc-transform/binding-linux-arm-gnueabihf` — a Linux ARM native binary written as a versionless placeholder on macOS.
46
+ - The build works locally on Node 24 regardless, so the failure is silent until Vercel runs.
47
+ - Vercel also respects the `engines.node` field in `package.json`, but `.nvmrc` is simpler and doesn't require a valid semver range.
48
+ - Do **not** attempt to fix by deleting stubs from `package-lock.json` alone — they reappear on the next `npm install`. The `.nvmrc` file is the durable fix.
@@ -46,9 +46,21 @@ const { headingId, ariaLabelledby } = useAriaLabelledById(props.tag);
46
46
  --_content-max-width: var(--page-row-content-max-width, 1064px);
47
47
  --_inset-content-max-width: var(--page-row-inset-content-max-width, 840px);
48
48
 
49
- --full: minmax(var(--_minimum-content-padding), 1fr);
49
+ /* Minimum gutter for the outer (full) track: 1rem on narrow viewports, dissolves to 0
50
+ once the viewport exceeds --_content-max-width + 2 × --_minimum-content-padding,
51
+ at which point 1fr already provides centering space with no forced floor needed. */
52
+ --_full-track-min: min(
53
+ var(--_minimum-content-padding),
54
+ max(0px, calc((var(--_content-max-width) + var(--_minimum-content-padding) * 2 - 100%) / 2))
55
+ );
56
+
57
+ --full: minmax(var(--_full-track-min), 1fr);
50
58
  --popout: minmax(0, calc((var(--_popout-max-width) - var(--_content-max-width)) * 0.5));
51
- --content: minmax(0, calc((var(--_content-max-width) - var(--_inset-content-max-width)) * 0.5));
59
+ --content: clamp(
60
+ 0px,
61
+ calc((100% - var(--_minimum-content-padding) * 2 - var(--_inset-content-max-width)) * 0.5),
62
+ calc((var(--_content-max-width) - var(--_inset-content-max-width)) * 0.5)
63
+ );
52
64
  --inset-content: min(var(--_inset-content-max-width), 100% - var(--_minimum-content-padding) * 2);
53
65
 
54
66
  display: grid;
@@ -83,16 +95,30 @@ const { headingId, ariaLabelledby } = useAriaLabelledById(props.tag);
83
95
  * its own children span full width, not just control placement when nested.
84
96
  * Specificity (0,2,0) — nested .page-row variant overrides below win at (0,3,0).
85
97
  */
86
- .page-row.full > * { grid-column: full; }
87
- .page-row.popout > * { grid-column: popout; }
88
- .page-row.inset-content > * { grid-column: inset-content; }
98
+ .page-row.full > * {
99
+ grid-column: full;
100
+ }
101
+ .page-row.popout > * {
102
+ grid-column: popout;
103
+ }
104
+ .page-row.inset-content > * {
105
+ grid-column: inset-content;
106
+ }
89
107
 
90
108
  /* Nested page-rows: symmetric placement by variant class */
91
109
  .page-row > .page-row {
92
- &.full { grid-column: full; }
93
- &.popout { grid-column: popout; }
94
- &.content { grid-column: content; }
95
- &.inset-content { grid-column: inset-content; }
110
+ &.full {
111
+ grid-column: full;
112
+ }
113
+ &.popout {
114
+ grid-column: popout;
115
+ }
116
+ &.content {
117
+ grid-column: content;
118
+ }
119
+ &.inset-content {
120
+ grid-column: inset-content;
121
+ }
96
122
  }
97
123
 
98
124
  /*
@@ -101,15 +127,27 @@ const { headingId, ariaLabelledby } = useAriaLabelledById(props.tag);
101
127
  * Specificity (0,4,0) beats the symmetric rules above at (0,3,0).
102
128
  */
103
129
  .page-row > .page-row[data-align="start"] {
104
- &.popout { grid-column: full-start / popout-end; }
105
- &.content { grid-column: full-start / content-end; }
106
- &.inset-content { grid-column: full-start / inset-content-end; }
130
+ &.popout {
131
+ grid-column: full-start / popout-end;
132
+ }
133
+ &.content {
134
+ grid-column: full-start / content-end;
135
+ }
136
+ &.inset-content {
137
+ grid-column: full-start / inset-content-end;
138
+ }
107
139
  }
108
140
 
109
141
  .page-row > .page-row[data-align="end"] {
110
- &.popout { grid-column: popout-start / full-end; }
111
- &.content { grid-column: content-start / full-end; }
112
- &.inset-content { grid-column: inset-content-start / full-end; }
142
+ &.popout {
143
+ grid-column: popout-start / full-end;
144
+ }
145
+ &.content {
146
+ grid-column: content-start / full-end;
147
+ }
148
+ &.inset-content {
149
+ grid-column: inset-content-start / full-end;
150
+ }
113
151
  }
114
152
  }
115
153
  </style>
package/package.json CHANGED
@@ -1,20 +1,16 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.1.52",
4
+ "version": "9.1.54",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",
8
- "engines": {
9
- "node": ">=20.19.0 <23",
10
- "npm": ">=10.0.0"
11
- },
12
8
  "scripts": {
13
9
  "clean": "rm -rf .nuxt && rm -rf .output",
14
10
  "cleanall": "rm -rf node_modules && rm -rf .nuxt && rm -rf .output && rm package-lock.json",
15
11
  "reinstall": "rm -rf node_modules && npm install",
16
12
  "cleaninstall": "npm run clean && npm run reinstall",
17
- "dev": "SRCDEV_STANDALONE=true nuxi dev",
13
+ "dev": "SRCDEV_STANDALONE=true nuxt dev",
18
14
  "build": "SRCDEV_STANDALONE=true nuxt build",
19
15
  "generate": "SRCDEV_STANDALONE=true nuxt generate",
20
16
  "preview": "SRCDEV_STANDALONE=true nuxt preview",