roast-my-design-system 3.6.0 → 3.7.0
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 +6 -3
- package/package.json +1 -1
- package/skills/roast-my-design-system/scripts/benchmark/benchmark.json +332 -41
- package/skills/roast-my-design-system/scripts/diagnose/index.mjs +8 -13
- package/skills/roast-my-design-system/scripts/lib/neverimported.mjs +17 -0
- package/skills/roast-my-design-system/scripts/rules/build.mjs +2 -7
package/README.md
CHANGED
|
@@ -24,11 +24,11 @@ Your AI agent (Claude, Cursor, Copilot) builds UI by imitating what's already in
|
|
|
24
24
|
|
|
25
25
|
The full report for vercel/ai-chatbot, top to bottom:
|
|
26
26
|
|
|
27
|
-

|
|
28
28
|
|
|
29
29
|
The same report in light mode (one file, built-in toggle):
|
|
30
30
|
|
|
31
|
-

|
|
32
32
|
|
|
33
33
|
## What makes the numbers trustworthy
|
|
34
34
|
|
|
@@ -120,6 +120,9 @@ Three real roasts of public repos, hosted as-is (the same self-contained HTML th
|
|
|
120
120
|
| Duplicated components | 0 | 14 | 10 |
|
|
121
121
|
| Inline style blocks | 0 | 42 | 12 |
|
|
122
122
|
| Arbitrary Tailwind values | ~20 | 91 | 0 |
|
|
123
|
+
| Near-identical colour pairs | 0 | 2 | 1 |
|
|
124
|
+
| !important declarations | 0 | 5 | 3 |
|
|
125
|
+
| Components never imported | 0 | 0 | 0 |
|
|
123
126
|
|
|
124
127
|
Yes, the median repo is already a mess. That's the point.
|
|
125
128
|
|
|
@@ -127,4 +130,4 @@ Yes, the median repo is already a mess. That's the point.
|
|
|
127
130
|
|
|
128
131
|
MIT
|
|
129
132
|
|
|
130
|
-
Built and designed by <a href="https://gregkozakiewicz.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/pencilrebel/roast-my-design-system/main/assets/gk-mark-dark.png?v=3.
|
|
133
|
+
Built and designed by <a href="https://gregkozakiewicz.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/pencilrebel/roast-my-design-system/main/assets/gk-mark-dark.png?v=3.7.0"><img src="https://raw.githubusercontent.com/pencilrebel/roast-my-design-system/main/assets/gk-mark.png?v=3.7.0" height="15" alt="GK mark"></picture> Greg Kozakiewicz</a>.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roast-my-design-system",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Roast your design system with real data. A deterministic, zero-dependency scanner that counts every colour, grey, spacing value, typeface, duplicated component, inline style and arbitrary Tailwind value in your repo, scores it 0-100 against Ideal Design System norms and a 30-repo benchmark, generates a shareable HTML diagnosis, and with --rules writes the agent rules file (CLAUDE.md, .cursor/rules) that stops the mess coming back.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"design-system",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"builtAt": "2026-08-
|
|
2
|
+
"builtAt": "2026-08-03T16:33:32.652Z",
|
|
3
3
|
"repoCount": 30,
|
|
4
4
|
"ideal2026": {
|
|
5
5
|
"colors": {
|
|
@@ -38,6 +38,18 @@
|
|
|
38
38
|
"value": 0,
|
|
39
39
|
"note": "styling belongs to the system"
|
|
40
40
|
},
|
|
41
|
+
"nearPairs": {
|
|
42
|
+
"value": 0,
|
|
43
|
+
"note": "near-identical colours are copy-paste, not decisions"
|
|
44
|
+
},
|
|
45
|
+
"important": {
|
|
46
|
+
"value": 0,
|
|
47
|
+
"note": "!important is the cascade admitting defeat"
|
|
48
|
+
},
|
|
49
|
+
"neverImported": {
|
|
50
|
+
"value": 0,
|
|
51
|
+
"note": "a system component nobody imports is dead weight"
|
|
52
|
+
},
|
|
41
53
|
"arbitrary": {
|
|
42
54
|
"value": 20,
|
|
43
55
|
"note": "bracket escape hatches; a handful of deliberate exceptions"
|
|
@@ -104,7 +116,7 @@
|
|
|
104
116
|
174,
|
|
105
117
|
206,
|
|
106
118
|
246,
|
|
107
|
-
|
|
119
|
+
303,
|
|
108
120
|
385,
|
|
109
121
|
403,
|
|
110
122
|
1645
|
|
@@ -112,7 +124,7 @@
|
|
|
112
124
|
"p25": 38,
|
|
113
125
|
"median": 96,
|
|
114
126
|
"p75": 170,
|
|
115
|
-
"p90":
|
|
127
|
+
"p90": 311
|
|
116
128
|
},
|
|
117
129
|
"greys": {
|
|
118
130
|
"values": [
|
|
@@ -373,7 +385,7 @@
|
|
|
373
385
|
95,
|
|
374
386
|
103,
|
|
375
387
|
115,
|
|
376
|
-
|
|
388
|
+
189
|
|
377
389
|
],
|
|
378
390
|
"p25": 1,
|
|
379
391
|
"median": 14,
|
|
@@ -397,7 +409,7 @@
|
|
|
397
409
|
23,
|
|
398
410
|
37,
|
|
399
411
|
41,
|
|
400
|
-
|
|
412
|
+
43,
|
|
401
413
|
46,
|
|
402
414
|
47,
|
|
403
415
|
51,
|
|
@@ -411,7 +423,7 @@
|
|
|
411
423
|
122,
|
|
412
424
|
173,
|
|
413
425
|
1178,
|
|
414
|
-
|
|
426
|
+
2923
|
|
415
427
|
],
|
|
416
428
|
"p25": 8,
|
|
417
429
|
"median": 42,
|
|
@@ -443,7 +455,7 @@
|
|
|
443
455
|
234,
|
|
444
456
|
271,
|
|
445
457
|
321,
|
|
446
|
-
|
|
458
|
+
380,
|
|
447
459
|
407,
|
|
448
460
|
468,
|
|
449
461
|
470,
|
|
@@ -456,6 +468,120 @@
|
|
|
456
468
|
"p75": 309,
|
|
457
469
|
"p90": 472
|
|
458
470
|
},
|
|
471
|
+
"nearPairs": {
|
|
472
|
+
"values": [
|
|
473
|
+
0,
|
|
474
|
+
0,
|
|
475
|
+
0,
|
|
476
|
+
0,
|
|
477
|
+
0,
|
|
478
|
+
0,
|
|
479
|
+
0,
|
|
480
|
+
0,
|
|
481
|
+
0,
|
|
482
|
+
0,
|
|
483
|
+
0,
|
|
484
|
+
1,
|
|
485
|
+
1,
|
|
486
|
+
2,
|
|
487
|
+
2,
|
|
488
|
+
2,
|
|
489
|
+
9,
|
|
490
|
+
12,
|
|
491
|
+
13,
|
|
492
|
+
13,
|
|
493
|
+
15,
|
|
494
|
+
16,
|
|
495
|
+
23,
|
|
496
|
+
26,
|
|
497
|
+
30,
|
|
498
|
+
37,
|
|
499
|
+
47,
|
|
500
|
+
49,
|
|
501
|
+
70,
|
|
502
|
+
146
|
|
503
|
+
],
|
|
504
|
+
"p25": 0,
|
|
505
|
+
"median": 2,
|
|
506
|
+
"p75": 21,
|
|
507
|
+
"p90": 47
|
|
508
|
+
},
|
|
509
|
+
"important": {
|
|
510
|
+
"values": [
|
|
511
|
+
0,
|
|
512
|
+
0,
|
|
513
|
+
0,
|
|
514
|
+
0,
|
|
515
|
+
0,
|
|
516
|
+
0,
|
|
517
|
+
0,
|
|
518
|
+
0,
|
|
519
|
+
0,
|
|
520
|
+
0,
|
|
521
|
+
0,
|
|
522
|
+
1,
|
|
523
|
+
1,
|
|
524
|
+
2,
|
|
525
|
+
4,
|
|
526
|
+
5,
|
|
527
|
+
5,
|
|
528
|
+
6,
|
|
529
|
+
9,
|
|
530
|
+
9,
|
|
531
|
+
11,
|
|
532
|
+
12,
|
|
533
|
+
20,
|
|
534
|
+
35,
|
|
535
|
+
42,
|
|
536
|
+
42,
|
|
537
|
+
74,
|
|
538
|
+
83,
|
|
539
|
+
88,
|
|
540
|
+
161
|
|
541
|
+
],
|
|
542
|
+
"p25": 0,
|
|
543
|
+
"median": 5,
|
|
544
|
+
"p75": 18,
|
|
545
|
+
"p90": 75
|
|
546
|
+
},
|
|
547
|
+
"neverImported": {
|
|
548
|
+
"values": [
|
|
549
|
+
0,
|
|
550
|
+
0,
|
|
551
|
+
0,
|
|
552
|
+
0,
|
|
553
|
+
0,
|
|
554
|
+
0,
|
|
555
|
+
0,
|
|
556
|
+
0,
|
|
557
|
+
0,
|
|
558
|
+
0,
|
|
559
|
+
0,
|
|
560
|
+
0,
|
|
561
|
+
0,
|
|
562
|
+
0,
|
|
563
|
+
0,
|
|
564
|
+
0,
|
|
565
|
+
0,
|
|
566
|
+
0,
|
|
567
|
+
5,
|
|
568
|
+
7,
|
|
569
|
+
10,
|
|
570
|
+
13,
|
|
571
|
+
22,
|
|
572
|
+
22,
|
|
573
|
+
26,
|
|
574
|
+
36,
|
|
575
|
+
39,
|
|
576
|
+
45,
|
|
577
|
+
94,
|
|
578
|
+
100
|
|
579
|
+
],
|
|
580
|
+
"p25": 0,
|
|
581
|
+
"median": 0,
|
|
582
|
+
"p75": 20,
|
|
583
|
+
"p90": 40
|
|
584
|
+
},
|
|
459
585
|
"components": {
|
|
460
586
|
"values": [
|
|
461
587
|
9,
|
|
@@ -471,27 +597,27 @@
|
|
|
471
597
|
342,
|
|
472
598
|
350,
|
|
473
599
|
417,
|
|
474
|
-
|
|
475
|
-
|
|
600
|
+
555,
|
|
601
|
+
637,
|
|
476
602
|
777,
|
|
477
|
-
|
|
478
|
-
|
|
603
|
+
796,
|
|
604
|
+
836,
|
|
479
605
|
936,
|
|
480
606
|
940,
|
|
481
|
-
|
|
607
|
+
962,
|
|
482
608
|
970,
|
|
483
|
-
|
|
609
|
+
1052,
|
|
484
610
|
1081,
|
|
485
611
|
1216,
|
|
486
612
|
1379,
|
|
487
613
|
1414,
|
|
488
614
|
1619,
|
|
489
|
-
|
|
490
|
-
|
|
615
|
+
2134,
|
|
616
|
+
2566
|
|
491
617
|
],
|
|
492
618
|
"p25": 233,
|
|
493
|
-
"median":
|
|
494
|
-
"p75":
|
|
619
|
+
"median": 707,
|
|
620
|
+
"p75": 1032,
|
|
495
621
|
"p90": 1435
|
|
496
622
|
}
|
|
497
623
|
},
|
|
@@ -511,6 +637,9 @@
|
|
|
511
637
|
"exactDuplicates": 115,
|
|
512
638
|
"inlineStyles": 79,
|
|
513
639
|
"arbitrary": 321,
|
|
640
|
+
"nearPairs": 47,
|
|
641
|
+
"important": 161,
|
|
642
|
+
"neverImported": 39,
|
|
514
643
|
"components": 1414
|
|
515
644
|
}
|
|
516
645
|
},
|
|
@@ -529,6 +658,9 @@
|
|
|
529
658
|
"exactDuplicates": 3,
|
|
530
659
|
"inlineStyles": 82,
|
|
531
660
|
"arbitrary": 0,
|
|
661
|
+
"nearPairs": 49,
|
|
662
|
+
"important": 88,
|
|
663
|
+
"neverImported": 0,
|
|
532
664
|
"components": 342
|
|
533
665
|
}
|
|
534
666
|
},
|
|
@@ -547,13 +679,16 @@
|
|
|
547
679
|
"exactDuplicates": 4,
|
|
548
680
|
"inlineStyles": 23,
|
|
549
681
|
"arbitrary": 0,
|
|
682
|
+
"nearPairs": 37,
|
|
683
|
+
"important": 4,
|
|
684
|
+
"neverImported": 0,
|
|
550
685
|
"components": 50
|
|
551
686
|
}
|
|
552
687
|
},
|
|
553
688
|
{
|
|
554
689
|
"repo": "outline/outline",
|
|
555
690
|
"designSystem": "custom",
|
|
556
|
-
"codeFiles":
|
|
691
|
+
"codeFiles": 2122,
|
|
557
692
|
"metrics": {
|
|
558
693
|
"colors": 89,
|
|
559
694
|
"greys": 15,
|
|
@@ -565,7 +700,10 @@
|
|
|
565
700
|
"exactDuplicates": 23,
|
|
566
701
|
"inlineStyles": 76,
|
|
567
702
|
"arbitrary": 0,
|
|
568
|
-
"
|
|
703
|
+
"nearPairs": 1,
|
|
704
|
+
"important": 0,
|
|
705
|
+
"neverImported": 0,
|
|
706
|
+
"components": 637
|
|
569
707
|
}
|
|
570
708
|
},
|
|
571
709
|
{
|
|
@@ -583,6 +721,9 @@
|
|
|
583
721
|
"exactDuplicates": 2,
|
|
584
722
|
"inlineStyles": 0,
|
|
585
723
|
"arbitrary": 4,
|
|
724
|
+
"nearPairs": 0,
|
|
725
|
+
"important": 5,
|
|
726
|
+
"neverImported": 0,
|
|
586
727
|
"components": 220
|
|
587
728
|
}
|
|
588
729
|
},
|
|
@@ -601,6 +742,9 @@
|
|
|
601
742
|
"exactDuplicates": 0,
|
|
602
743
|
"inlineStyles": 0,
|
|
603
744
|
"arbitrary": 0,
|
|
745
|
+
"nearPairs": 0,
|
|
746
|
+
"important": 0,
|
|
747
|
+
"neverImported": 0,
|
|
604
748
|
"components": 25
|
|
605
749
|
}
|
|
606
750
|
},
|
|
@@ -619,6 +763,9 @@
|
|
|
619
763
|
"exactDuplicates": 0,
|
|
620
764
|
"inlineStyles": 0,
|
|
621
765
|
"arbitrary": 60,
|
|
766
|
+
"nearPairs": 0,
|
|
767
|
+
"important": 1,
|
|
768
|
+
"neverImported": 94,
|
|
622
769
|
"components": 182
|
|
623
770
|
}
|
|
624
771
|
},
|
|
@@ -637,6 +784,9 @@
|
|
|
637
784
|
"exactDuplicates": 0,
|
|
638
785
|
"inlineStyles": 0,
|
|
639
786
|
"arbitrary": 0,
|
|
787
|
+
"nearPairs": 0,
|
|
788
|
+
"important": 0,
|
|
789
|
+
"neverImported": 0,
|
|
640
790
|
"components": 9
|
|
641
791
|
}
|
|
642
792
|
},
|
|
@@ -655,6 +805,9 @@
|
|
|
655
805
|
"exactDuplicates": 1,
|
|
656
806
|
"inlineStyles": 2,
|
|
657
807
|
"arbitrary": 16,
|
|
808
|
+
"nearPairs": 0,
|
|
809
|
+
"important": 2,
|
|
810
|
+
"neverImported": 0,
|
|
658
811
|
"components": 60
|
|
659
812
|
}
|
|
660
813
|
},
|
|
@@ -673,6 +826,9 @@
|
|
|
673
826
|
"exactDuplicates": 1,
|
|
674
827
|
"inlineStyles": 7,
|
|
675
828
|
"arbitrary": 103,
|
|
829
|
+
"nearPairs": 0,
|
|
830
|
+
"important": 9,
|
|
831
|
+
"neverImported": 0,
|
|
676
832
|
"components": 315
|
|
677
833
|
}
|
|
678
834
|
},
|
|
@@ -691,13 +847,16 @@
|
|
|
691
847
|
"exactDuplicates": 1,
|
|
692
848
|
"inlineStyles": 11,
|
|
693
849
|
"arbitrary": 148,
|
|
850
|
+
"nearPairs": 0,
|
|
851
|
+
"important": 0,
|
|
852
|
+
"neverImported": 100,
|
|
694
853
|
"components": 272
|
|
695
854
|
}
|
|
696
855
|
},
|
|
697
856
|
{
|
|
698
857
|
"repo": "documenso/documenso",
|
|
699
858
|
"designSystem": "custom",
|
|
700
|
-
"codeFiles":
|
|
859
|
+
"codeFiles": 1912,
|
|
701
860
|
"metrics": {
|
|
702
861
|
"colors": 36,
|
|
703
862
|
"greys": 13,
|
|
@@ -709,13 +868,16 @@
|
|
|
709
868
|
"exactDuplicates": 17,
|
|
710
869
|
"inlineStyles": 69,
|
|
711
870
|
"arbitrary": 234,
|
|
712
|
-
"
|
|
871
|
+
"nearPairs": 15,
|
|
872
|
+
"important": 0,
|
|
873
|
+
"neverImported": 45,
|
|
874
|
+
"components": 796
|
|
713
875
|
}
|
|
714
876
|
},
|
|
715
877
|
{
|
|
716
878
|
"repo": "dubinc/dub",
|
|
717
879
|
"designSystem": "custom",
|
|
718
|
-
"codeFiles":
|
|
880
|
+
"codeFiles": 3526,
|
|
719
881
|
"metrics": {
|
|
720
882
|
"colors": 102,
|
|
721
883
|
"greys": 14,
|
|
@@ -727,6 +889,9 @@
|
|
|
727
889
|
"exactDuplicates": 17,
|
|
728
890
|
"inlineStyles": 47,
|
|
729
891
|
"arbitrary": 470,
|
|
892
|
+
"nearPairs": 13,
|
|
893
|
+
"important": 1,
|
|
894
|
+
"neverImported": 22,
|
|
730
895
|
"components": 1379
|
|
731
896
|
}
|
|
732
897
|
},
|
|
@@ -745,6 +910,9 @@
|
|
|
745
910
|
"exactDuplicates": 59,
|
|
746
911
|
"inlineStyles": 18,
|
|
747
912
|
"arbitrary": 164,
|
|
913
|
+
"nearPairs": 13,
|
|
914
|
+
"important": 83,
|
|
915
|
+
"neverImported": 0,
|
|
748
916
|
"components": 940
|
|
749
917
|
}
|
|
750
918
|
},
|
|
@@ -763,13 +931,16 @@
|
|
|
763
931
|
"exactDuplicates": 92,
|
|
764
932
|
"inlineStyles": 119,
|
|
765
933
|
"arbitrary": 164,
|
|
934
|
+
"nearPairs": 0,
|
|
935
|
+
"important": 0,
|
|
936
|
+
"neverImported": 5,
|
|
766
937
|
"components": 1081
|
|
767
938
|
}
|
|
768
939
|
},
|
|
769
940
|
{
|
|
770
941
|
"repo": "lukevella/rallly",
|
|
771
942
|
"designSystem": "custom",
|
|
772
|
-
"codeFiles":
|
|
943
|
+
"codeFiles": 692,
|
|
773
944
|
"metrics": {
|
|
774
945
|
"colors": 26,
|
|
775
946
|
"greys": 4,
|
|
@@ -781,7 +952,10 @@
|
|
|
781
952
|
"exactDuplicates": 10,
|
|
782
953
|
"inlineStyles": 23,
|
|
783
954
|
"arbitrary": 27,
|
|
784
|
-
"
|
|
955
|
+
"nearPairs": 2,
|
|
956
|
+
"important": 0,
|
|
957
|
+
"neverImported": 22,
|
|
958
|
+
"components": 555
|
|
785
959
|
}
|
|
786
960
|
},
|
|
787
961
|
{
|
|
@@ -799,13 +973,16 @@
|
|
|
799
973
|
"exactDuplicates": 20,
|
|
800
974
|
"inlineStyles": 46,
|
|
801
975
|
"arbitrary": 407,
|
|
976
|
+
"nearPairs": 0,
|
|
977
|
+
"important": 42,
|
|
978
|
+
"neverImported": 13,
|
|
802
979
|
"components": 777
|
|
803
980
|
}
|
|
804
981
|
},
|
|
805
982
|
{
|
|
806
983
|
"repo": "elie222/inbox-zero",
|
|
807
984
|
"designSystem": "custom",
|
|
808
|
-
"codeFiles":
|
|
985
|
+
"codeFiles": 1821,
|
|
809
986
|
"metrics": {
|
|
810
987
|
"colors": 154,
|
|
811
988
|
"greys": 24,
|
|
@@ -817,7 +994,10 @@
|
|
|
817
994
|
"exactDuplicates": 21,
|
|
818
995
|
"inlineStyles": 5,
|
|
819
996
|
"arbitrary": 125,
|
|
820
|
-
"
|
|
997
|
+
"nearPairs": 26,
|
|
998
|
+
"important": 6,
|
|
999
|
+
"neverImported": 0,
|
|
1000
|
+
"components": 836
|
|
821
1001
|
}
|
|
822
1002
|
},
|
|
823
1003
|
{
|
|
@@ -835,6 +1015,9 @@
|
|
|
835
1015
|
"exactDuplicates": 7,
|
|
836
1016
|
"inlineStyles": 41,
|
|
837
1017
|
"arbitrary": 78,
|
|
1018
|
+
"nearPairs": 0,
|
|
1019
|
+
"important": 0,
|
|
1020
|
+
"neverImported": 0,
|
|
838
1021
|
"components": 190
|
|
839
1022
|
}
|
|
840
1023
|
},
|
|
@@ -853,13 +1036,16 @@
|
|
|
853
1036
|
"exactDuplicates": 0,
|
|
854
1037
|
"inlineStyles": 173,
|
|
855
1038
|
"arbitrary": 1,
|
|
1039
|
+
"nearPairs": 2,
|
|
1040
|
+
"important": 5,
|
|
1041
|
+
"neverImported": 0,
|
|
856
1042
|
"components": 417
|
|
857
1043
|
}
|
|
858
1044
|
},
|
|
859
1045
|
{
|
|
860
1046
|
"repo": "twentyhq/twenty",
|
|
861
1047
|
"designSystem": "library",
|
|
862
|
-
"codeFiles":
|
|
1048
|
+
"codeFiles": 15132,
|
|
863
1049
|
"metrics": {
|
|
864
1050
|
"colors": 1645,
|
|
865
1051
|
"greys": 100,
|
|
@@ -871,13 +1057,16 @@
|
|
|
871
1057
|
"exactDuplicates": 22,
|
|
872
1058
|
"inlineStyles": 122,
|
|
873
1059
|
"arbitrary": 0,
|
|
874
|
-
"
|
|
1060
|
+
"nearPairs": 146,
|
|
1061
|
+
"important": 9,
|
|
1062
|
+
"neverImported": 0,
|
|
1063
|
+
"components": 2134
|
|
875
1064
|
}
|
|
876
1065
|
},
|
|
877
1066
|
{
|
|
878
1067
|
"repo": "langfuse/langfuse",
|
|
879
1068
|
"designSystem": "custom",
|
|
880
|
-
"codeFiles":
|
|
1069
|
+
"codeFiles": 2774,
|
|
881
1070
|
"metrics": {
|
|
882
1071
|
"colors": 170,
|
|
883
1072
|
"greys": 4,
|
|
@@ -887,9 +1076,12 @@
|
|
|
887
1076
|
"radii": 10,
|
|
888
1077
|
"shadows": 0,
|
|
889
1078
|
"exactDuplicates": 7,
|
|
890
|
-
"inlineStyles":
|
|
891
|
-
"arbitrary":
|
|
892
|
-
"
|
|
1079
|
+
"inlineStyles": 43,
|
|
1080
|
+
"arbitrary": 380,
|
|
1081
|
+
"nearPairs": 2,
|
|
1082
|
+
"important": 12,
|
|
1083
|
+
"neverImported": 10,
|
|
1084
|
+
"components": 1052
|
|
893
1085
|
}
|
|
894
1086
|
},
|
|
895
1087
|
{
|
|
@@ -907,6 +1099,9 @@
|
|
|
907
1099
|
"exactDuplicates": 45,
|
|
908
1100
|
"inlineStyles": 37,
|
|
909
1101
|
"arbitrary": 468,
|
|
1102
|
+
"nearPairs": 70,
|
|
1103
|
+
"important": 42,
|
|
1104
|
+
"neverImported": 0,
|
|
910
1105
|
"components": 1216
|
|
911
1106
|
}
|
|
912
1107
|
},
|
|
@@ -925,6 +1120,9 @@
|
|
|
925
1120
|
"exactDuplicates": 95,
|
|
926
1121
|
"inlineStyles": 22,
|
|
927
1122
|
"arbitrary": 561,
|
|
1123
|
+
"nearPairs": 16,
|
|
1124
|
+
"important": 74,
|
|
1125
|
+
"neverImported": 7,
|
|
928
1126
|
"components": 1619
|
|
929
1127
|
}
|
|
930
1128
|
},
|
|
@@ -943,31 +1141,37 @@
|
|
|
943
1141
|
"exactDuplicates": 19,
|
|
944
1142
|
"inlineStyles": 1178,
|
|
945
1143
|
"arbitrary": 0,
|
|
1144
|
+
"nearPairs": 23,
|
|
1145
|
+
"important": 35,
|
|
1146
|
+
"neverImported": 36,
|
|
946
1147
|
"components": 350
|
|
947
1148
|
}
|
|
948
1149
|
},
|
|
949
1150
|
{
|
|
950
1151
|
"repo": "lobehub/lobe-chat",
|
|
951
1152
|
"designSystem": "library",
|
|
952
|
-
"codeFiles":
|
|
1153
|
+
"codeFiles": 8344,
|
|
953
1154
|
"metrics": {
|
|
954
|
-
"colors":
|
|
1155
|
+
"colors": 303,
|
|
955
1156
|
"greys": 37,
|
|
956
1157
|
"spacing": 61,
|
|
957
1158
|
"typefaces": 1,
|
|
958
1159
|
"fontSizes": 2,
|
|
959
1160
|
"radii": 1,
|
|
960
1161
|
"shadows": 0,
|
|
961
|
-
"exactDuplicates":
|
|
962
|
-
"inlineStyles":
|
|
1162
|
+
"exactDuplicates": 189,
|
|
1163
|
+
"inlineStyles": 2923,
|
|
963
1164
|
"arbitrary": 0,
|
|
964
|
-
"
|
|
1165
|
+
"nearPairs": 9,
|
|
1166
|
+
"important": 0,
|
|
1167
|
+
"neverImported": 0,
|
|
1168
|
+
"components": 2566
|
|
965
1169
|
}
|
|
966
1170
|
},
|
|
967
1171
|
{
|
|
968
1172
|
"repo": "danny-avila/LibreChat",
|
|
969
1173
|
"designSystem": "custom",
|
|
970
|
-
"codeFiles":
|
|
1174
|
+
"codeFiles": 2430,
|
|
971
1175
|
"metrics": {
|
|
972
1176
|
"colors": 174,
|
|
973
1177
|
"greys": 30,
|
|
@@ -979,7 +1183,10 @@
|
|
|
979
1183
|
"exactDuplicates": 38,
|
|
980
1184
|
"inlineStyles": 71,
|
|
981
1185
|
"arbitrary": 492,
|
|
982
|
-
"
|
|
1186
|
+
"nearPairs": 30,
|
|
1187
|
+
"important": 20,
|
|
1188
|
+
"neverImported": 0,
|
|
1189
|
+
"components": 962
|
|
983
1190
|
}
|
|
984
1191
|
},
|
|
985
1192
|
{
|
|
@@ -997,13 +1204,16 @@
|
|
|
997
1204
|
"exactDuplicates": 103,
|
|
998
1205
|
"inlineStyles": 117,
|
|
999
1206
|
"arbitrary": 1751,
|
|
1207
|
+
"nearPairs": 12,
|
|
1208
|
+
"important": 0,
|
|
1209
|
+
"neverImported": 26,
|
|
1000
1210
|
"components": 970
|
|
1001
1211
|
}
|
|
1002
1212
|
},
|
|
1003
1213
|
{
|
|
1004
1214
|
"repo": "triggerdotdev/trigger.dev",
|
|
1005
1215
|
"designSystem": "custom",
|
|
1006
|
-
"codeFiles":
|
|
1216
|
+
"codeFiles": 2366,
|
|
1007
1217
|
"metrics": {
|
|
1008
1218
|
"colors": 137,
|
|
1009
1219
|
"greys": 18,
|
|
@@ -1015,6 +1225,9 @@
|
|
|
1015
1225
|
"exactDuplicates": 8,
|
|
1016
1226
|
"inlineStyles": 51,
|
|
1017
1227
|
"arbitrary": 271,
|
|
1228
|
+
"nearPairs": 1,
|
|
1229
|
+
"important": 11,
|
|
1230
|
+
"neverImported": 0,
|
|
1018
1231
|
"components": 936
|
|
1019
1232
|
}
|
|
1020
1233
|
},
|
|
@@ -1033,12 +1246,15 @@
|
|
|
1033
1246
|
"exactDuplicates": 0,
|
|
1034
1247
|
"inlineStyles": 0,
|
|
1035
1248
|
"arbitrary": 26,
|
|
1249
|
+
"nearPairs": 0,
|
|
1250
|
+
"important": 0,
|
|
1251
|
+
"neverImported": 0,
|
|
1036
1252
|
"components": 36
|
|
1037
1253
|
}
|
|
1038
1254
|
}
|
|
1039
1255
|
],
|
|
1040
1256
|
"referenceSystems": {
|
|
1041
|
-
"builtAt": "2026-08-
|
|
1257
|
+
"builtAt": "2026-08-03T16:33:34.617Z",
|
|
1042
1258
|
"count": 10,
|
|
1043
1259
|
"note": "Curated scoped scans of reputable public design systems. Not comparable head-to-head with product repos: see per-system notes.",
|
|
1044
1260
|
"stats": {
|
|
@@ -1192,6 +1408,51 @@
|
|
|
1192
1408
|
],
|
|
1193
1409
|
"median": 0
|
|
1194
1410
|
},
|
|
1411
|
+
"nearPairs": {
|
|
1412
|
+
"values": [
|
|
1413
|
+
0,
|
|
1414
|
+
0,
|
|
1415
|
+
0,
|
|
1416
|
+
0,
|
|
1417
|
+
1,
|
|
1418
|
+
1,
|
|
1419
|
+
1,
|
|
1420
|
+
5,
|
|
1421
|
+
33,
|
|
1422
|
+
50
|
|
1423
|
+
],
|
|
1424
|
+
"median": 1
|
|
1425
|
+
},
|
|
1426
|
+
"important": {
|
|
1427
|
+
"values": [
|
|
1428
|
+
0,
|
|
1429
|
+
0,
|
|
1430
|
+
0,
|
|
1431
|
+
1,
|
|
1432
|
+
1,
|
|
1433
|
+
4,
|
|
1434
|
+
4,
|
|
1435
|
+
30,
|
|
1436
|
+
33,
|
|
1437
|
+
61
|
|
1438
|
+
],
|
|
1439
|
+
"median": 3
|
|
1440
|
+
},
|
|
1441
|
+
"neverImported": {
|
|
1442
|
+
"values": [
|
|
1443
|
+
0,
|
|
1444
|
+
0,
|
|
1445
|
+
0,
|
|
1446
|
+
0,
|
|
1447
|
+
0,
|
|
1448
|
+
0,
|
|
1449
|
+
0,
|
|
1450
|
+
0,
|
|
1451
|
+
0,
|
|
1452
|
+
0
|
|
1453
|
+
],
|
|
1454
|
+
"median": 0
|
|
1455
|
+
},
|
|
1195
1456
|
"components": {
|
|
1196
1457
|
"values": [
|
|
1197
1458
|
0,
|
|
@@ -1226,6 +1487,9 @@
|
|
|
1226
1487
|
"exactDuplicates": 0,
|
|
1227
1488
|
"inlineStyles": 1,
|
|
1228
1489
|
"arbitrary": 35,
|
|
1490
|
+
"nearPairs": 0,
|
|
1491
|
+
"important": 0,
|
|
1492
|
+
"neverImported": 0,
|
|
1229
1493
|
"components": 331
|
|
1230
1494
|
}
|
|
1231
1495
|
},
|
|
@@ -1246,6 +1510,9 @@
|
|
|
1246
1510
|
"exactDuplicates": 13,
|
|
1247
1511
|
"inlineStyles": 14,
|
|
1248
1512
|
"arbitrary": 0,
|
|
1513
|
+
"nearPairs": 5,
|
|
1514
|
+
"important": 33,
|
|
1515
|
+
"neverImported": 0,
|
|
1249
1516
|
"components": 228
|
|
1250
1517
|
}
|
|
1251
1518
|
},
|
|
@@ -1266,6 +1533,9 @@
|
|
|
1266
1533
|
"exactDuplicates": 15,
|
|
1267
1534
|
"inlineStyles": 10,
|
|
1268
1535
|
"arbitrary": 0,
|
|
1536
|
+
"nearPairs": 0,
|
|
1537
|
+
"important": 30,
|
|
1538
|
+
"neverImported": 0,
|
|
1269
1539
|
"components": 243
|
|
1270
1540
|
}
|
|
1271
1541
|
},
|
|
@@ -1286,6 +1556,9 @@
|
|
|
1286
1556
|
"exactDuplicates": 6,
|
|
1287
1557
|
"inlineStyles": 17,
|
|
1288
1558
|
"arbitrary": 0,
|
|
1559
|
+
"nearPairs": 1,
|
|
1560
|
+
"important": 4,
|
|
1561
|
+
"neverImported": 0,
|
|
1289
1562
|
"components": 314
|
|
1290
1563
|
}
|
|
1291
1564
|
},
|
|
@@ -1306,6 +1579,9 @@
|
|
|
1306
1579
|
"exactDuplicates": 2,
|
|
1307
1580
|
"inlineStyles": 10,
|
|
1308
1581
|
"arbitrary": 0,
|
|
1582
|
+
"nearPairs": 50,
|
|
1583
|
+
"important": 0,
|
|
1584
|
+
"neverImported": 0,
|
|
1309
1585
|
"components": 170
|
|
1310
1586
|
}
|
|
1311
1587
|
},
|
|
@@ -1326,6 +1602,9 @@
|
|
|
1326
1602
|
"exactDuplicates": 0,
|
|
1327
1603
|
"inlineStyles": 1,
|
|
1328
1604
|
"arbitrary": 0,
|
|
1605
|
+
"nearPairs": 1,
|
|
1606
|
+
"important": 0,
|
|
1607
|
+
"neverImported": 0,
|
|
1329
1608
|
"components": 711
|
|
1330
1609
|
}
|
|
1331
1610
|
},
|
|
@@ -1346,6 +1625,9 @@
|
|
|
1346
1625
|
"exactDuplicates": 17,
|
|
1347
1626
|
"inlineStyles": 24,
|
|
1348
1627
|
"arbitrary": 0,
|
|
1628
|
+
"nearPairs": 1,
|
|
1629
|
+
"important": 1,
|
|
1630
|
+
"neverImported": 0,
|
|
1349
1631
|
"components": 246
|
|
1350
1632
|
}
|
|
1351
1633
|
},
|
|
@@ -1366,6 +1648,9 @@
|
|
|
1366
1648
|
"exactDuplicates": 0,
|
|
1367
1649
|
"inlineStyles": 0,
|
|
1368
1650
|
"arbitrary": 0,
|
|
1651
|
+
"nearPairs": 33,
|
|
1652
|
+
"important": 61,
|
|
1653
|
+
"neverImported": 0,
|
|
1369
1654
|
"components": 0
|
|
1370
1655
|
}
|
|
1371
1656
|
},
|
|
@@ -1386,6 +1671,9 @@
|
|
|
1386
1671
|
"exactDuplicates": 170,
|
|
1387
1672
|
"inlineStyles": 14,
|
|
1388
1673
|
"arbitrary": 0,
|
|
1674
|
+
"nearPairs": 0,
|
|
1675
|
+
"important": 1,
|
|
1676
|
+
"neverImported": 0,
|
|
1389
1677
|
"components": 819
|
|
1390
1678
|
}
|
|
1391
1679
|
},
|
|
@@ -1406,6 +1694,9 @@
|
|
|
1406
1694
|
"exactDuplicates": 28,
|
|
1407
1695
|
"inlineStyles": 22,
|
|
1408
1696
|
"arbitrary": 0,
|
|
1697
|
+
"nearPairs": 0,
|
|
1698
|
+
"important": 4,
|
|
1699
|
+
"neverImported": 0,
|
|
1409
1700
|
"components": 508
|
|
1410
1701
|
}
|
|
1411
1702
|
}
|
|
@@ -13,6 +13,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
13
13
|
import { distinctTypefaces } from '../lib/typefaces.mjs';
|
|
14
14
|
import { rulesMarkdown } from '../rules/build.mjs';
|
|
15
15
|
import { nearColorPairs } from '../lib/nearpairs.mjs';
|
|
16
|
+
import { neverImportedComponents } from '../lib/neverimported.mjs';
|
|
16
17
|
|
|
17
18
|
// The benchmark (Ideal-2026 norms + scanned-repo stats) ships next to the
|
|
18
19
|
// code so the page works offline; degrade gracefully when absent.
|
|
@@ -35,7 +36,7 @@ const GK_MASK = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqa
|
|
|
35
36
|
const GK_MARK = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAAAAAAAAAQCEeRdzAAACPklEQVR4nOVWTYh5URR/PlJYEKV8LKwkZalsmI2dZmMnK8pKmaZ87JSanexEkayUhSxsZyfJNBQ7UYqVhSShfM+v/6mXmtU81+p/Frfze+/d3++ce88993Hcf2cikehZ1GazWafTPUVDLBZjLBQKnU6HMTVvcrl8Op3ebrdsNgsokUiYUVP4Pp/v9s96vd79cwZGK95sNkkgGAwC2u12lhrY3u12C/b1ei2TyV5eXjabjV6vZ6BBa51MJin8arUKWKlU4H99fSkUCo5JUQ2HQxJwuVzIYLVawcdIVSs8CQoNpMQ+Go0Aw+EwwXw+D+h2u4Vr0LRSqUSMqVQKsN1uE3Q4HEql8ng8BgIBTnDhqlSqxWIBuvP5bDAYLBbL5XIBHAwGeBuJRODvdjun0/nnPOjraDRK8TYaDcBMJkMwFosBfn9/E0wkEn9OgjYgnU6fTidQwAGcTCbw9/u9VqvFUYB/vV5RskajkRNcTiaTKR6PI9j5fE7xlstlPM/lcgTr9ToneJ/5oOB4PB70O8Tb7/f9fv9sNqPkXl9fhQsQ9f1ktVqNvUVCxA6ZRxsf5pMAxnsuVBSOwvv7+6Phk0PsBNn0OOLC9haLReqdvBL/wUNKNPnt7Q0LjeVutVqhUEij0TwU9W8BVA4JUEUul8tarcZGhpbIarWiSeA0HQ4Hkvn4+GB56VMvov6DA+z1eplR89btdsE+Ho9tNhv3jOv+8/MTFz06M3ypVMqMnTfcwPhn4djG/tue+Mf4RGom9gMt6lAx16huIwAAAABJRU5ErkJggg==';
|
|
36
37
|
|
|
37
38
|
// Shown in the report footer; keep in step with plugin.json when releasing.
|
|
38
|
-
const VERSION = '3.
|
|
39
|
+
const VERSION = '3.7.0';
|
|
39
40
|
|
|
40
41
|
// Two shipped skins, same layout: 'dark' (navy glass, mint accent) and
|
|
41
42
|
// 'light' (lilac wash, white glass, violet accent). --theme picks one.
|
|
@@ -157,16 +158,7 @@ const important = h.tokens.important ?? { count: 0, files: [] };
|
|
|
157
158
|
|
|
158
159
|
const nearPairs = nearColorPairs(colors);
|
|
159
160
|
|
|
160
|
-
|
|
161
|
-
// directory, where "nobody imports this" is meaningful. File-local
|
|
162
|
-
// subcomponents elsewhere legitimately never get imported by name.
|
|
163
|
-
const dsDirRe = h.profile?.uiDir
|
|
164
|
-
? new RegExp(`^${h.profile.uiDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/`)
|
|
165
|
-
: /(^|\/)(packages\/ui|design-system|ui-kit)\//;
|
|
166
|
-
const usedFiles = new Set(reusable.filter((c) => c.usageCount > 0).map((c) => c.file));
|
|
167
|
-
const neverImported = reusable.filter((c) => !c.usageCount && dsDirRe.test(c.file)
|
|
168
|
-
&& !/(^|\/)icons?\//.test(c.file) // glyph sets are deliberately complete
|
|
169
|
-
&& !usedFiles.has(c.file)); // compound API: an adopted file's sub-exports are surface, not dead
|
|
161
|
+
const neverImported = neverImportedComponents(h.components, h.profile?.uiDir);
|
|
170
162
|
|
|
171
163
|
// Benchmark helpers: for a metric value, where does this repo sit among the
|
|
172
164
|
// scanned fleet? ("more colours than 90% of scanned repos")
|
|
@@ -254,8 +246,8 @@ if (bench && findings.length) {
|
|
|
254
246
|
// Where the median is missing or sits at/below ideal, warn caps at 1.5x ideal.
|
|
255
247
|
// Zero-ideal metrics (duplicates, inline styles): 0 is good; a small tolerance
|
|
256
248
|
// is warn; beyond that bad.
|
|
257
|
-
const ZERO_IDEAL = new Set(['exactDuplicates', 'inlineStyles']);
|
|
258
|
-
const WARN_TOLERANCE = { exactDuplicates: 2, inlineStyles: 10 };
|
|
249
|
+
const ZERO_IDEAL = new Set(['exactDuplicates', 'inlineStyles', 'nearPairs', 'important', 'neverImported']);
|
|
250
|
+
const WARN_TOLERANCE = { exactDuplicates: 2, inlineStyles: 10, nearPairs: 2, important: 5, neverImported: 2 };
|
|
259
251
|
// Absence rule also skipped for arbitrary values: zero brackets is discipline
|
|
260
252
|
// (nine of ten reputable systems sit at 0, including Tailwind-native shadcn/ui).
|
|
261
253
|
const NO_ABSENCE_RULE = new Set(['colors', 'greys', 'arbitrary']);
|
|
@@ -308,6 +300,9 @@ const bigStats = [
|
|
|
308
300
|
tile(spacingTotal, 'off-scale spacing values', 'spacing', 'a dozen deliberate exceptions'),
|
|
309
301
|
tile(hardDupes.length, 'duplicated components', 'exactDuplicates', 'should be 0'),
|
|
310
302
|
tile(inline.count, 'inline style blocks', 'inlineStyles', 'invisible to any system'),
|
|
303
|
+
tile(nearPairs.length, 'near-identical colour pairs', 'nearPairs', 'copy-paste, not decisions'),
|
|
304
|
+
tile(important.count, '!important declarations', 'important', 'the cascade admitting defeat'),
|
|
305
|
+
tile(neverImported.length, 'components never imported', 'neverImported', 'the system nobody found'),
|
|
311
306
|
tile(arbitraryCount, 'arbitrary bracket values', 'arbitrary', 'a handful of deliberate exceptions'),
|
|
312
307
|
];
|
|
313
308
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design-system components defined but never imported — scoped so the claim
|
|
3
|
+
* is honest. File-local subcomponents elsewhere legitimately never get
|
|
4
|
+
* imported by name; icon sets are deliberately complete; sub-exports of an
|
|
5
|
+
* adopted file are API surface, not dead code. Shared by diagnose, rules and
|
|
6
|
+
* the benchmark builder.
|
|
7
|
+
*/
|
|
8
|
+
export function neverImportedComponents(components, uiDir) {
|
|
9
|
+
const reusable = (components ?? []).filter((c) => !c.isPage);
|
|
10
|
+
const dsDirRe = uiDir
|
|
11
|
+
? new RegExp(`^${uiDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/`)
|
|
12
|
+
: /(^|\/)(packages\/ui|design-system|ui-kit)\//;
|
|
13
|
+
const usedFiles = new Set(reusable.filter((c) => c.usageCount > 0).map((c) => c.file));
|
|
14
|
+
return reusable.filter((c) => !c.usageCount && dsDirRe.test(c.file)
|
|
15
|
+
&& !/(^|\/)icons?\//.test(c.file)
|
|
16
|
+
&& !usedFiles.has(c.file));
|
|
17
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { distinctTypefaces } from '../lib/typefaces.mjs';
|
|
8
8
|
import { nearColorPairs } from './../lib/nearpairs.mjs';
|
|
9
|
+
import { neverImportedComponents } from '../lib/neverimported.mjs';
|
|
9
10
|
|
|
10
11
|
export function rulesMarkdown(h) {
|
|
11
12
|
const repoName = h.profile?.name ?? 'this repo';
|
|
@@ -88,13 +89,7 @@ const repoName = h.profile?.name ?? 'this repo';
|
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
// ---------- never-imported components ----------
|
|
91
|
-
const
|
|
92
|
-
? new RegExp(`^${h.profile.uiDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/`)
|
|
93
|
-
: /(^|\/)(packages\/ui|design-system|ui-kit)\//;
|
|
94
|
-
const usedFiles = new Set(reusable.filter((c) => c.usageCount > 0).map((c) => c.file));
|
|
95
|
-
const neverImported = reusable.filter((c) => !c.usageCount && dsDirRe.test(c.file)
|
|
96
|
-
&& !/(^|\/)icons?\//.test(c.file) // glyph sets are deliberately complete
|
|
97
|
-
&& !usedFiles.has(c.file)); // compound API: an adopted file's sub-exports are surface, not dead
|
|
92
|
+
const neverImported = neverImportedComponents(h.components, h.profile?.uiDir);
|
|
98
93
|
if (neverImported.length >= 3) {
|
|
99
94
|
section('Components nobody imports');
|
|
100
95
|
rule(`${neverImported.length} components are defined but never imported (${neverImported.slice(0, 3).map((c) => `\`<${c.name}>\``).join(', ')}…). Before writing any new component, check this list first; adopt one or flag it for deletion instead of adding another.`);
|