me.linkna.linkinbio

linkna.me

Schema Diff

+13 -4

From

CID
bafyreiaslbzydhq...
Indexed At
2026-03-19 20:26 UTC
View this version

To

CID
bafyreidwzodhqyu...
Indexed At
2026-04-21 15:34 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

2 breaking changes, 2 non-breaking changes.

Breaking Changes (2)
  • KindChanged KindChanged { vertex_id: "me.linkna.linkinbio#widgetMap.latitude", old_kind: "object", new_kind: "string" }
  • KindChanged KindChanged { vertex_id: "me.linkna.linkinbio#widgetMap.longitude", old_kind: "object", new_kind: "string" }
Non-Breaking Changes (2)
  • AddedVertex AddedVertex { vertex_id: "me.linkna.linkinbio#widgetMap.mapImageRef" }
  • AddedEdge AddedEdge { src: "me.linkna.linkinbio#widgetMap", tgt: "me.linkna.linkinbio#widgetMap.mapImageRef", kind: "prop", name: Some("mapImageRef") }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "me.linkna.linkinbio#widgetMap.mapImageRef" }

Additional Notes

  • Breaking: KindChanged { vertex_id: "me.linkna.linkinbio#widgetMap.latitude", old_kind: "object", new_kind: "string" }
  • Breaking: KindChanged { vertex_id: "me.linkna.linkinbio#widgetMap.longitude", old_kind: "object", new_kind: "string" }
  • Non-breaking: AddedEdge { src: "me.linkna.linkinbio#widgetMap", tgt: "me.linkna.linkinbio#widgetMap.mapImageRef", kind: "prop", name: Some("mapImageRef") }
