kmcom-nuxt-layers 2.2.6 → 2.2.9

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.
Files changed (202) hide show
  1. package/docs/FEEDS.md +197 -0
  2. package/docs/LAYERS-FIXES.md +101 -0
  3. package/docs/MIGRATION.md +627 -0
  4. package/docs/feed-layer.md +374 -0
  5. package/docs/patch-picture-provider-type.md +52 -0
  6. package/docs/shaderGuide.md +2071 -0
  7. package/docs/types-architecture.md +234 -0
  8. package/layers/animations/app/components/Motion/CountUp.vue +1 -2
  9. package/layers/animations/app/components/Motion/Magnetic.vue +1 -2
  10. package/layers/animations/app/components/Motion/Marquee.vue +2 -5
  11. package/layers/animations/app/components/Motion/MarqueeText.vue +1 -2
  12. package/layers/animations/app/components/Motion/Tilt.vue +1 -2
  13. package/layers/animations/app/composables/useCountUp.ts +4 -1
  14. package/layers/animations/app/composables/useMagneticElement.ts +1 -3
  15. package/layers/animations/app/composables/useMarqueeCopies.ts +3 -3
  16. package/layers/animations/app/types/animations.ts +8 -0
  17. package/layers/animations/app/types/index.ts +1 -0
  18. package/layers/animations/package.json +4 -1
  19. package/layers/canvas/app/components/ShaderCanvas.vue +4 -4
  20. package/layers/canvas/app/composables/useRendererCapabilities.ts +19 -15
  21. package/layers/canvas/app/types/index.ts +1 -0
  22. package/layers/canvas/package.json +2 -1
  23. package/layers/canvas/tsconfig.json +2 -1
  24. package/layers/content/app/components/Blog/Card.vue +5 -5
  25. package/layers/content/app/components/Gallery/AmbientImage.vue +3 -3
  26. package/layers/content/app/components/Gallery/Card.vue +3 -3
  27. package/layers/content/app/components/NuxtContent/Detail.vue +5 -1
  28. package/layers/content/app/components/NuxtContent/Surround.vue +5 -3
  29. package/layers/content/app/components/NuxtContent/Toc.vue +1 -1
  30. package/layers/content/app/components/Portfolio/Card.vue +5 -5
  31. package/layers/content/app/components/content/Figure.vue +3 -3
  32. package/layers/content/app/types/index.ts +1 -0
  33. package/layers/content/package.json +2 -1
  34. package/layers/core/app/composables/useErrorLog.ts +9 -11
  35. package/layers/core/app/utils/helpers.ts +14 -12
  36. package/layers/core/nuxt.config.ts +1 -0
  37. package/layers/feeds/app/plugins/feed-head.ts +1 -2
  38. package/layers/feeds/package.json +2 -1
  39. package/layers/feeds/public/feed/style.css +256 -0
  40. package/layers/feeds/server/routes/feed/discovery.get.ts +1 -2
  41. package/layers/feeds/server/utils/content-adapter.ts +3 -2
  42. package/layers/forms/app/components/Form/Field.vue +4 -4
  43. package/layers/forms/app/types/index.ts +1 -0
  44. package/layers/forms/package.json +2 -1
  45. package/layers/layout/app/components/Layout/Grid/Item.vue +33 -19
  46. package/layers/layout/app/components/Layout/Page/Container.vue +11 -11
  47. package/layers/layout/app/components/Layout/Page/Header.vue +1 -1
  48. package/layers/layout/app/components/Layout/Page/index.vue +1 -1
  49. package/layers/layout/app/components/Layout/Section/Gallery.vue +6 -1
  50. package/layers/layout/app/components/Layout/Section/Title.vue +1 -1
  51. package/layers/layout/app/types/index.ts +1 -0
  52. package/layers/layout/package.json +2 -1
  53. package/layers/mailer/app/types/index.ts +1 -0
  54. package/layers/mailer/app/types/mailer.ts +25 -0
  55. package/layers/mailer/package.json +2 -1
  56. package/layers/motion/package.json +2 -1
  57. package/layers/navigation/app/components/Links/Group.vue +1 -0
  58. package/layers/navigation/app/components/Links/Named.vue +2 -0
  59. package/layers/navigation/app/types/index.ts +1 -0
  60. package/layers/navigation/package.json +4 -1
  61. package/layers/page-transitions/package.json +4 -1
  62. package/layers/routing/app/types/app-config.d.ts +3 -1
  63. package/layers/routing/app/types/index.ts +1 -0
  64. package/layers/routing/package.json +2 -1
  65. package/layers/scripts/app/composables/useGtm.ts +1 -1
  66. package/layers/scripts/app/types/index.ts +1 -0
  67. package/layers/scripts/app/types/scripts.ts +14 -0
  68. package/layers/scripts/package.json +2 -1
  69. package/layers/scroll/app/components/Motion/ScrollScene.vue +3 -1
  70. package/layers/scroll/app/composables/useScrollSteps.ts +2 -9
  71. package/layers/scroll/app/composables/useSectionProgress.ts +2 -1
  72. package/layers/scroll/app/plugins/locomotive-scroll.client.ts +1 -8
  73. package/layers/scroll/app/types/index.ts +1 -0
  74. package/layers/scroll/app/types/scroll.ts +32 -0
  75. package/layers/scroll/package.json +3 -0
  76. package/layers/seo/package.json +2 -1
  77. package/layers/shader/app/components/Material/Fresnel.client.vue +1 -1
  78. package/layers/shader/app/components/Material/Image.client.vue +1 -1
  79. package/layers/shader/app/components/Material/Node.client.vue +7 -7
  80. package/layers/shader/app/components/Material/Noise.client.vue +1 -1
  81. package/layers/shader/app/components/Node/Color.client.vue +17 -20
  82. package/layers/shader/app/components/Node/Noise.client.vue +31 -34
  83. package/layers/shader/app/components/Pipeline/Aurora.client.vue +4 -8
  84. package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +8 -11
  85. package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +4 -8
  86. package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +6 -2
  87. package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +4 -8
  88. package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +4 -8
  89. package/layers/shader/app/components/Pipeline/Circle.client.vue +5 -8
  90. package/layers/shader/app/components/Pipeline/Clouds.client.vue +4 -8
  91. package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +2 -19
  92. package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +2 -19
  93. package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +5 -9
  94. package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +5 -8
  95. package/layers/shader/app/components/Pipeline/Cross.client.vue +4 -8
  96. package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +3 -7
  97. package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +2 -19
  98. package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +5 -8
  99. package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +5 -8
  100. package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +5 -8
  101. package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +2 -19
  102. package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +4 -8
  103. package/layers/shader/app/components/Pipeline/Dots.client.vue +4 -8
  104. package/layers/shader/app/components/Pipeline/DuoTone.client.vue +5 -9
  105. package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +3 -23
  106. package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +4 -7
  107. package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +4 -7
  108. package/layers/shader/app/components/Pipeline/Flame.client.vue +4 -8
  109. package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +5 -8
  110. package/layers/shader/app/components/Pipeline/GodRays.client.vue +4 -7
  111. package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +4 -8
  112. package/layers/shader/app/components/Pipeline/Grid.client.vue +4 -8
  113. package/layers/shader/app/components/Pipeline/Halation.client.vue +3 -7
  114. package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +2 -19
  115. package/layers/shader/app/components/Pipeline/Haze.client.vue +4 -7
  116. package/layers/shader/app/components/Pipeline/Hexagon.client.vue +4 -8
  117. package/layers/shader/app/components/Pipeline/LensFlare.client.vue +4 -7
  118. package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +2 -19
  119. package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +2 -2
  120. package/layers/shader/app/components/Pipeline/Marble.client.vue +4 -8
  121. package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +3 -7
  122. package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +2 -19
  123. package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +4 -8
  124. package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +4 -8
  125. package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +2 -19
  126. package/layers/shader/app/components/Pipeline/Polygon.client.vue +4 -8
  127. package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +4 -7
  128. package/layers/shader/app/components/Pipeline/Rectangle.client.vue +4 -8
  129. package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +4 -8
  130. package/layers/shader/app/components/Pipeline/Ring.client.vue +4 -8
  131. package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +2 -19
  132. package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +6 -9
  133. package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +2 -19
  134. package/layers/shader/app/components/Pipeline/SplitTone.client.vue +4 -8
  135. package/layers/shader/app/components/Pipeline/Star.client.vue +4 -8
  136. package/layers/shader/app/components/Pipeline/Stripes.client.vue +4 -8
  137. package/layers/shader/app/components/Pipeline/Tint.client.vue +4 -7
  138. package/layers/shader/app/components/Pipeline/Triangle.client.vue +4 -8
  139. package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +4 -8
  140. package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +4 -8
  141. package/layers/shader/app/components/Pipeline/Water.client.vue +5 -8
  142. package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +4 -7
  143. package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +3 -7
  144. package/layers/shader/app/components/Pipeline/Wood.client.vue +4 -8
  145. package/layers/shader/app/components/Preset/Aurora.client.vue +15 -21
  146. package/layers/shader/app/components/Preset/Flow.client.vue +2 -1
  147. package/layers/shader/app/components/Preset/GradientMesh.client.vue +2 -1
  148. package/layers/shader/app/components/Preset/Nebula.client.vue +2 -1
  149. package/layers/shader/app/components/Preset/Ocean.client.vue +2 -1
  150. package/layers/shader/app/components/Preset/ThemeAurora.client.vue +30 -90
  151. package/layers/shader/app/components/Preset/ThemeBubble.client.vue +30 -91
  152. package/layers/shader/app/components/Preset/ThemeFlow.client.vue +30 -90
  153. package/layers/shader/app/components/Preset/ThemeGradient.client.vue +30 -91
  154. package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +30 -90
  155. package/layers/shader/app/components/Preset/ThemePlasma.client.vue +30 -90
  156. package/layers/shader/app/components/Preset/ThemeWave.client.vue +30 -90
  157. package/layers/shader/app/components/Shader/Background.client.vue +4 -4
  158. package/layers/shader/app/components/Shader/Host.client.vue +31 -33
  159. package/layers/shader/app/components/Shader/Runtime.client.vue +15 -23
  160. package/layers/shader/app/composables/useAmbientMaterials.ts +53 -51
  161. package/layers/shader/app/composables/useShaderMixBlend.ts +26 -0
  162. package/layers/shader/app/composables/useThemePreset.ts +75 -0
  163. package/layers/shader/app/shaders/common/noise.ts +2 -7
  164. package/layers/shader/app/shaders/types.ts +6 -6
  165. package/layers/shader/app/types/tsl.ts +7 -25
  166. package/layers/shader/app/types/uniforms.ts +2 -1
  167. package/layers/shader/app/utils/tsl/color.ts +7 -1
  168. package/layers/shader/package.json +2 -1
  169. package/layers/theme/app/components/ThemePicker/Colors.vue +1 -3
  170. package/layers/theme/app/types/app-config.d.ts +4 -2
  171. package/layers/theme/app/types/index.ts +1 -0
  172. package/layers/theme/app/types/theme.ts +3 -18
  173. package/layers/theme/package.json +2 -1
  174. package/layers/theme/server/plugins/theme-fouc.ts +1 -1
  175. package/layers/transitions/package.json +4 -1
  176. package/layers/typography/app/components/Typography/CodeBlock.vue +2 -2
  177. package/layers/typography/app/components/Typography/Headline.vue +2 -2
  178. package/layers/typography/app/components/Typography/HeadlineScreen.vue +1 -1
  179. package/layers/typography/app/components/Typography/QuoteBlock.vue +4 -1
  180. package/layers/typography/app/components/Typography/TextStroke.vue +2 -0
  181. package/layers/typography/app/components/Typography/index.vue +36 -27
  182. package/layers/typography/app/composables/typography.ts +27 -21
  183. package/layers/typography/app/types/colors.ts +9 -29
  184. package/layers/typography/app/types/index.ts +2 -0
  185. package/layers/typography/package.json +4 -1
  186. package/layers/ui/package.json +2 -1
  187. package/layers/visual/app/app.config.ts +5 -2
  188. package/layers/visual/app/components/Accent/Blob.vue +20 -20
  189. package/layers/visual/app/components/Accent/Scene.vue +2 -2
  190. package/layers/visual/app/components/Base/Modal.vue +2 -2
  191. package/layers/visual/app/components/Gradient/Background.vue +2 -2
  192. package/layers/visual/app/components/Gradient/Text.vue +2 -2
  193. package/layers/visual/app/components/Media/Picture.vue +3 -1
  194. package/layers/visual/app/components/Progress/Bar.vue +6 -6
  195. package/layers/visual/app/components/Tint/Overlay.vue +14 -14
  196. package/layers/visual/app/composables/accent.ts +10 -8
  197. package/layers/visual/app/composables/tint.ts +7 -7
  198. package/layers/visual/app/types/index.ts +6 -0
  199. package/layers/visual/app/types/media.ts +4 -2
  200. package/layers/visual/app/types/tint.ts +2 -1
  201. package/layers/visual/package.json +4 -1
  202. package/package.json +6 -2
