@rmdes/indiekit-endpoint-youtube 1.2.2 → 1.2.3

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/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  YouTube channel endpoint for [Indiekit](https://getindiekit.com/).
7
7
 
8
- Display latest videos and live streaming status from any YouTube channel on your IndieWeb site.
8
+ Display latest videos and live streaming status from any YouTube channel (or multiple channels) on your IndieWeb site.
9
9
 
10
10
  ## Installation
11
11
 
@@ -17,7 +17,8 @@ npm install @rmdes/indiekit-endpoint-youtube
17
17
 
18
18
  ## Features
19
19
 
20
- - **Admin Dashboard** - Overview of channel with latest videos in Indiekit's admin UI
20
+ - **Single or Multi-Channel** - Monitor one channel or aggregate multiple channels
21
+ - **Admin Dashboard** - Overview of channel(s) with latest videos in Indiekit's admin UI
21
22
  - **Live Status** - Shows when channel is live streaming (with animated badge)
22
23
  - **Upcoming Streams** - Display scheduled upcoming live streams
23
24
  - **Latest Videos** - Grid of recent uploads with thumbnails, duration, view counts
@@ -27,6 +28,8 @@ npm install @rmdes/indiekit-endpoint-youtube
27
28
 
28
29
  ## Configuration
29
30
 
31
+ ### Single Channel
32
+
30
33
  Add to your `indiekit.config.js`:
31
34
 
32
35
  ```javascript
@@ -50,6 +53,39 @@ export default {
50
53
  };
51
54
  ```
52
55
 
56
+ ### Multiple Channels
57
+
58
+ Monitor multiple YouTube channels simultaneously:
59
+
60
+ ```javascript
61
+ import YouTubeEndpoint from "@rmdes/indiekit-endpoint-youtube";
62
+
63
+ export default {
64
+ plugins: [
65
+ new YouTubeEndpoint({
66
+ mountPath: "/youtube",
67
+ apiKey: process.env.YOUTUBE_API_KEY,
68
+ channels: [
69
+ { id: "UC...", name: "Main Channel" },
70
+ { handle: "@SecondChannel", name: "Second Channel" },
71
+ { id: "UC...", name: "Third Channel" },
72
+ ],
73
+ cacheTtl: 300_000,
74
+ liveCacheTtl: 60_000,
75
+ limits: {
76
+ videos: 10,
77
+ },
78
+ }),
79
+ ],
80
+ };
81
+ ```
82
+
83
+ In multi-channel mode:
84
+ - Dashboard shows all channels with separate sections
85
+ - API endpoints aggregate data from all channels
86
+ - Videos are sorted by date across all channels
87
+ - Live status shows any channel that is currently live
88
+
53
89
  ## Environment Variables
54
90
 
55
91
  | Variable | Required | Description |
@@ -58,7 +94,7 @@ export default {
58
94
  | `YOUTUBE_CHANNEL_ID` | Yes* | Channel ID (starts with `UC...`) |
59
95
  | `YOUTUBE_CHANNEL_HANDLE` | Yes* | Channel handle (e.g., `@YourChannel`) |
60
96
 
61
- *Either `channelId` or `channelHandle` is required.
97
+ *Either `channelId` or `channelHandle` is required for single-channel mode. In multi-channel mode, use the `channels` array instead.
62
98
 
63
99
  ### Getting a YouTube API Key
64
100
 
@@ -81,7 +117,7 @@ export default {
81
117
  | Route | Description |
82
118
  |-------|-------------|
83
119
  | `GET /youtube/` | Dashboard with channel info, live status, latest videos |
84
- | `POST /youtube/refresh` | Clear cache and refresh data |
120
+ | `POST /youtube/refresh` | Clear cache and refresh data (returns JSON) |
85
121
 
86
122
  ### Public API Routes (JSON)
87
123
 
@@ -89,7 +125,8 @@ export default {
89
125
  |-------|-------------|
90
126
  | `GET /youtube/api/videos` | Latest videos (supports `?limit=N`) |
91
127
  | `GET /youtube/api/channel` | Channel information |
92
- | `GET /youtube/api/live` | Live streaming status |
128
+ | `GET /youtube/api/live` | Live streaming status (efficient by default) |
129
+ | `GET /youtube/api/live?full=true` | Live status using search API (more accurate, costs more quota) |
93
130
 
94
131
  ### Example: Eleventy Integration
95
132
 
@@ -119,6 +156,7 @@ export default async function() {
119
156
 
120
157
  ### GET /youtube/api/live
121
158
 
159
+ **Single channel:**
122
160
  ```json
123
161
  {
124
162
  "isLive": true,
@@ -133,8 +171,34 @@ export default async function() {
133
171
  }
134
172
  ```
135
173
 
174
+ **Multi-channel:**
175
+ ```json
176
+ {
177
+ "isLive": true,
178
+ "isUpcoming": false,
179
+ "stream": {
180
+ "videoId": "abc123",
181
+ "title": "Live Stream Title"
182
+ },
183
+ "liveStatuses": [
184
+ {
185
+ "channelConfigName": "Main Channel",
186
+ "isLive": true,
187
+ "stream": { "videoId": "abc123" }
188
+ },
189
+ {
190
+ "channelConfigName": "Second Channel",
191
+ "isLive": false,
192
+ "stream": null
193
+ }
194
+ ],
195
+ "cached": true
196
+ }
197
+ ```
198
+
136
199
  ### GET /youtube/api/videos
137
200
 
201
+ **Single channel:**
138
202
  ```json
139
203
  {
140
204
  "videos": [
@@ -155,17 +219,75 @@ export default async function() {
155
219
  }
156
220
  ```
157
221
 
222
+ **Multi-channel:**
223
+ ```json
224
+ {
225
+ "videos": [],
226
+ "videosByChannel": {
227
+ "Main Channel": [],
228
+ "Second Channel": []
229
+ },
230
+ "count": 20,
231
+ "cached": true
232
+ }
233
+ ```
234
+
235
+ ### GET /youtube/api/channel
236
+
237
+ **Single channel:**
238
+ ```json
239
+ {
240
+ "channel": {
241
+ "id": "UC...",
242
+ "title": "Channel Name",
243
+ "description": "Channel description",
244
+ "thumbnail": "https://...",
245
+ "subscriberCount": 12345,
246
+ "videoCount": 100,
247
+ "viewCount": 999999
248
+ },
249
+ "cached": true
250
+ }
251
+ ```
252
+
253
+ **Multi-channel:**
254
+ ```json
255
+ {
256
+ "channels": [
257
+ { "id": "UC...", "title": "Channel 1", "configName": "Main Channel" },
258
+ { "id": "UC...", "title": "Channel 2", "configName": "Second Channel" }
259
+ ],
260
+ "channel": {},
261
+ "cached": true
262
+ }
263
+ ```
264
+
158
265
  ## Options
159
266
 
160
267
  | Option | Default | Description |
161
268
  |--------|---------|-------------|
162
269
  | `mountPath` | `/youtube` | URL path for the endpoint |
163
270
  | `apiKey` | - | YouTube Data API key |
164
- | `channelId` | - | Channel ID (UC...) |
165
- | `channelHandle` | - | Channel handle (@...) |
271
+ | `channelId` | - | Channel ID (UC...) - single channel mode |
272
+ | `channelHandle` | - | Channel handle (@...) - single channel mode |
273
+ | `channels` | `null` | Array of channels for multi-channel mode |
166
274
  | `cacheTtl` | `300000` | Cache TTL in ms (5 min) |
167
275
  | `liveCacheTtl` | `60000` | Live status cache TTL in ms (1 min) |
168
- | `limits.videos` | `10` | Number of videos to fetch |
276
+ | `limits.videos` | `10` | Number of videos to fetch per channel |
277
+
278
+ ### Channels Array Format
279
+
280
+ For multi-channel mode, the `channels` option accepts an array of objects:
281
+
282
+ ```javascript
283
+ channels: [
284
+ { id: "UC...", name: "Display Name" }, // Using channel ID
285
+ { handle: "@username", name: "Display Name" }, // Using handle
286
+ { id: "UC..." } // Name defaults to channel title
287
+ ]
288
+ ```
289
+
290
+ Either `id` or `handle` is required. The `name` field is optional and used for display purposes.
169
291
 
170
292
  ## Quota Efficiency
171
293
 
@@ -175,16 +297,19 @@ YouTube Data API has a daily quota (10,000 units by default). This plugin is opt
175
297
  |-----------|------------|--------|
176
298
  | Get videos | 2 units | Uses uploads playlist (not search) |
177
299
  | Get channel | 1 unit | Cached for 24 hours |
178
- | Check live status | 2 units | Checks recent videos (efficient) |
179
- | Full live search | 100 units | Only when explicitly requested |
300
+ | Check live status (efficient) | 2 units | Checks recent videos |
301
+ | Check live status (full) | 100 units | Only when explicitly requested |
302
+
303
+ **Single channel:** With default settings (5-min cache), ~600 units/day.
180
304
 
181
- With default settings (5-min cache), you'll use ~600 units/day for video checks.
305
+ **Multi-channel:** Quota usage scales linearly. 3 channels = ~1,800 units/day.
182
306
 
183
307
  ## Requirements
184
308
 
185
309
  - Indiekit >= 1.0.0-beta.25
186
310
  - YouTube Data API v3 enabled
187
311
  - Valid API key with YouTube Data API access
312
+ - Node.js >= 20
188
313
 
189
314
  ## License
190
315
 
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Neueste Videos",
5
+ "channel": "Kanal",
6
+ "live": "Live jetzt",
7
+ "upcoming": "Demnächst",
8
+ "offline": "Offline",
9
+ "subscribers": "Abonnenten",
10
+ "views": "Aufrufe",
11
+ "watchNow": "Jetzt ansehen",
12
+ "viewChannel": "Kanal anzeigen",
13
+ "viewAll": "Alle Videos anzeigen",
14
+ "noVideos": "Keine Videos gefunden",
15
+ "refreshed": "Aktualisiert",
16
+ "error": {
17
+ "noApiKey": "YouTube-API-Schlüssel nicht konfiguriert",
18
+ "noChannel": "YouTube-Kanal nicht angegeben",
19
+ "connection": "Verbindung zur YouTube-API nicht möglich"
20
+ },
21
+ "widget": {
22
+ "description": "Vollständigen Kanal auf YouTube anzeigen",
23
+ "view": "YouTube-Kanal öffnen"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Videos más recientes",
5
+ "channel": "Canal",
6
+ "live": "En vivo ahora",
7
+ "upcoming": "Próximamente",
8
+ "offline": "Desconectado",
9
+ "subscribers": "suscriptores",
10
+ "views": "vistas",
11
+ "watchNow": "Ver ahora",
12
+ "viewChannel": "Ver canal",
13
+ "viewAll": "Ver todos los videos",
14
+ "noVideos": "No se encontraron videos",
15
+ "refreshed": "Actualizado",
16
+ "error": {
17
+ "noApiKey": "Clave API de YouTube no configurada",
18
+ "noChannel": "Canal de YouTube no especificado",
19
+ "connection": "No se pudo conectar con la API de YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Ver el canal completo en YouTube",
23
+ "view": "Abrir canal de YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Últimos vídeos",
5
+ "channel": "Canal",
6
+ "live": "En directo",
7
+ "upcoming": "Próximamente",
8
+ "offline": "Desconectado",
9
+ "subscribers": "suscriptores",
10
+ "views": "visualizaciones",
11
+ "watchNow": "Ver ahora",
12
+ "viewChannel": "Ver canal",
13
+ "viewAll": "Ver todos los vídeos",
14
+ "noVideos": "No se encontraron vídeos",
15
+ "refreshed": "Actualizado",
16
+ "error": {
17
+ "noApiKey": "Clave API de YouTube no configurada",
18
+ "noChannel": "Canal de YouTube no especificado",
19
+ "connection": "No se pudo conectar con la API de YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Ver el canal completo en YouTube",
23
+ "view": "Abrir canal de YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Dernières vidéos",
5
+ "channel": "Chaîne",
6
+ "live": "En direct",
7
+ "upcoming": "À venir",
8
+ "offline": "Hors ligne",
9
+ "subscribers": "abonnés",
10
+ "views": "vues",
11
+ "watchNow": "Regarder maintenant",
12
+ "viewChannel": "Voir la chaîne",
13
+ "viewAll": "Voir toutes les vidéos",
14
+ "noVideos": "Aucune vidéo trouvée",
15
+ "refreshed": "Actualisé",
16
+ "error": {
17
+ "noApiKey": "Clé API YouTube non configurée",
18
+ "noChannel": "Chaîne YouTube non spécifiée",
19
+ "connection": "Impossible de se connecter à l'API YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Voir la chaîne complète sur YouTube",
23
+ "view": "Ouvrir la chaîne YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "नवीनतम वीडियो",
5
+ "channel": "चैनल",
6
+ "live": "अभी लाइव",
7
+ "upcoming": "आने वाला",
8
+ "offline": "ऑफ़लाइन",
9
+ "subscribers": "सब्सक्राइबर",
10
+ "views": "दृश्य",
11
+ "watchNow": "अभी देखें",
12
+ "viewChannel": "चैनल देखें",
13
+ "viewAll": "सभी वीडियो देखें",
14
+ "noVideos": "कोई वीडियो नहीं मिला",
15
+ "refreshed": "ताज़ा किया गया",
16
+ "error": {
17
+ "noApiKey": "YouTube API कुंजी कॉन्फ़िगर नहीं है",
18
+ "noChannel": "YouTube चैनल निर्दिष्ट नहीं है",
19
+ "connection": "YouTube API से कनेक्ट नहीं हो सका"
20
+ },
21
+ "widget": {
22
+ "description": "YouTube पर पूरा चैनल देखें",
23
+ "view": "YouTube चैनल खोलें"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Video Terbaru",
5
+ "channel": "Saluran",
6
+ "live": "Live Sekarang",
7
+ "upcoming": "Akan Datang",
8
+ "offline": "Offline",
9
+ "subscribers": "pelanggan",
10
+ "views": "tayangan",
11
+ "watchNow": "Tonton Sekarang",
12
+ "viewChannel": "Lihat Saluran",
13
+ "viewAll": "Lihat Semua Video",
14
+ "noVideos": "Tidak ada video ditemukan",
15
+ "refreshed": "Diperbarui",
16
+ "error": {
17
+ "noApiKey": "Kunci API YouTube tidak dikonfigurasi",
18
+ "noChannel": "Saluran YouTube tidak ditentukan",
19
+ "connection": "Tidak dapat terhubung ke YouTube API"
20
+ },
21
+ "widget": {
22
+ "description": "Lihat saluran lengkap di YouTube",
23
+ "view": "Buka Saluran YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Video recenti",
5
+ "channel": "Canale",
6
+ "live": "In diretta ora",
7
+ "upcoming": "In arrivo",
8
+ "offline": "Offline",
9
+ "subscribers": "iscritti",
10
+ "views": "visualizzazioni",
11
+ "watchNow": "Guarda ora",
12
+ "viewChannel": "Visualizza canale",
13
+ "viewAll": "Visualizza tutti i video",
14
+ "noVideos": "Nessun video trovato",
15
+ "refreshed": "Aggiornato",
16
+ "error": {
17
+ "noApiKey": "Chiave API YouTube non configurata",
18
+ "noChannel": "Canale YouTube non specificato",
19
+ "connection": "Impossibile connettersi all'API di YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Visualizza il canale completo su YouTube",
23
+ "view": "Apri canale YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Nieuwste video's",
5
+ "channel": "Kanaal",
6
+ "live": "Nu live",
7
+ "upcoming": "Binnenkort",
8
+ "offline": "Offline",
9
+ "subscribers": "abonnees",
10
+ "views": "weergaven",
11
+ "watchNow": "Nu kijken",
12
+ "viewChannel": "Kanaal bekijken",
13
+ "viewAll": "Alle video's bekijken",
14
+ "noVideos": "Geen video's gevonden",
15
+ "refreshed": "Vernieuwd",
16
+ "error": {
17
+ "noApiKey": "YouTube API-sleutel niet geconfigureerd",
18
+ "noChannel": "YouTube-kanaal niet opgegeven",
19
+ "connection": "Kon geen verbinding maken met YouTube API"
20
+ },
21
+ "widget": {
22
+ "description": "Volledig kanaal op YouTube bekijken",
23
+ "view": "YouTube-kanaal openen"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Najnowsze filmy",
5
+ "channel": "Kanał",
6
+ "live": "Teraz na żywo",
7
+ "upcoming": "Nadchodzące",
8
+ "offline": "Offline",
9
+ "subscribers": "subskrybentów",
10
+ "views": "wyświetleń",
11
+ "watchNow": "Obejrzyj teraz",
12
+ "viewChannel": "Wyświetl kanał",
13
+ "viewAll": "Wyświetl wszystkie filmy",
14
+ "noVideos": "Nie znaleziono filmów",
15
+ "refreshed": "Odświeżono",
16
+ "error": {
17
+ "noApiKey": "Klucz API YouTube nie jest skonfigurowany",
18
+ "noChannel": "Kanał YouTube nie został określony",
19
+ "connection": "Nie można połączyć się z API YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Zobacz pełny kanał na YouTube",
23
+ "view": "Otwórz kanał YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Vídeos mais recentes",
5
+ "channel": "Canal",
6
+ "live": "Ao vivo agora",
7
+ "upcoming": "Em breve",
8
+ "offline": "Offline",
9
+ "subscribers": "inscritos",
10
+ "views": "visualizações",
11
+ "watchNow": "Assistir agora",
12
+ "viewChannel": "Ver canal",
13
+ "viewAll": "Ver todos os vídeos",
14
+ "noVideos": "Nenhum vídeo encontrado",
15
+ "refreshed": "Atualizado",
16
+ "error": {
17
+ "noApiKey": "Chave API do YouTube não configurada",
18
+ "noChannel": "Canal do YouTube não especificado",
19
+ "connection": "Não foi possível conectar à API do YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Ver o canal completo no YouTube",
23
+ "view": "Abrir canal do YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Vídeos mais recentes",
5
+ "channel": "Canal",
6
+ "live": "Ao vivo agora",
7
+ "upcoming": "Em breve",
8
+ "offline": "Offline",
9
+ "subscribers": "subscritores",
10
+ "views": "visualizações",
11
+ "watchNow": "Ver agora",
12
+ "viewChannel": "Ver canal",
13
+ "viewAll": "Ver todos os vídeos",
14
+ "noVideos": "Nenhum vídeo encontrado",
15
+ "refreshed": "Atualizado",
16
+ "error": {
17
+ "noApiKey": "Chave API do YouTube não configurada",
18
+ "noChannel": "Canal do YouTube não especificado",
19
+ "connection": "Não foi possível ligar à API do YouTube"
20
+ },
21
+ "widget": {
22
+ "description": "Ver o canal completo no YouTube",
23
+ "view": "Abrir canal do YouTube"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Најновији видео снимци",
5
+ "channel": "Канал",
6
+ "live": "Уживо сада",
7
+ "upcoming": "Ускоро",
8
+ "offline": "Офлајн",
9
+ "subscribers": "претплатника",
10
+ "views": "прегледа",
11
+ "watchNow": "Гледај сада",
12
+ "viewChannel": "Погледај канал",
13
+ "viewAll": "Погледај све видео снимке",
14
+ "noVideos": "Нису пронађени видео снимци",
15
+ "refreshed": "Освежено",
16
+ "error": {
17
+ "noApiKey": "YouTube API кључ није конфигурисан",
18
+ "noChannel": "YouTube канал није наведен",
19
+ "connection": "Није могуће повезати се са YouTube API"
20
+ },
21
+ "widget": {
22
+ "description": "Погледајте комплетан канал на YouTube",
23
+ "view": "Отвори YouTube канал"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "Senaste videor",
5
+ "channel": "Kanal",
6
+ "live": "Live nu",
7
+ "upcoming": "Kommande",
8
+ "offline": "Offline",
9
+ "subscribers": "prenumeranter",
10
+ "views": "visningar",
11
+ "watchNow": "Titta nu",
12
+ "viewChannel": "Visa kanal",
13
+ "viewAll": "Visa alla videor",
14
+ "noVideos": "Inga videor hittades",
15
+ "refreshed": "Uppdaterad",
16
+ "error": {
17
+ "noApiKey": "YouTube API-nyckel inte konfigurerad",
18
+ "noChannel": "YouTube-kanal inte angiven",
19
+ "connection": "Kunde inte ansluta till YouTube API"
20
+ },
21
+ "widget": {
22
+ "description": "Visa fullständig kanal på YouTube",
23
+ "view": "Öppna YouTube-kanal"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "youtube": {
3
+ "title": "YouTube",
4
+ "videos": "最新视频",
5
+ "channel": "频道",
6
+ "live": "正在直播",
7
+ "upcoming": "即将开始",
8
+ "offline": "离线",
9
+ "subscribers": "订阅者",
10
+ "views": "次观看",
11
+ "watchNow": "立即观看",
12
+ "viewChannel": "查看频道",
13
+ "viewAll": "查看所有视频",
14
+ "noVideos": "未找到视频",
15
+ "refreshed": "已刷新",
16
+ "error": {
17
+ "noApiKey": "未配置 YouTube API 密钥",
18
+ "noChannel": "未指定 YouTube 频道",
19
+ "connection": "无法连接到 YouTube API"
20
+ },
21
+ "widget": {
22
+ "description": "在 YouTube 上查看完整频道",
23
+ "view": "打开 YouTube 频道"
24
+ }
25
+ }
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-youtube",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "YouTube channel endpoint for Indiekit. Display latest videos and live status from any YouTube channel.",
5
5
  "keywords": [
6
6
  "indiekit",