1 1
{
2 2
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "connectedServices": {
5 5
      "description": "Saved service credentials/identifiers for pre-filling widget forms.",
6 6
      "properties": {
7 7
        "githubUsername": {
8 8
          "description": "GitHub username.",
9 9
          "type": "string"
10 10
        },
11 11
        "goodreadsUserId": {
12 12
          "description": "Goodreads numeric user ID.",
13 13
          "type": "string"
14 14
        },
15 15
        "lastfmUsername": {
16 16
          "description": "Last.fm username.",
17 17
          "type": "string"
18 18
        }
19 19
      },
20 20
      "type": "object"
21 21
    },
22 22
    "githubContributionDay": {
23 23
      "description": "A single day's contribution data from GitHub.",
24 24
      "properties": {
25 25
        "count": {
26 26
          "description": "Number of contributions on this day.",
27 27
          "type": "integer"
28 28
        },
29 29
        "date": {
30 30
          "description": "Date in YYYY-MM-DD format.",
31 31
          "type": "string"
32 32
        },
33 33
        "level": {
34 34
          "description": "Contribution intensity level (0=none, 4=highest).",
35 35
          "maximum": 4,
36 36
          "minimum": 0,
37 37
          "type": "integer"
38 38
        }
39 39
      },
40 40
      "required": [
41 41
        "date",
42 42
        "count",
43 43
        "level"
44 44
      ],
45 45
      "type": "object"
46 46
    },
47 47
    "goodreadsBook": {
48 48
      "description": "A book from a Goodreads shelf.",
49 49
      "properties": {
50 50
        "author": {
51 51
          "description": "Book author.",
52 52
          "type": "string"
53 53
        },
54 54
        "coverUrl": {
55 55
          "description": "URL to the book cover image.",
56 56
          "type": "string"
57 57
        },
58 58
        "link": {
59 59
          "description": "URL to the book on Goodreads.",
60 60
          "type": "string"
61 61
        },
62 62
        "rating": {
63 63
          "description": "User's rating (1-5), or absent if unrated.",
64 64
          "maximum": 5,
65 65
          "minimum": 0,
66 66
          "type": "integer"
67 67
        },
68 68
        "title": {
69 69
          "description": "Book title.",
70 70
          "type": "string"
71 71
        }
72 72
      },
73 73
      "required": [
74 74
        "title",
75 75
        "author"
76 76
      ],
77 77
      "type": "object"
78 78
    },
79 79
    "headerCard": {
80 80
      "description": "A section header/divider card.",
81 81
      "properties": {
82 82
        "alignment": {
83 83
          "description": "Text alignment for the header. Defaults to the user's button alignment.",
84 84
          "enum": [
85 85
            "left",
86 86
            "center",
87 87
            "right"
88 88
          ],
89 89
          "type": "string"
90 90
        },
91 91
        "enabled": {
92 92
          "description": "Whether the header is visible on the public page. Defaults to true.",
93 93
          "type": "boolean"
94 94
        },
95 95
        "id": {
96 96
          "description": "Unique identifier for the card.",
97 97
          "type": "string"
98 98
        },
99 99
        "text": {
100 100
          "description": "Header text displayed as a section divider.",
101 101
          "maxLength": 100,
102 102
          "type": "string"
103 103
        },
104 104
        "type": {
105 105
          "const": "header",
106 106
          "description": "Card type discriminator.",
107 107
          "type": "string"
108 108
        }
109 109
      },
110 110
      "required": [
111 111
        "id",
112 112
        "type",
113 113
        "text"
114 114
      ],
115 115
      "type": "object"
116 116
    },
117 117
    "linkCard": {
118 118
      "description": "A standard link card.",
119 119
      "properties": {
120 120
        "enabled": {
121 121
          "description": "Whether the card is visible on the public page. Defaults to true.",
122 122
          "type": "boolean"
123 123
        },
124 124
        "highlighted": {
125 125
          "description": "Whether the card is visually highlighted.",
126 126
          "type": "boolean"
127 127
        },
128 128
        "id": {
129 129
          "description": "Unique identifier for the card.",
130 130
          "type": "string"
131 131
        },
132 132
        "text": {
133 133
          "description": "Display text for the card (falls back to URL domain if empty).",
134 134
          "maxLength": 100,
135 135
          "type": "string"
136 136
        },
137 137
        "type": {
138 138
          "description": "Card type discriminator. Value: 'link' or absent for link cards.",
139 139
          "type": "string"
140 140
        },
141 141
        "url": {
142 142
          "description": "URL the card links to.",
143 143
          "format": "uri",
144 144
          "type": "string"
145 145
        }
146 146
      },
147 147
      "type": "object"
148 148
    },
149 149
    "main": {
150 150
      "description": "A user's link-in-bio page containing cards, theme configuration, and social icons.",
151 151
      "key": "literal:self",
152 152
      "record": {
153 153
        "properties": {
154 154
          "cards": {
155 155
            "description": "Ordered list of cards on the page.",
156 156
            "items": {
157 157
              "refs": [
158 158
                "#linkCard",
159 159
                "#headerCard",
160 160
                "#widgetGoodreads",
161 161
                "#widgetGithub",
162 162
                "#widgetTealfm",
163 163
                "#widgetLastfm",
164 164
                "#widgetClock",
165 165
                "#widgetYoutube",
166 166
                "#widgetPatreon",
167 167
                "#widgetSubstack",
168 168
                "#widgetBeehiiv",
169 169
                "#widgetVideo",
170 170
                "#widgetTwitch",
171 171
                "#widgetDiscord",
172 172
                "#widgetReddit",
173 173
                "#widgetMedium",
174 174
                "#widgetMap"
175 175
              ],
176 176
              "type": "union"
177 177
            },
178 178
            "type": "array"
179 179
          },
180 180
          "connectedServices": {
181 181
            "ref": "#connectedServices",
182 182
            "type": "ref"
183 183
          },
184 184
          "socialIcons": {
185 185
            "description": "Social media icons displayed on the profile.",
186 186
            "items": {
187 187
              "ref": "#socialIcon",
188 188
              "type": "ref"
189 189
            },
190 190
            "type": "array"
191 191
          },
192 192
          "theme": {
193 193
            "description": "Deprecated: use themeConfig instead.",
194 194
            "type": "string"
195 195
          },
196 196
          "themeConfig": {
197 197
            "ref": "#themeConfig",
198 198
            "type": "ref"
199 199
          }
200 200
        },
201 201
        "required": [
202 202
          "cards"
203 203
        ],
204 204
        "type": "object"
205 205
      },
206 206
      "type": "record"
207 207
    },
208 208
    "mediumArticle": {
209 209
      "description": "A Medium article.",
210 210
      "properties": {
211 211
        "claps": {
212 212
          "description": "Number of claps.",
213 213
          "type": "integer"
214 214
        },
215 215
        "publishedAt": {
216 216
          "description": "When the article was published.",
217 217
          "type": "string"
218 218
        },
219 219
        "readingTime": {
220 220
          "description": "Estimated reading time in minutes.",
221 221
          "type": "integer"
222 222
        },
223 223
        "subtitle": {
224 224
          "description": "Article subtitle.",
225 225
          "type": "string"
226 226
        },
227 227
        "title": {
228 228
          "description": "Article title.",
229 229
          "type": "string"
230 230
        },
231 231
        "url": {
232 232
          "description": "Article URL.",
233 233
          "type": "string"
234 234
        }
235 235
      },
236 236
      "required": [
237 237
        "title",
238 238
        "url",
239 239
        "publishedAt",
240 240
        "claps"
241 241
      ],
242 242
      "type": "object"
243 243
    },
244 244
    "redditPost": {
245 245
      "description": "A Reddit post.",
246 246
      "properties": {
247 247
        "numComments": {
248 248
          "description": "Number of comments.",
249 249
          "type": "integer"
250 250
        },
251 251
        "score": {
252 252
          "description": "Post score.",
253 253
          "type": "integer"
254 254
        },
255 255
        "subreddit": {
256 256
          "description": "Subreddit name.",
257 257
          "type": "string"
258 258
        },
259 259
        "title": {
260 260
          "description": "Post title.",
261 261
          "type": "string"
262 262
        },
263 263
        "url": {
264 264
          "description": "Post URL.",
265 265
          "type": "string"
266 266
        }
267 267
      },
268 268
      "required": [
269 269
        "title",
270 270
        "subreddit",
271 271
        "url",
272 272
        "score",
273 273
        "numComments"
274 274
      ],
275 275
      "type": "object"
276 276
    },
277 277
    "socialIcon": {
278 278
      "description": "A social media icon link.",
279 279
      "properties": {
280 280
        "id": {
281 281
          "description": "Unique identifier for the icon.",
282 282
          "type": "string"
283 283
        },
284 284
        "platform": {
285 285
          "description": "Platform identifier (e.g., 'bluesky', 'twitter', 'instagram').",
286 286
          "type": "string"
287 287
        },
288 288
        "url": {
289 289
          "description": "URL to the user's profile on this platform.",
290 290
          "format": "uri",
291 291
          "type": "string"
292 292
        }
293 293
      },
294 294
      "required": [
295 295
        "id",
296 296
        "platform",
297 297
        "url"
298 298
      ],
299 299
      "type": "object"
300 300
    },
301 301
    "tealfmPlay": {
302 302
      "description": "A recently played track from teal.fm.",
303 303
      "properties": {
304 304
        "artistName": {
305 305
          "description": "Artist name(s).",
306 306
          "type": "string"
307 307
        },
308 308
        "coverUrl": {
309 309
          "description": "URL to the album cover image (from Cover Art Archive).",
310 310
          "type": "string"
311 311
        },
312 312
        "originUrl": {
313 313
          "description": "URL to the track on the original music service.",
314 314
          "type": "string"
315 315
        },
316 316
        "playedTime": {
317 317
          "description": "When the track was played.",
318 318
          "format": "datetime",
319 319
          "type": "string"
320 320
        },
321 321
        "releaseName": {
322 322
          "description": "Album/release name.",
323 323
          "type": "string"
324 324
        },
325 325
        "trackName": {
326 326
          "description": "Track/song name.",
327 327
          "type": "string"
328 328
        }
329 329
      },
330 330
      "required": [
331 331
        "trackName",
332 332
        "artistName"
333 333
      ],
334 334
      "type": "object"
335 335
    },
336 336
    "themeConfig": {
337 337
      "description": "Theme configuration for the page appearance.",
338 338
      "properties": {
339 339
        "backgroundColor": {
340 340
          "description": "Page background color.",
341 341
          "type": "string"
342 342
        },
343 343
        "backgroundGradient": {
344 344
          "description": "CSS gradient for the page background.",
345 345
          "type": "string"
346 346
        },
347 347
        "backgroundImage": {
348 348
          "accept": [
349 349
            "image/png",
350 350
            "image/jpeg",
351 351
            "image/webp"
352 352
          ],
353 353
          "description": "Background wallpaper image blob.",
354 354
          "maxSize": 10000000,
355 355
          "type": "blob"
356 356
        },
357 357
        "backgroundImageCredit": {
358 358
          "description": "Optional credit URL for the wallpaper image artist. Stored for attribution purposes only, not displayed on the public page.",
359 359
          "format": "uri",
360 360
          "type": "string"
361 361
        },
362 362
        "buttonAlignment": {
363 363
          "description": "Button content alignment. Default: left.",
364 364
          "knownValues": [
365 365
            "left",
366 366
            "right"
367 367
          ],
368 368
          "type": "string"
369 369
        },
370 370
        "buttonHoverGlow": {
371 371
          "description": "Whether buttons glow on hover. Default: false.",
372 372
          "type": "boolean"
373 373
        },
374 374
        "buttonHoverGlowColor": {
375 375
          "description": "Color for the button hover glow effect.",
376 376
          "type": "string"
377 377
        },
378 378
        "cardBackgroundColor": {
379 379
          "description": "Individual card/button background color.",
380 380
          "type": "string"
381 381
        },
382 382
        "cardBorderColor": {
383 383
          "description": "Card/button border color.",
384 384
          "type": "string"
385 385
        },
386 386
        "cardBorderRadius": {
387 387
          "description": "Card/button border radius.",
388 388
          "knownValues": [
389 389
            "none",
390 390
            "sm",
391 391
            "md",
392 392
            "lg",
393 393
            "full"
394 394
          ],
395 395
          "type": "string"
396 396
        },
397 397
        "cardHoverColor": {
398 398
          "description": "Card/button border color on hover.",
399 399
          "type": "string"
400 400
        },
401 401
        "cardShadow": {
402 402
          "description": "Card/button shadow intensity.",
403 403
          "knownValues": [
404 404
            "none",
405 405
            "sm",
406 406
            "md",
407 407
            "lg",
408 408
            "xl"
409 409
          ],
410 410
          "type": "string"
411 411
        },
412 412
        "cardTextColor": {
413 413
          "description": "Card/button text color.",
414 414
          "type": "string"
415 415
        },
416 416
        "contentCardColor": {
417 417
          "description": "Card container background color.",
418 418
          "type": "string"
419 419
        },
420 420
        "cursorSparkles": {
421 421
          "description": "Whether cursor has sparkle trail. Default: false.",
422 422
          "type": "boolean"
423 423
        },
424 424
        "cursorStyle": {
425 425
          "description": "Custom cursor style. Default: default.",
426 426
          "knownValues": [
427 427
            "default",
428 428
            "hello-kitty"
429 429
          ],
430 430
          "type": "string"
431 431
        },
432 432
        "fontFamily": {
433 433
          "description": "Font family for the page.",
434 434
          "type": "string"
435 435
        },
436 436
        "fontSize": {
437 437
          "description": "Font size. Default: md.",
438 438
          "knownValues": [
439 439
            "sm",
440 440
            "md",
441 441
            "lg"
442 442
          ],
443 443
          "type": "string"
444 444
        },
445 445
        "particles": {
446 446
          "description": "Background particle effect. Default: none.",
447 447
          "knownValues": [
448 448
            "none",
449 449
            "white",
450 450
            "blue",
451 451
            "leaves",
452 452
            "grid-sm",
453 453
            "grid-lg"
454 454
          ],
455 455
          "type": "string"
456 456
        },
457 457
        "preset": {
458 458
          "description": "Theme preset ID (e.g., 'custom', 'agate', 'air', 'astrid', 'aura').",
459 459
          "type": "string"
460 460
        },
461 461
        "profileAlignment": {
462 462
          "description": "Profile section alignment. Default: center.",
463 463
          "knownValues": [
464 464
            "left",
465 465
            "center",
466 466
            "right"
467 467
          ],
468 468
          "type": "string"
469 469
        },
470 470
        "profilePictureShape": {
471 471
          "description": "Profile picture shape. Default: circle.",
472 472
          "knownValues": [
473 473
            "circle",
474 474
            "rounded",
475 475
            "square"
476 476
          ],
477 477
          "type": "string"
478 478
        },
479 479
        "profilePictureSize": {
480 480
          "description": "Profile picture size. Default: sm.",
481 481
          "knownValues": [
482 482
            "sm",
483 483
            "md",
484 484
            "lg"
485 485
          ],
486 486
          "type": "string"
487 487
        },
488 488
        "profileTextColor": {
489 489
          "description": "Profile section text color.",
490 490
          "type": "string"
491 491
        },
492 492
        "showBranding": {
493 493
          "description": "Whether Linkname branding is visible. Default: true.",
494 494
          "type": "boolean"
495 495
        },
496 496
        "socialIconsBorderColor": {
497 497
          "description": "Border color for social icons dock/sphere.",
498 498
          "type": "string"
499 499
        },
500 500
        "socialIconsColor": {
501 501
          "description": "Social icons color.",
502 502
          "type": "string"
503 503
        },
504 504
        "socialIconsShape": {
505 505
          "description": "Social icons container shape. Default: dock.",
506 506
          "knownValues": [
507 507
            "dock",
508 508
            "sphere"
509 509
          ],
510 510
          "type": "string"
511 511
        },
512 512
        "socialIconsShapeColor": {
513 513
          "description": "Background color for social icons dock/sphere.",
514 514
          "type": "string"
515 515
        }
516 516
      },
517 517
      "type": "object"
518 518
    },
519 519
    "videoAspectRatio": {
520 520
      "description": "Video aspect ratio dimensions.",
521 521
      "properties": {
522 522
        "height": {
523 523
          "description": "Video height.",
524 524
          "type": "integer"
525 525
        },
526 526
        "width": {
527 527
          "description": "Video width.",
528 528
          "type": "integer"
529 529
        }
530 530
      },
531 531
      "required": [
532 532
        "width",
533 533
        "height"
534 534
      ],
535 535
      "type": "object"
536 536
    },
537 537
    "widgetBeehiiv": {
538 538
      "description": "A Beehiiv publication widget card.",
539 539
      "properties": {
540 540
        "description": {
541 541
          "description": "Publication description.",
542 542
          "type": "string"
543 543
        },
544 544
        "enabled": {
545 545
          "description": "Whether the widget is visible on the public page. Defaults to true.",
546 546
          "type": "boolean"
547 547
        },
548 548
        "id": {
549 549
          "description": "Unique identifier for the card.",
550 550
          "type": "string"
551 551
        },
552 552
        "imageUrl": {
553 553
          "description": "Publication image URL.",
554 554
          "type": "string"
555 555
        },
556 556
        "lastSyncedAt": {
557 557
          "description": "When the publication data was last fetched.",
558 558
          "format": "datetime",
559 559
          "type": "string"
560 560
        },
561 561
        "publicationId": {
562 562
          "description": "Beehiiv publication ID.",
563 563
          "type": "string"
564 564
        },
565 565
        "publicationName": {
566 566
          "description": "Beehiiv publication name.",
567 567
          "type": "string"
568 568
        },
569 569
        "publicationUrl": {
570 570
          "description": "URL to the Beehiiv publication.",
571 571
          "type": "string"
572 572
        },
573 573
        "size": {
574 574
          "description": "Widget display size. Default: 1x1.",
575 575
          "knownValues": [
576 576
            "1x1",
577 577
            "1x2",
578 578
            "2x2",
579 579
            "2x1"
580 580
          ],
581 581
          "type": "string"
582 582
        },
583 583
        "type": {
584 584
          "const": "beehiiv",
585 585
          "description": "Card type discriminator.",
586 586
          "type": "string"
587 587
        }
588 588
      },
589 589
      "required": [
590 590
        "id",
591 591
        "type",
592 592
        "publicationId",
593 593
        "publicationName",
594 594
        "publicationUrl"
595 595
      ],
596 596
      "type": "object"
597 597
    },
598 598
    "widgetClock": {
599 599
      "description": "A clock, countdown, or stopwatch timer widget card.",
600 600
      "properties": {
601 601
        "enabled": {
602 602
          "description": "Whether the widget is visible on the public page. Defaults to true.",
603 603
          "type": "boolean"
604 604
        },
605 605
        "id": {
606 606
          "description": "Unique identifier for the card.",
607 607
          "type": "string"
608 608
        },
609 609
        "label": {
610 610
          "description": "Optional display label for the widget.",
611 611
          "maxLength": 100,
612 612
          "type": "string"
613 613
        },
614 614
        "mode": {
615 615
          "description": "Widget mode: clock (timezone display), countdown (to a target date), or timer (interactive stopwatch).",
616 616
          "knownValues": [
617 617
            "clock",
618 618
            "countdown",
619 619
            "timer"
620 620
          ],
621 621
          "type": "string"
622 622
        },
623 623
        "size": {
624 624
          "description": "Widget display size. Default: 1x1.",
625 625
          "knownValues": [
626 626
            "1x1",
627 627
            "1x2",
628 628
            "2x2",
629 629
            "2x1"
630 630
          ],
631 631
          "type": "string"
632 632
        },
633 633
        "targetDate": {
634 634
          "description": "ISO 8601 target date for countdown mode.",
635 635
          "format": "datetime",
636 636
          "type": "string"
637 637
        },
638 638
        "timezone": {
639 639
          "description": "IANA timezone identifier for clock mode (e.g. 'America/New_York').",
640 640
          "type": "string"
641 641
        },
642 642
        "type": {
643 643
          "const": "clock",
644 644
          "description": "Card type discriminator.",
645 645
          "type": "string"
646 646
        }
647 647
      },
648 648
      "required": [
649 649
        "id",
650 650
        "type",
651 651
        "mode"
652 652
      ],
653 653
      "type": "object"
654 654
    },
655 655
    "widgetDiscord": {
656 656
      "description": "A Discord server widget card.",
657 657
      "properties": {
658 658
        "bannerUrl": {
659 659
          "description": "Server banner URL.",
660 660
          "type": "string"
661 661
        },
662 662
        "description": {
663 663
          "description": "Server description.",
664 664
          "type": "string"
665 665
        },
666 666
        "enabled": {
667 667
          "description": "Whether the widget is visible on the public page. Defaults to true.",
668 668
          "type": "boolean"
669 669
        },
670 670
        "iconUrl": {
671 671
          "description": "Server icon URL.",
672 672
          "type": "string"
673 673
        },
674 674
        "id": {
675 675
          "description": "Unique identifier for the card.",
676 676
          "type": "string"
677 677
        },
678 678
        "inviteUrl": {
679 679
          "description": "Discord invite URL.",
680 680
          "type": "string"
681 681
        },
682 682
        "lastSyncedAt": {
683 683
          "description": "When the server data was last fetched.",
684 684
          "format": "datetime",
685 685
          "type": "string"
686 686
        },
687 687
        "memberCount": {
688 688
          "description": "Total member count.",
689 689
          "type": "integer"
690 690
        },
691 691
        "presenceCount": {
692 692
          "description": "Online member count.",
693 693
          "type": "integer"
694 694
        },
695 695
        "serverId": {
696 696
          "description": "Discord server ID.",
697 697
          "type": "string"
698 698
        },
699 699
        "serverName": {
700 700
          "description": "Discord server name.",
701 701
          "type": "string"
702 702
        },
703 703
        "size": {
704 704
          "description": "Widget display size. Default: 1x1.",
705 705
          "knownValues": [
706 706
            "1x1",
707 707
            "1x2",
708 708
            "2x2",
709 709
            "2x1"
710 710
          ],
711 711
          "type": "string"
712 712
        },
713 713
        "type": {
714 714
          "const": "discord",
715 715
          "description": "Card type discriminator.",
716 716
          "type": "string"
717 717
        }
718 718
      },
719 719
      "required": [
720 720
        "id",
721 721
        "type",
722 722
        "serverId",
723 723
        "serverName",
724 724
        "inviteUrl"
725 725
      ],
726 726
      "type": "object"
727 727
    },
728 728
    "widgetGithub": {
729 729
      "description": "A GitHub contributions graph widget card.",
730 730
      "properties": {
731 731
        "contributions": {
732 732
          "description": "Contribution data for the last year.",
733 733
          "items": {
734 734
            "ref": "#githubContributionDay",
735 735
            "type": "ref"
736 736
          },
737 737
          "type": "array"
738 738
        },
739 739
        "enabled": {
740 740
          "description": "Whether the widget is visible on the public page. Defaults to true.",
741 741
          "type": "boolean"
742 742
        },
743 743
        "githubUsername": {
744 744
          "description": "GitHub username.",
745 745
          "type": "string"
746 746
        },
747 747
        "id": {
748 748
          "description": "Unique identifier for the card.",
749 749
          "type": "string"
750 750
        },
751 751
        "lastSyncedAt": {
752 752
          "description": "When the contribution data was last fetched from GitHub.",
753 753
          "format": "datetime",
754 754
          "type": "string"
755 755
        },
756 756
        "size": {
757 757
          "description": "Widget display size. Default: 1x1.",
758 758
          "knownValues": [
759 759
            "1x1",
760 760
            "1x2",
761 761
            "2x2"
762 762
          ],
763 763
          "type": "string"
764 764
        },
765 765
        "totalContributions": {
766 766
          "description": "Total number of contributions in the last year.",
767 767
          "type": "integer"
768 768
        },
769 769
        "type": {
770 770
          "const": "github",
771 771
          "description": "Card type discriminator.",
772 772
          "type": "string"
773 773
        }
774 774
      },
775 775
      "required": [
776 776
        "id",
777 777
        "type",
778 778
        "githubUsername",
779 779
        "contributions"
780 780
      ],
781 781
      "type": "object"
782 782
    },
783 783
    "widgetGoodreads": {
784 784
      "description": "A Goodreads bookshelf widget card.",
785 785
      "properties": {
786 786
        "books": {
787 787
          "description": "Books on the currently-reading shelf.",
788 788
          "items": {
789 789
            "ref": "#goodreadsBook",
790 790
            "type": "ref"
791 791
          },
792 792
          "type": "array"
793 793
        },
794 794
        "enabled": {
795 795
          "description": "Whether the widget is visible on the public page. Defaults to true.",
796 796
          "type": "boolean"
797 797
        },
798 798
        "goodreadsUserId": {
799 799
          "description": "Goodreads numeric user ID.",
800 800
          "type": "string"
801 801
        },
802 802
        "id": {
803 803
          "description": "Unique identifier for the card.",
804 804
          "type": "string"
805 805
        },
806 806
        "lastSyncedAt": {
807 807
          "description": "When the book data was last fetched from Goodreads.",
808 808
          "format": "datetime",
809 809
          "type": "string"
810 810
        },
811 811
        "readBooks": {
812 812
          "description": "Books on the read shelf (used by 1x2 size).",
813 813
          "items": {
814 814
            "ref": "#goodreadsBook",
815 815
            "type": "ref"
816 816
          },
817 817
          "type": "array"
818 818
        },
819 819
        "shelf": {
820 820
          "description": "Shelf name (currently-reading, read, or to-read).",
821 821
          "type": "string"
822 822
        },
823 823
        "size": {
824 824
          "description": "Widget display size. Default: 1x1.",
825 825
          "knownValues": [
826 826
            "1x1",
827 827
            "1x2",
828 828
            "2x2"
829 829
          ],
830 830
          "type": "string"
831 831
        },
832 832
        "type": {
833 833
          "const": "goodreads",
834 834
          "description": "Card type discriminator.",
835 835
          "type": "string"
836 836
        }
837 837
      },
838 838
      "required": [
839 839
        "id",
840 840
        "type",
841 841
        "goodreadsUserId",
842 842
        "shelf",
843 843
        "books"
844 844
      ],
845 845
      "type": "object"
846 846
    },
847 847
    "widgetLastfm": {
848 848
      "description": "A Last.fm recently played tracks widget card.",
849 849
      "properties": {
850 850
        "coverArtNotice": {
851 851
          "description": "Copyright notice for cover art images.",
852 852
          "type": "string"
853 853
        },
854 854
        "enabled": {
855 855
          "description": "Whether the widget is visible on the public page. Defaults to true.",
856 856
          "type": "boolean"
857 857
        },
858 858
        "id": {
859 859
          "description": "Unique identifier for the card.",
860 860
          "type": "string"
861 861
        },
862 862
        "lastSyncedAt": {
863 863
          "description": "When the play data was last fetched from Last.fm.",
864 864
          "format": "datetime",
865 865
          "type": "string"
866 866
        },
867 867
        "lastfmUsername": {
868 868
          "description": "Last.fm username for fetching scrobbles.",
869 869
          "type": "string"
870 870
        },
871 871
        "plays": {
872 872
          "description": "Recently played tracks from Last.fm.",
873 873
          "items": {
874 874
            "ref": "#tealfmPlay",
875 875
            "type": "ref"
876 876
          },
877 877
          "type": "array"
878 878
        },
879 879
        "size": {
880 880
          "description": "Widget display size. Default: 1x1.",
881 881
          "knownValues": [
882 882
            "1x1",
883 883
            "1x2",
884 884
            "2x2"
885 885
          ],
886 886
          "type": "string"
887 887
        },
888 888
        "type": {
889 889
          "const": "lastfm",
890 890
          "description": "Card type discriminator.",
891 891
          "type": "string"
892 892
        }
893 893
      },
894 894
      "required": [
895 895
        "id",
896 896
        "type",
897 897
        "lastfmUsername",
898 898
        "plays"
899 899
      ],
900 900
      "type": "object"
901 901
    },
902 902
    "widgetMap": {
903 903
      "description": "A map location widget card.",
904 904
      "properties": {
905 905
        "enabled": {
906 906
          "description": "Whether the widget is visible on the public page. Defaults to true.",
907 907
          "type": "boolean"
908 908
        },
909 909
        "id": {
910 910
          "description": "Unique identifier for the card.",
911 911
          "type": "string"
912 912
        },
913 913
        "latitude": {
914 -
          "description": "Latitude coordinate.",
915 -
          "type": "number"
914 +
          "description": "Latitude coordinate as string (AT Protocol does not support floats).",
915 +
          "type": "string"
916 916
        },
917 917
        "locationName": {
918 918
          "description": "Display name for the location.",
919 919
          "type": "string"
920 920
        },
921 921
        "longitude": {
922 -
          "description": "Longitude coordinate.",
923 -
          "type": "number"
922 +
          "description": "Longitude coordinate as string (AT Protocol does not support floats).",
923 +
          "type": "string"
924 +
        },
925 +
        "mapImageRef": {
926 +
          "accept": [
927 +
            "image/png",
928 +
            "image/jpeg"
929 +
          ],
930 +
          "description": "Cached static map image blob to avoid repeated Stadia Maps API calls.",
931 +
          "maxSize": 5000000,
932 +
          "type": "blob"
924 933
        },
925 934
        "size": {
926 935
          "description": "Widget display size. Default: 1x1.",
927 936
          "knownValues": [
928 937
            "1x1",
929 938
            "1x2",
930 939
            "2x2",
931 940
            "2x1"
932 941
          ],
933 942
          "type": "string"
934 943
        },
935 944
        "style": {
936 945
          "description": "Map style. Default: light.",
937 946
          "knownValues": [
938 947
            "light",
939 948
            "dark"
940 949
          ],
941 950
          "type": "string"
942 951
        },
943 952
        "type": {
944 953
          "const": "map",
945 954
          "description": "Card type discriminator.",
946 955
          "type": "string"
947 956
        },
948 957
        "zoom": {
949 958
          "description": "Map zoom level (1-18). Default: 12.",
950 959
          "type": "integer"
951 960
        }
952 961
      },
953 962
      "required": [
954 963
        "id",
955 964
        "type",
956 965
        "locationName",
957 966
        "latitude",
958 967
        "longitude"
959 968
      ],
960 969
      "type": "object"
961 970
    },
962 971
    "widgetMedium": {
963 972
      "description": "A Medium profile widget card.",
964 973
      "properties": {
965 974
        "articles": {
966 975
          "description": "Recent articles.",
967 976
          "items": {
968 977
            "ref": "#mediumArticle",
969 978
            "type": "ref"
970 979
          },
971 980
          "type": "array"
972 981
        },
973 982
        "bio": {
974 983
          "description": "Medium bio.",
975 984
          "type": "string"
976 985
        },
977 986
        "displayName": {
978 987
          "description": "Medium display name.",
979 988
          "type": "string"
980 989
        },
981 990
        "enabled": {
982 991
          "description": "Whether the widget is visible on the public page. Defaults to true.",
983 992
          "type": "boolean"
984 993
        },
985 994
        "followerCount": {
986 995
          "description": "Number of followers.",
987 996
          "type": "integer"
988 997
        },
989 998
        "id": {
990 999
          "description": "Unique identifier for the card.",
991 1000
          "type": "string"
992 1001
        },
993 1002
        "lastSyncedAt": {
994 1003
          "description": "When the Medium data was last fetched.",
995 1004
          "format": "datetime",
996 1005
          "type": "string"
997 1006
        },
998 1007
        "profileUrl": {
999 1008
          "description": "Medium profile URL.",
1000 1009
          "type": "string"
1001 1010
        },
1002 1011
        "size": {
1003 1012
          "description": "Widget display size. Default: 1x1.",
1004 1013
          "knownValues": [
1005 1014
            "1x1",
1006 1015
            "1x2",
1007 1016
            "2x2",
1008 1017
            "2x1"
1009 1018
          ],
1010 1019
          "type": "string"
1011 1020
        },
1012 1021
        "type": {
1013 1022
          "const": "medium",
1014 1023
          "description": "Card type discriminator.",
1015 1024
          "type": "string"
1016 1025
        },
1017 1026
        "username": {
1018 1027
          "description": "Medium username.",
1019 1028
          "type": "string"
1020 1029
        }
1021 1030
      },
1022 1031
      "required": [
1023 1032
        "id",
1024 1033
        "type",
1025 1034
        "username",
1026 1035
        "profileUrl"
1027 1036
      ],
1028 1037
      "type": "object"
1029 1038
    },
1030 1039
    "widgetPatreon": {
1031 1040
      "description": "A Patreon campaign widget card.",
1032 1041
      "properties": {
1033 1042
        "campaignId": {
1034 1043
          "description": "Patreon campaign ID.",
1035 1044
          "type": "string"
1036 1045
        },
1037 1046
        "campaignUrl": {
1038 1047
          "description": "URL to the Patreon campaign.",
1039 1048
          "type": "string"
1040 1049
        },
1041 1050
        "creationName": {
1042 1051
          "description": "Name of the creation/project.",
1043 1052
          "type": "string"
1044 1053
        },
1045 1054
        "creatorName": {
1046 1055
          "description": "Patreon creator name.",
1047 1056
          "type": "string"
1048 1057
        },
1049 1058
        "enabled": {
1050 1059
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1051 1060
          "type": "boolean"
1052 1061
        },
1053 1062
        "id": {
1054 1063
          "description": "Unique identifier for the card.",
1055 1064
          "type": "string"
1056 1065
        },
1057 1066
        "imageUrl": {
1058 1067
          "description": "Campaign image URL.",
1059 1068
          "type": "string"
1060 1069
        },
1061 1070
        "lastSyncedAt": {
1062 1071
          "description": "When the campaign data was last fetched.",
1063 1072
          "format": "datetime",
1064 1073
          "type": "string"
1065 1074
        },
1066 1075
        "patronCount": {
1067 1076
          "description": "Number of patrons.",
1068 1077
          "type": "integer"
1069 1078
        },
1070 1079
        "postCount": {
1071 1080
          "description": "Number of posts.",
1072 1081
          "type": "integer"
1073 1082
        },
1074 1083
        "size": {
1075 1084
          "description": "Widget display size. Default: 1x1.",
1076 1085
          "knownValues": [
1077 1086
            "1x1",
1078 1087
            "1x2",
1079 1088
            "2x2",
1080 1089
            "2x1"
1081 1090
          ],
1082 1091
          "type": "string"
1083 1092
        },
1084 1093
        "type": {
1085 1094
          "const": "patreon",
1086 1095
          "description": "Card type discriminator.",
1087 1096
          "type": "string"
1088 1097
        }
1089 1098
      },
1090 1099
      "required": [
1091 1100
        "id",
1092 1101
        "type",
1093 1102
        "campaignId",
1094 1103
        "creatorName",
1095 1104
        "campaignUrl"
1096 1105
      ],
1097 1106
      "type": "object"
1098 1107
    },
1099 1108
    "widgetReddit": {
1100 1109
      "description": "A Reddit profile widget card.",
1101 1110
      "properties": {
1102 1111
        "avatarUrl": {
1103 1112
          "description": "Reddit avatar URL.",
1104 1113
          "type": "string"
1105 1114
        },
1106 1115
        "commentKarma": {
1107 1116
          "description": "Comment karma.",
1108 1117
          "type": "integer"
1109 1118
        },
1110 1119
        "enabled": {
1111 1120
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1112 1121
          "type": "boolean"
1113 1122
        },
1114 1123
        "id": {
1115 1124
          "description": "Unique identifier for the card.",
1116 1125
          "type": "string"
1117 1126
        },
1118 1127
        "karma": {
1119 1128
          "description": "Total karma.",
1120 1129
          "type": "integer"
1121 1130
        },
1122 1131
        "lastSyncedAt": {
1123 1132
          "description": "When the Reddit data was last fetched.",
1124 1133
          "format": "datetime",
1125 1134
          "type": "string"
1126 1135
        },
1127 1136
        "linkKarma": {
1128 1137
          "description": "Link karma.",
1129 1138
          "type": "integer"
1130 1139
        },
1131 1140
        "profileUrl": {
1132 1141
          "description": "Reddit profile URL.",
1133 1142
          "type": "string"
1134 1143
        },
1135 1144
        "recentPosts": {
1136 1145
          "description": "Recent posts.",
1137 1146
          "items": {
1138 1147
            "ref": "#redditPost",
1139 1148
            "type": "ref"
1140 1149
          },
1141 1150
          "type": "array"
1142 1151
        },
1143 1152
        "size": {
1144 1153
          "description": "Widget display size. Default: 1x1.",
1145 1154
          "knownValues": [
1146 1155
            "1x1",
1147 1156
            "1x2",
1148 1157
            "2x2",
1149 1158
            "2x1"
1150 1159
          ],
1151 1160
          "type": "string"
1152 1161
        },
1153 1162
        "type": {
1154 1163
          "const": "reddit",
1155 1164
          "description": "Card type discriminator.",
1156 1165
          "type": "string"
1157 1166
        },
1158 1167
        "username": {
1159 1168
          "description": "Reddit username.",
1160 1169
          "type": "string"
1161 1170
        }
1162 1171
      },
1163 1172
      "required": [
1164 1173
        "id",
1165 1174
        "type",
1166 1175
        "username",
1167 1176
        "profileUrl"
1168 1177
      ],
1169 1178
      "type": "object"
1170 1179
    },
1171 1180
    "widgetSubstack": {
1172 1181
      "description": "A Substack publication widget card.",
1173 1182
      "properties": {
1174 1183
        "authorName": {
1175 1184
          "description": "Author name.",
1176 1185
          "type": "string"
1177 1186
        },
1178 1187
        "coverImageUrl": {
1179 1188
          "description": "Publication cover image URL.",
1180 1189
          "type": "string"
1181 1190
        },
1182 1191
        "description": {
1183 1192
          "description": "Publication description.",
1184 1193
          "type": "string"
1185 1194
        },
1186 1195
        "enabled": {
1187 1196
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1188 1197
          "type": "boolean"
1189 1198
        },
1190 1199
        "id": {
1191 1200
          "description": "Unique identifier for the card.",
1192 1201
          "type": "string"
1193 1202
        },
1194 1203
        "imageUrl": {
1195 1204
          "description": "Publication image URL.",
1196 1205
          "type": "string"
1197 1206
        },
1198 1207
        "lastSyncedAt": {
1199 1208
          "description": "When the publication data was last fetched.",
1200 1209
          "format": "datetime",
1201 1210
          "type": "string"
1202 1211
        },
1203 1212
        "postCount": {
1204 1213
          "description": "Number of posts.",
1205 1214
          "type": "integer"
1206 1215
        },
1207 1216
        "publicationId": {
1208 1217
          "description": "Substack publication ID.",
1209 1218
          "type": "string"
1210 1219
        },
1211 1220
        "publicationName": {
1212 1221
          "description": "Substack publication name.",
1213 1222
          "type": "string"
1214 1223
        },
1215 1224
        "publicationUrl": {
1216 1225
          "description": "URL to the Substack publication.",
1217 1226
          "type": "string"
1218 1227
        },
1219 1228
        "size": {
1220 1229
          "description": "Widget display size. Default: 1x1.",
1221 1230
          "knownValues": [
1222 1231
            "1x1",
1223 1232
            "1x2",
1224 1233
            "2x2",
1225 1234
            "2x1"
1226 1235
          ],
1227 1236
          "type": "string"
1228 1237
        },
1229 1238
        "subscriberCount": {
1230 1239
          "description": "Number of subscribers.",
1231 1240
          "type": "integer"
1232 1241
        },
1233 1242
        "type": {
1234 1243
          "const": "substack",
1235 1244
          "description": "Card type discriminator.",
1236 1245
          "type": "string"
1237 1246
        }
1238 1247
      },
1239 1248
      "required": [
1240 1249
        "id",
1241 1250
        "type",
1242 1251
        "publicationId",
1243 1252
        "publicationName",
1244 1253
        "publicationUrl"
1245 1254
      ],
1246 1255
      "type": "object"
1247 1256
    },
1248 1257
    "widgetTealfm": {
1249 1258
      "description": "A teal.fm recently played tracks widget card.",
1250 1259
      "properties": {
1251 1260
        "coverArtNotice": {
1252 1261
          "description": "Copyright notice for cover art images.",
1253 1262
          "type": "string"
1254 1263
        },
1255 1264
        "enabled": {
1256 1265
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1257 1266
          "type": "boolean"
1258 1267
        },
1259 1268
        "id": {
1260 1269
          "description": "Unique identifier for the card.",
1261 1270
          "type": "string"
1262 1271
        },
1263 1272
        "lastSyncedAt": {
1264 1273
          "description": "When the play data was last fetched from the PDS.",
1265 1274
          "format": "datetime",
1266 1275
          "type": "string"
1267 1276
        },
1268 1277
        "plays": {
1269 1278
          "description": "Recently played tracks.",
1270 1279
          "items": {
1271 1280
            "ref": "#tealfmPlay",
1272 1281
            "type": "ref"
1273 1282
          },
1274 1283
          "type": "array"
1275 1284
        },
1276 1285
        "size": {
1277 1286
          "description": "Widget display size. Default: 1x1.",
1278 1287
          "knownValues": [
1279 1288
            "1x1",
1280 1289
            "1x2",
1281 1290
            "2x2"
1282 1291
          ],
1283 1292
          "type": "string"
1284 1293
        },
1285 1294
        "source": {
1286 1295
          "description": "Data source for the widget. 'lastfm' for imported Last.fm scrobbles, 'tealfm' (default) for native AT Protocol plays.",
1287 1296
          "knownValues": [
1288 1297
            "tealfm",
1289 1298
            "lastfm"
1290 1299
          ],
1291 1300
          "type": "string"
1292 1301
        },
1293 1302
        "type": {
1294 1303
          "const": "tealfm",
1295 1304
          "description": "Card type discriminator.",
1296 1305
          "type": "string"
1297 1306
        }
1298 1307
      },
1299 1308
      "required": [
1300 1309
        "id",
1301 1310
        "type",
1302 1311
        "plays"
1303 1312
      ],
1304 1313
      "type": "object"
1305 1314
    },
1306 1315
    "widgetTwitch": {
1307 1316
      "description": "A Twitch channel widget card.",
1308 1317
      "properties": {
1309 1318
        "displayName": {
1310 1319
          "description": "Twitch display name.",
1311 1320
          "type": "string"
1312 1321
        },
1313 1322
        "enabled": {
1314 1323
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1315 1324
          "type": "boolean"
1316 1325
        },
1317 1326
        "id": {
1318 1327
          "description": "Unique identifier for the card.",
1319 1328
          "type": "string"
1320 1329
        },
1321 1330
        "isLive": {
1322 1331
          "description": "Whether the channel is currently live.",
1323 1332
          "type": "boolean"
1324 1333
        },
1325 1334
        "lastSyncedAt": {
1326 1335
          "description": "When the channel data was last fetched.",
1327 1336
          "format": "datetime",
1328 1337
          "type": "string"
1329 1338
        },
1330 1339
        "profileImageUrl": {
1331 1340
          "description": "Twitch profile image URL.",
1332 1341
          "type": "string"
1333 1342
        },
1334 1343
        "size": {
1335 1344
          "description": "Widget display size. Default: 1x1.",
1336 1345
          "knownValues": [
1337 1346
            "1x1",
1338 1347
            "1x2",
1339 1348
            "2x2",
1340 1349
            "2x1"
1341 1350
          ],
1342 1351
          "type": "string"
1343 1352
        },
1344 1353
        "streamGame": {
1345 1354
          "description": "Current stream game/category.",
1346 1355
          "type": "string"
1347 1356
        },
1348 1357
        "streamTitle": {
1349 1358
          "description": "Current stream title.",
1350 1359
          "type": "string"
1351 1360
        },
1352 1361
        "type": {
1353 1362
          "const": "twitch",
1354 1363
          "description": "Card type discriminator.",
1355 1364
          "type": "string"
1356 1365
        },
1357 1366
        "username": {
1358 1367
          "description": "Twitch username.",
1359 1368
          "type": "string"
1360 1369
        },
1361 1370
        "viewerCount": {
1362 1371
          "description": "Current viewer count.",
1363 1372
          "type": "integer"
1364 1373
        }
1365 1374
      },
1366 1375
      "required": [
1367 1376
        "id",
1368 1377
        "type",
1369 1378
        "username"
1370 1379
      ],
1371 1380
      "type": "object"
1372 1381
    },
1373 1382
    "widgetVideo": {
1374 1383
      "description": "A video widget card.",
1375 1384
      "properties": {
1376 1385
        "alt": {
1377 1386
          "description": "Alt text for accessibility.",
1378 1387
          "maxLength": 1000,
1379 1388
          "type": "string"
1380 1389
        },
1381 1390
        "aspectRatio": {
1382 1391
          "description": "Video aspect ratio.",
1383 1392
          "ref": "#videoAspectRatio",
1384 1393
          "type": "ref"
1385 1394
        },
1386 1395
        "createdAt": {
1387 1396
          "description": "When the video was uploaded.",
1388 1397
          "format": "datetime",
1389 1398
          "type": "string"
1390 1399
        },
1391 1400
        "did": {
1392 1401
          "description": "Author DID for constructing PDS blob URLs.",
1393 1402
          "type": "string"
1394 1403
        },
1395 1404
        "enabled": {
1396 1405
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1397 1406
          "type": "boolean"
1398 1407
        },
1399 1408
        "id": {
1400 1409
          "description": "Unique identifier for the card.",
1401 1410
          "type": "string"
1402 1411
        },
1403 1412
        "loop": {
1404 1413
          "description": "Whether the video loops. Defaults to true.",
1405 1414
          "type": "boolean"
1406 1415
        },
1407 1416
        "muted": {
1408 1417
          "description": "Whether the video is muted. Defaults to true.",
1409 1418
          "type": "boolean"
1410 1419
        },
1411 1420
        "showOverlay": {
1412 1421
          "description": "Whether to show the title overlay. Defaults to false.",
1413 1422
          "type": "boolean"
1414 1423
        },
1415 1424
        "size": {
1416 1425
          "description": "Widget display size. Default: 1x1.",
1417 1426
          "knownValues": [
1418 1427
            "1x1",
1419 1428
            "1x2",
1420 1429
            "2x2",
1421 1430
            "2x1"
1422 1431
          ],
1423 1432
          "type": "string"
1424 1433
        },
1425 1434
        "title": {
1426 1435
          "description": "Video title overlay.",
1427 1436
          "maxLength": 100,
1428 1437
          "type": "string"
1429 1438
        },
1430 1439
        "type": {
1431 1440
          "const": "video",
1432 1441
          "description": "Card type discriminator.",
1433 1442
          "type": "string"
1434 1443
        },
1435 1444
        "videoBlobRef": {
1436 1445
          "description": "Reference to the uploaded video blob.",
1437 1446
          "type": "blob"
1438 1447
        }
1439 1448
      },
1440 1449
      "required": [
1441 1450
        "id",
1442 1451
        "type",
1443 1452
        "videoBlobRef",
1444 1453
        "did"
1445 1454
      ],
1446 1455
      "type": "object"
1447 1456
    },
1448 1457
    "widgetYoutube": {
1449 1458
      "description": "A YouTube channel widget card.",
1450 1459
      "properties": {
1451 1460
        "channelId": {
1452 1461
          "description": "YouTube channel ID.",
1453 1462
          "type": "string"
1454 1463
        },
1455 1464
        "channelName": {
1456 1465
          "description": "YouTube channel name.",
1457 1466
          "type": "string"
1458 1467
        },
1459 1468
        "channelUrl": {
1460 1469
          "description": "URL to the YouTube channel.",
1461 1470
          "type": "string"
1462 1471
        },
1463 1472
        "enabled": {
1464 1473
          "description": "Whether the widget is visible on the public page. Defaults to true.",
1465 1474
          "type": "boolean"
1466 1475
        },
1467 1476
        "id": {
1468 1477
          "description": "Unique identifier for the card.",
1469 1478
          "type": "string"
1470 1479
        },
1471 1480
        "lastSyncedAt": {
1472 1481
          "description": "When the video data was last fetched.",
1473 1482
          "format": "datetime",
1474 1483
          "type": "string"
1475 1484
        },
1476 1485
        "latestVideo": {
1477 1486
          "description": "The latest video from the channel.",
1478 1487
          "ref": "#youtubeVideo",
1479 1488
          "type": "ref"
1480 1489
        },
1481 1490
        "size": {
1482 1491
          "description": "Widget display size. Default: 1x1.",
1483 1492
          "knownValues": [
1484 1493
            "1x1",
1485 1494
            "1x2",
1486 1495
            "2x2",
1487 1496
            "2x1"
1488 1497
          ],
1489 1498
          "type": "string"
1490 1499
        },
1491 1500
        "type": {
1492 1501
          "const": "youtube",
1493 1502
          "description": "Card type discriminator.",
1494 1503
          "type": "string"
1495 1504
        }
1496 1505
      },
1497 1506
      "required": [
1498 1507
        "id",
1499 1508
        "type",
1500 1509
        "channelId",
1501 1510
        "channelName",
1502 1511
        "channelUrl"
1503 1512
      ],
1504 1513
      "type": "object"
1505 1514
    },
1506 1515
    "youtubeVideo": {
1507 1516
      "description": "A YouTube video.",
1508 1517
      "properties": {
1509 1518
        "isShort": {
1510 1519
          "description": "Whether this is a YouTube Short.",
1511 1520
          "type": "boolean"
1512 1521
        },
1513 1522
        "publishedAt": {
1514 1523
          "description": "When the video was published.",
1515 1524
          "type": "string"
1516 1525
        },
1517 1526
        "title": {
1518 1527
          "description": "Video title.",
1519 1528
          "type": "string"
1520 1529
        },
1521 1530
        "videoId": {
1522 1531
          "description": "YouTube video ID.",
1523 1532
          "type": "string"
1524 1533
        }
1525 1534
      },
1526 1535
      "required": [
1527 1536
        "videoId",
1528 1537
        "title",
1529 1538
        "publishedAt"
1530 1539
      ],
1531 1540
      "type": "object"
1532 1541
    }
1533 1542
  },
1534 1543
  "id": "me.linkna.linkinbio",
1535 1544
  "lexicon": 1
1536 1545
}

Compare Other Versions

Lexicon Garden

@