package/docs/FEEDS.md ADDED
@@ -0,0 +1,197 @@
1
+ # Adding Feeds to Your Content Sections
2
+
3
+ How to expose your Nuxt Content collections as **RSS 2.0**, **Atom 1.0**, and **JSON Feed 1.1** using the `feeds` layer (`layers/feeds`).
4
+
5
+ The layer provides everything server-side — feed routes, format serializers, XSLT browser styling, and `<head>` autodiscovery. Your app only has to do three things: **register the layer**, **declare which collections to expose**, and **prerender the collection routes** (for static/Netlify hosting).
6
+
7
+ > **Prerequisite:** the site `app.config.ts` must define a top-level `site` key (`title`, `url`, `author`, …). Feeds read it for channel metadata. If you're coming from an older version where this lived under `feedsLayer.site`, do the breaking-change migration in [`MIGRATION.md`](./MIGRATION.md) first.
8
+
9
+ ---
10
+
11
+ ## How it works
12
+
13
+ ```
14
+ content collection ──> content-adapter ──> feed-service ──> rss / atom / json serializer ──> /feed/... route
15
+ (queryCollection) (drop drafts, (channel meta (format-specific XML/JSON)
16
+ sort by date, from `site`)
17
+ slice to limit)
18
+ ```
19
+
20
+ - `layers/feeds/server/utils/content-adapter.ts` — queries a collection, drops `draft` items, sorts newest-first by `date` (falling back to `createdAt`), slices to `limit`, and maps each item to a `FeedItem`.
21
+ - `layers/feeds/server/utils/feed-service.ts` + `formats/` — build the channel from `site` config and serialize to each format.
22
+ - `layers/feeds/app/plugins/feed-head.ts` — injects `<link rel="alternate">` discovery tags.
23
+ - `/feed/style.xsl` — stylesheet so feeds render as a styled page in a browser, not raw XML.
24
+
25
+ You don't edit any of these. You configure them.
26
+
27
+ ---
28
+
29
+ ## Step 1 — Register the `feeds` layer
30
+
31
+ The feeds layer depends on `core` and `content`. Register all three (Nuxt deduplicates, so listing an already-present dependency is free).
32
+
33
+ **Direct `extends`:**
34
+
35
+ ```ts
36
+ // nuxt.config.ts
37
+ export default defineNuxtConfig({
38
+ extends: ['../layers/core', '../layers/content', '../layers/feeds'],
39
+ })
40
+ ```
41
+
42
+ **Resolver-style (like the playground):**
43
+
44
+ ```ts
45
+ const AVAILABLE_LAYERS = [/* ...existing... */, 'content', 'feeds'] as const
46
+
47
+ const LAYER_PATHS = {
48
+ /* ... */
49
+ content: '../../layers/content',
50
+ feeds: '../../layers/feeds',
51
+ }
52
+
53
+ const LAYER_DEPENDENCIES = {
54
+ /* ... */
55
+ content: ['core'],
56
+ feeds: ['core', 'content'],
57
+ }
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Step 2 — Declare which collections become feeds
63
+
64
+ Feeds are driven by `feedsLayer.feed.collections` in `app/app.config.ts`. The default is `['blog']`. Each name must match a key in your app's `content.config.ts` `collections` object.
65
+
66
+ ```ts
67
+ // app/app.config.ts
68
+ export default defineAppConfig({
69
+ site: {
70
+ title: 'My Site',
71
+ description: 'What the site is about',
72
+ url: 'https://example.com', // canonical origin, no trailing slash
73
+ author: { name: 'Jane', email: 'jane@example.com' },
74
+ },
75
+ feedsLayer: {
76
+ feed: {
77
+ limit: 30, // max items per feed
78
+ collections: ['blog', 'portfolio'], // every collection to expose
79
+ defaultCollection: 'blog', // backs the /feed/rss shorthand routes
80
+ },
81
+ },
82
+ })
83
+ ```
84
+
85
+ | Option | Default | Meaning |
86
+ |--------|---------|---------|
87
+ | `limit` | `30` | Max items included in each feed |
88
+ | `collections` | `['blog']` | Collection names to expose as feeds |
89
+ | `defaultCollection` | `'blog'` | Collection served by the shorthand `/feed/rss` routes |
90
+
91
+ ---
92
+
93
+ ## Step 3 — Routes you now get for free
94
+
95
+ Every configured collection serves:
96
+
97
+ | URL | Format |
98
+ |-----|--------|
99
+ | `/feed/:collection/rss` | RSS 2.0 |
100
+ | `/feed/:collection/atom` | Atom 1.0 |
101
+ | `/feed/:collection/json` | JSON Feed 1.1 |
102
+
103
+ Plus site-wide shorthand and index routes:
104
+
105
+ | URL | Purpose |
106
+ |-----|---------|
107
+ | `/feed/rss`, `/feed/atom`, `/feed/json` | Shorthand → serves `defaultCollection` |
108
+ | `/feed` | JSON index of all configured feeds |
109
+ | `/feed/discovery` | Machine-readable feed discovery document |
110
+ | `/feed/style.xsl` | Browser stylesheet (applied automatically) |
111
+
112
+ Opening any feed URL in a browser shows a styled page thanks to the XSLT stylesheet — no app work required.
113
+
114
+ ---
115
+
116
+ ## Step 4 — Prerender collection routes (required for static / Netlify)
117
+
118
+ Feed routes are **server routes**. The prerender crawler can't discover `/feed/:collection/*` because nothing links to them with an `<a href>`. The feeds layer already prerenders the **shorthand** routes (`/feed`, `/feed/rss`, `/feed/atom`, `/feed/json`, `/feed/style.xsl`, `/feed/discovery`). You must list the **collection-specific** routes in your app's `nuxt.config.ts` — one trio per collection in `feedsLayer.feed.collections`:
119
+
120
+ ```ts
121
+ // nuxt.config.ts
122
+ nitro: {
123
+ prerender: {
124
+ routes: [
125
+ '/feed/blog/rss',
126
+ '/feed/blog/atom',
127
+ '/feed/blog/json',
128
+ // repeat for every other collection, e.g. portfolio:
129
+ '/feed/portfolio/rss',
130
+ '/feed/portfolio/atom',
131
+ '/feed/portfolio/json',
132
+ ],
133
+ },
134
+ },
135
+ ```
136
+
137
+ **Omitting these makes collection feeds return 404 on Netlify and other static hosts.** Reference: `apps/playground/nuxt.config.ts` → `nitro.prerender.routes`.
138
+
139
+ > Running a Node server (SSR) instead of static prerendering? This step is optional — the routes are served on demand. It only matters for fully prerendered/static deploys.
140
+
141
+ ---
142
+
143
+ ## Step 5 — `<head>` autodiscovery (automatic)
144
+
145
+ The `feed-head.ts` plugin injects `<link rel="alternate">` tags so RSS readers and browsers discover your feeds. The rule:
146
+
147
+ - **Every page** gets the 3 main site feeds (shorthand routes → `defaultCollection`).
148
+ - A page whose first path segment matches a **non-default** collection (e.g. `/portfolio/...`) **also** gets that collection's 3 specific feeds.
149
+
150
+ | Page | Links injected |
151
+ |------|----------------|
152
+ | `/`, `/about`, any non-collection page | 3 main site feeds |
153
+ | `/blog`, `/blog/hello` (when `blog` is the default) | 3 main site feeds (already point to blog) |
154
+ | `/portfolio`, `/portfolio/project` (non-default collection) | 3 main + 3 portfolio feeds |
155
+
156
+ **Do nothing.** Don't hand-add `<link rel="alternate">` tags — you'll duplicate them.
157
+
158
+ ---
159
+
160
+ ## Aliased collections
161
+
162
+ If you've aliased a collection (e.g. reused the portfolio schema as `works` via `createPortfolioCollection('works/**/*.md')` in `content.config.ts`), feeds work the same way — add the alias name to `feedsLayer.feed.collections` and its routes to `nitro.prerender.routes`:
163
+
164
+ ```ts
165
+ // app.config.ts
166
+ feedsLayer: { feed: { collections: ['blog', 'works'] } }
167
+
168
+ // nuxt.config.ts
169
+ nitro: { prerender: { routes: ['/feed/works/rss', '/feed/works/atom', '/feed/works/json'] } }
170
+ ```
171
+
172
+ See `MIGRATION.md` → "Collection Aliases" for how to define the alias itself.
173
+
174
+ ---
175
+
176
+ ## Verify
177
+
178
+ 1. `pnpm dev`, then load:
179
+ - `/feed/rss` → styled XML, items present, `<author>` / `link` populated from frontmatter.
180
+ - `/feed/<collection>/json` for each configured collection → JSON Feed 1.1 with items.
181
+ - `/feed` → index lists every configured collection.
182
+ 2. View source on a content page → `<link rel="alternate" ...>` tags present (a non-default-collection page has the extra trio).
183
+ 3. **Static/Netlify:** `pnpm build`, then confirm each `/feed/<collection>/*` route emitted a static file with no 404 warnings in the prerender log.
184
+
185
+ ---
186
+
187
+ ## Quick reference
188
+
189
+ | Goal | Action |
190
+ |------|--------|
191
+ | Turn on feeds | Register `core` + `content` + `feeds` layers |
192
+ | Expose a collection | Add its name to `feedsLayer.feed.collections` |
193
+ | Set the shorthand target | `feedsLayer.feed.defaultCollection` |
194
+ | Cap items per feed | `feedsLayer.feed.limit` |
195
+ | Static hosting | Add `/feed/<collection>/{rss,atom,json}` to `nitro.prerender.routes` |
196
+ | Autodiscovery in `<head>` | Automatic — nothing to do |
197
+ | Feed channel metadata | Top-level `site` config in `app.config.ts` |
@@ -0,0 +1,101 @@
1
+ # kmcom-nuxt-layers — Two Fixes Required
2
+
3
+ Discovered while migrating KMCOMv5/frontend to v2.2.3 and wiring up feeds.
4
+
5
+ ---
6
+
7
+ ## Fix 1 — `PictureProps.provider` hardcoded to `'ipx'`
8
+
9
+ **File:** `layers/visual/app/types/media.ts`, line 154
10
+
11
+ **Problem:** The `provider` prop is typed as a literal `'ipx'`, so any app that configures
12
+ a different Nuxt Image provider (e.g. `netlify`) gets a TypeScript error when `NuxtPicture`
13
+ receives the prop:
14
+
15
+ ```
16
+ Type '"ipx" | undefined' is not assignable to type '"netlify" | undefined'.
17
+ ```
18
+
19
+ **Fix:** Widen the type to `string` so any configured provider is accepted.
20
+
21
+ ```ts
22
+ // BEFORE
23
+ /** Image provider - defaults to 'ipx' (Nuxt's built-in image optimizer) */
24
+ provider?: 'ipx'
25
+
26
+ // AFTER
27
+ /** Image provider override. Defaults to the app's configured Nuxt Image provider. */
28
+ provider?: string
29
+ ```
30
+
31
+ No other changes needed — the prop is already passed through as-is to `NuxtPicture`.
32
+
33
+ ---
34
+
35
+ ## Fix 2 — `feeds` layer missing from package exports and server routes excluded from published files
36
+
37
+ **Problem:** The `feeds` layer has two packaging issues that prevent it from working in
38
+ consuming apps:
39
+
40
+ ### 2a — Missing export entry
41
+
42
+ `package.json` `exports` lists every other layer but not `feeds`, so Node's package
43
+ exports map rejects the import and Nuxt emits:
44
+
45
+ ```
46
+ WARN Cannot extend config from kmcom-nuxt-layers/layers/feeds
47
+ ```
48
+
49
+ **Fix:** Add one line to the `exports` map in the root `package.json`:
50
+
51
+ ```json
52
+ "exports": {
53
+ "./layers/core": "./layers/core/nuxt.config.ts",
54
+ ...
55
+ "./layers/content": "./layers/content/nuxt.config.ts",
56
+ "./layers/feeds": "./layers/feeds/nuxt.config.ts", // ← add this
57
+ "./layers/routing": "./layers/routing/nuxt.config.ts"
58
+ }
59
+ ```
60
+
61
+ ### 2b — Server routes excluded from published files
62
+
63
+ The `files` glob only covers `layers/*/app/**`. Feed endpoints live in
64
+ `layers/feeds/server/` and are therefore stripped from the npm tarball, so the
65
+ `/feed/rss`, `/feed/atom`, `/feed/json`, and `/feed/blog/*` routes are never shipped.
66
+
67
+ **Fix:** Add a `server` glob to the `files` array in the root `package.json`:
68
+
69
+ ```json
70
+ "files": [
71
+ "layers/*/nuxt.config.ts",
72
+ "layers/*/app.config.ts",
73
+ "layers/*/package.json",
74
+ "layers/*/tsconfig.json",
75
+ "layers/*/tailwind.config.*",
76
+ "layers/*/app/**",
77
+ "layers/*/server/**", // ← add this
78
+ "docs/"
79
+ ]
80
+ ```
81
+
82
+ Both changes are required. Without 2a the layer is silently skipped; without 2b the
83
+ layer loads but all feed routes return 404 because the server handlers are absent.
84
+
85
+ ---
86
+
87
+ ## Verification (after publishing a new version)
88
+
89
+ In KMCOMv5/frontend, bump `kmcom-nuxt-layers` to the new version and run:
90
+
91
+ ```sh
92
+ pnpm install
93
+ pnpm typecheck # should pass with zero errors
94
+ pnpm dev
95
+ ```
96
+
97
+ Then visit:
98
+ - `/feed/rss` — styled RSS XML, blog items present
99
+ - `/feed/blog/json` — JSON Feed 1.1 with items
100
+ - `/feed` — index listing the blog collection
101
+ - View source on any page → `<link rel="alternate" ...>` tags in `<head>`