kmcom-nuxt-layers 2.2.6 → 2.2.8
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/docs/FEEDS.md +197 -0
- package/docs/LAYERS-FIXES.md +101 -0
- package/docs/MIGRATION.md +627 -0
- package/docs/feed-layer.md +374 -0
- package/docs/patch-picture-provider-type.md +52 -0
- package/docs/shaderGuide.md +2071 -0
- package/docs/types-architecture.md +234 -0
- package/layers/animations/app/components/Motion/CountUp.vue +1 -2
- package/layers/animations/app/components/Motion/Magnetic.vue +1 -2
- package/layers/animations/app/components/Motion/Marquee.vue +2 -5
- package/layers/animations/app/components/Motion/MarqueeText.vue +1 -2
- package/layers/animations/app/components/Motion/Tilt.vue +1 -2
- package/layers/animations/app/composables/useCountUp.ts +4 -1
- package/layers/animations/app/composables/useMagneticElement.ts +1 -3
- package/layers/animations/app/composables/useMarqueeCopies.ts +3 -3
- package/layers/animations/app/types/animations.ts +8 -0
- package/layers/animations/app/types/index.ts +1 -0
- package/layers/animations/package.json +4 -1
- package/layers/canvas/app/components/ShaderCanvas.vue +4 -4
- package/layers/canvas/app/composables/useRendererCapabilities.ts +19 -15
- package/layers/canvas/app/types/index.ts +1 -0
- package/layers/canvas/package.json +2 -1
- package/layers/canvas/tsconfig.json +2 -1
- package/layers/content/app/components/Blog/Card.vue +5 -5
- package/layers/content/app/components/Gallery/AmbientImage.vue +3 -3
- package/layers/content/app/components/Gallery/Card.vue +3 -3
- package/layers/content/app/components/NuxtContent/Detail.vue +5 -1
- package/layers/content/app/components/NuxtContent/Surround.vue +5 -3
- package/layers/content/app/components/NuxtContent/Toc.vue +1 -1
- package/layers/content/app/components/Portfolio/Card.vue +5 -5
- package/layers/content/app/components/content/Figure.vue +3 -3
- package/layers/content/app/types/index.ts +1 -0
- package/layers/content/package.json +2 -1
- package/layers/core/app/composables/useErrorLog.ts +9 -11
- package/layers/core/app/utils/helpers.ts +14 -12
- package/layers/core/nuxt.config.ts +1 -0
- package/layers/feeds/app/plugins/feed-head.ts +1 -2
- package/layers/feeds/package.json +2 -1
- package/layers/feeds/server/routes/feed/discovery.get.ts +1 -2
- package/layers/feeds/server/utils/content-adapter.ts +3 -2
- package/layers/forms/app/components/Form/Field.vue +4 -4
- package/layers/forms/app/types/index.ts +1 -0
- package/layers/forms/package.json +2 -1
- package/layers/layout/app/components/Layout/Grid/Item.vue +33 -19
- package/layers/layout/app/components/Layout/Page/Container.vue +11 -11
- package/layers/layout/app/components/Layout/Page/Header.vue +1 -1
- package/layers/layout/app/components/Layout/Page/index.vue +1 -1
- package/layers/layout/app/components/Layout/Section/Gallery.vue +6 -1
- package/layers/layout/app/components/Layout/Section/Title.vue +1 -1
- package/layers/layout/app/types/index.ts +1 -0
- package/layers/layout/package.json +2 -1
- package/layers/mailer/app/types/index.ts +1 -0
- package/layers/mailer/app/types/mailer.ts +25 -0
- package/layers/mailer/package.json +2 -1
- package/layers/motion/package.json +2 -1
- package/layers/navigation/app/components/Links/Group.vue +1 -0
- package/layers/navigation/app/components/Links/Named.vue +2 -0
- package/layers/navigation/app/types/index.ts +1 -0
- package/layers/navigation/package.json +4 -1
- package/layers/page-transitions/package.json +4 -1
- package/layers/routing/app/types/app-config.d.ts +3 -1
- package/layers/routing/app/types/index.ts +1 -0
- package/layers/routing/package.json +2 -1
- package/layers/scripts/app/composables/useGtm.ts +1 -1
- package/layers/scripts/app/types/index.ts +1 -0
- package/layers/scripts/app/types/scripts.ts +14 -0
- package/layers/scripts/package.json +2 -1
- package/layers/scroll/app/components/Motion/ScrollScene.vue +3 -1
- package/layers/scroll/app/composables/useScrollSteps.ts +2 -9
- package/layers/scroll/app/composables/useSectionProgress.ts +2 -1
- package/layers/scroll/app/plugins/locomotive-scroll.client.ts +1 -8
- package/layers/scroll/app/types/index.ts +1 -0
- package/layers/scroll/app/types/scroll.ts +32 -0
- package/layers/scroll/package.json +3 -0
- package/layers/seo/package.json +2 -1
- package/layers/shader/app/components/Material/Fresnel.client.vue +1 -1
- package/layers/shader/app/components/Material/Image.client.vue +1 -1
- package/layers/shader/app/components/Material/Node.client.vue +7 -7
- package/layers/shader/app/components/Material/Noise.client.vue +1 -1
- package/layers/shader/app/components/Node/Color.client.vue +17 -20
- package/layers/shader/app/components/Node/Noise.client.vue +31 -34
- package/layers/shader/app/components/Pipeline/Aurora.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +8 -11
- package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +6 -2
- package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Circle.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/Clouds.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +5 -9
- package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/Cross.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Dots.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/DuoTone.client.vue +5 -9
- package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +3 -23
- package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Flame.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/GodRays.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Grid.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Halation.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/Haze.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Hexagon.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/LensFlare.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +2 -2
- package/layers/shader/app/components/Pipeline/Marble.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/Polygon.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Rectangle.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Ring.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +6 -9
- package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/SplitTone.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Star.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Stripes.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Tint.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Triangle.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Water.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/Wood.client.vue +4 -8
- package/layers/shader/app/components/Preset/Aurora.client.vue +15 -21
- package/layers/shader/app/components/Preset/Flow.client.vue +2 -1
- package/layers/shader/app/components/Preset/GradientMesh.client.vue +2 -1
- package/layers/shader/app/components/Preset/Nebula.client.vue +2 -1
- package/layers/shader/app/components/Preset/Ocean.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemeAurora.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemeBubble.client.vue +30 -91
- package/layers/shader/app/components/Preset/ThemeFlow.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemeGradient.client.vue +30 -91
- package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemePlasma.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemeWave.client.vue +30 -90
- package/layers/shader/app/components/Shader/Background.client.vue +4 -4
- package/layers/shader/app/components/Shader/Host.client.vue +31 -33
- package/layers/shader/app/components/Shader/Runtime.client.vue +15 -23
- package/layers/shader/app/composables/useAmbientMaterials.ts +53 -51
- package/layers/shader/app/composables/useShaderMixBlend.ts +26 -0
- package/layers/shader/app/composables/useThemePreset.ts +75 -0
- package/layers/shader/app/shaders/common/noise.ts +2 -7
- package/layers/shader/app/shaders/types.ts +6 -6
- package/layers/shader/app/types/tsl.ts +7 -25
- package/layers/shader/app/types/uniforms.ts +2 -1
- package/layers/shader/app/utils/tsl/color.ts +7 -1
- package/layers/shader/package.json +2 -1
- package/layers/theme/app/components/ThemePicker/Colors.vue +1 -3
- package/layers/theme/app/types/app-config.d.ts +4 -2
- package/layers/theme/app/types/index.ts +1 -0
- package/layers/theme/app/types/theme.ts +3 -18
- package/layers/theme/package.json +2 -1
- package/layers/theme/server/plugins/theme-fouc.ts +1 -1
- package/layers/transitions/package.json +4 -1
- package/layers/typography/app/components/Typography/CodeBlock.vue +2 -2
- package/layers/typography/app/components/Typography/Headline.vue +2 -2
- package/layers/typography/app/components/Typography/HeadlineScreen.vue +1 -1
- package/layers/typography/app/components/Typography/QuoteBlock.vue +4 -1
- package/layers/typography/app/components/Typography/TextStroke.vue +2 -0
- package/layers/typography/app/components/Typography/index.vue +36 -27
- package/layers/typography/app/composables/typography.ts +27 -21
- package/layers/typography/app/types/colors.ts +9 -29
- package/layers/typography/app/types/index.ts +2 -0
- package/layers/typography/package.json +4 -1
- package/layers/ui/package.json +2 -1
- package/layers/visual/app/app.config.ts +5 -2
- package/layers/visual/app/components/Accent/Blob.vue +20 -20
- package/layers/visual/app/components/Accent/Scene.vue +2 -2
- package/layers/visual/app/components/Base/Modal.vue +2 -2
- package/layers/visual/app/components/Gradient/Background.vue +2 -2
- package/layers/visual/app/components/Gradient/Text.vue +2 -2
- package/layers/visual/app/components/Media/Picture.vue +3 -1
- package/layers/visual/app/components/Progress/Bar.vue +6 -6
- package/layers/visual/app/components/Tint/Overlay.vue +14 -14
- package/layers/visual/app/composables/accent.ts +10 -8
- package/layers/visual/app/composables/tint.ts +7 -7
- package/layers/visual/app/types/index.ts +6 -0
- package/layers/visual/app/types/media.ts +4 -2
- package/layers/visual/app/types/tint.ts +2 -1
- package/layers/visual/package.json +4 -1
- package/package.json +5 -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>`
|