diff --git a/devicon.json b/devicon.json
index d779a6685..91b1eec59 100644
--- a/devicon.json
+++ b/devicon.json
@@ -193,7 +193,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#955AE0",
"aliases": []
},
{
@@ -286,7 +286,7 @@
"original-wordmark"
]
},
- "color": "#2d3441",
+ "color": "#77C1D2",
"aliases": [
{
"base": "original",
@@ -517,7 +517,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#FFB71B",
"aliases": []
},
{
@@ -562,7 +562,7 @@
"original",
"plain"
],
- "font":[
+ "font": [
"plain"
]
},
@@ -1699,7 +1699,7 @@
"plain-wordmark"
]
},
- "color": "#161414",
+ "color": "#F6A71A",
"aliases": []
},
{
@@ -2188,7 +2188,7 @@
"plain-wordmark"
]
},
- "color": "#13171a",
+ "color": "#0079B8",
"aliases": []
},
{
@@ -2213,9 +2213,9 @@
"aliases": []
},
{
- "name":"claudecode",
+ "name": "claudecode",
"altnames": [],
- "tags":[
+ "tags": [
"ai",
"coding",
"assistant"
@@ -2280,7 +2280,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#009AE5",
"aliases": []
},
{
@@ -2750,7 +2750,7 @@
"plain-wordmark"
]
},
- "color": "#444",
+ "color": "#4CC2E4",
"aliases": []
},
{
@@ -3209,7 +3209,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#34A853",
"aliases": []
},
{
@@ -3811,7 +3811,7 @@
"plain"
]
},
- "color": "#000000",
+ "color": "#FFF100",
"aliases": []
},
{
@@ -3876,7 +3876,7 @@
"line-wordmark"
]
},
- "color": "#000000",
+ "color": "#1496FF",
"aliases": []
},
{
@@ -5073,7 +5073,7 @@
"line-wordmark"
]
},
- "color": "#3581E5",
+ "color": "#3581E5",
"aliases": []
},
{
@@ -5319,12 +5319,14 @@
"plain"
]
},
- "color": "#24292e",
+ "color": "#007ACC",
"aliases": []
},
{
"name": "githubcopilot",
- "altnames": ["github copilot"],
+ "altnames": [
+ "github copilot"
+ ],
"tags": [
"automation",
"AI",
@@ -5346,7 +5348,7 @@
"line-wordmark"
]
},
- "color": "#000",
+ "color": "#8534F3",
"aliases": []
},
{
@@ -5479,7 +5481,7 @@
"plain"
]
},
- "color": "#000000",
+ "color": "#3333FF",
"aliases": []
},
{
@@ -5608,7 +5610,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#00ADD8",
"aliases": []
},
{
@@ -6168,11 +6170,11 @@
"svg": [
"original",
"plain",
- "line"
+ "line"
],
"font": [
"plain",
- "line"
+ "line"
]
},
"color": "#997ff8",
@@ -6384,7 +6386,7 @@
"line-wordmark"
]
},
- "color": "#333333",
+ "color": "#3465A4",
"aliases": []
},
{
@@ -6766,7 +6768,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#FE315D",
"aliases": []
},
{
@@ -6977,7 +6979,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#CC0000",
"aliases": []
},
{
@@ -8137,7 +8139,7 @@
"plain"
]
},
- "color": "#000000",
+ "color": "#FCC624",
"aliases": []
},
{
@@ -8258,7 +8260,7 @@
"plain"
]
},
- "color": "#000",
+ "color": "#3492FF",
"aliases": []
},
{
@@ -8301,13 +8303,13 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#4B73FF",
"aliases": []
},
{
"name": "love2d",
"altnames": [
- "lรถve"
+ "l\u00f6ve"
],
"tags": [
"programming",
@@ -9625,7 +9627,7 @@
"line"
]
},
- "color": "#1d252c",
+ "color": "#00AC69",
"aliases": [
{
"base": "original",
@@ -9954,7 +9956,7 @@
"line-wordmark"
]
},
- "color": "#3d3b47",
+ "color": "#0977F7",
"aliases": []
},
{
@@ -10461,7 +10463,7 @@
"line"
]
},
- "color": "#000",
+ "color": "#3DAE2B",
"aliases": [
{
"base": "original",
@@ -11074,7 +11076,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#B41E8E",
"aliases": []
},
{
@@ -11197,7 +11199,7 @@
"line-wordmark"
]
},
- "color": "#000",
+ "color": "#2B037A",
"aliases": []
},
{
@@ -11588,7 +11590,7 @@
"plain"
]
},
- "color": "#000",
+ "color": "#DD0031",
"aliases": []
},
{
@@ -11957,7 +11959,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#21D789",
"aliases": []
},
{
@@ -12953,7 +12955,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#C41475",
"aliases": []
},
{
@@ -13147,7 +13149,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#D72B2B",
"aliases": []
},
{
@@ -13260,7 +13262,7 @@
"plain"
]
},
- "color": "#0D0E12",
+ "color": "#F03E2F",
"aliases": []
},
{
@@ -13649,7 +13651,7 @@
{
"name": "shadcn",
"altnames": [],
- "color":"#000000",
+ "color": "#000000",
"tags": [
"ui",
"components",
@@ -13759,7 +13761,7 @@
"plain-wordmark"
]
},
- "color": "#2D333A",
+ "color": "#4A154B",
"aliases": []
},
{
@@ -13984,7 +13986,7 @@
"original-wordmark"
]
},
- "color": "#0C1724",
+ "color": "#EA005A",
"aliases": [
{
"base": "original-wordmark",
@@ -14086,7 +14088,7 @@
"plain-wordmark"
]
},
- "color": "#333333",
+ "color": "#CA2727",
"aliases": []
},
{
@@ -14291,7 +14293,7 @@
"plain-wordmark"
]
},
- "color": "#000",
+ "color": "#FFFFFF",
"aliases": []
},
{
@@ -14681,7 +14683,7 @@
}
]
},
- {
+ {
"name": "systemverilog",
"altnames": [
"system verilog",
@@ -14801,7 +14803,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#00F076",
"aliases": []
},
{
@@ -14972,7 +14974,7 @@
]
},
"color": "#50d18d",
- "aliases":[
+ "aliases": [
{
"base": "original",
"alias": "plain"
@@ -15163,7 +15165,7 @@
"plain"
]
},
- "color": "#1d1d1b",
+ "color": "#00ADD8",
"aliases": [
{
"base": "plain",
@@ -15387,7 +15389,7 @@
"line-wordmark"
]
},
- "color": "#2d3136",
+ "color": "#CB3349",
"aliases": []
},
{
@@ -15549,7 +15551,7 @@
"line-wordmark"
]
},
- "color": "#000000",
+ "color": "#F14A00",
"aliases": []
},
{
@@ -15931,7 +15933,7 @@
"plain-wordmark"
]
},
- "color": "#141416",
+ "color": "#3DC4FF",
"aliases": []
},
{
@@ -16024,7 +16026,7 @@
}
]
},
- {
+ {
"name": "verilog",
"altnames": [
"verilog hdl"
@@ -16604,7 +16606,7 @@
"plain"
]
},
- "color": "#000000",
+ "color": "#F5C842",
"aliases": []
},
{
@@ -16674,14 +16676,14 @@
"graphics",
"web",
"3d"
- ],
+ ],
"versions": {
"svg": [
"original"
],
- "font": [
+ "font": [
"original"
- ]
+ ]
},
"color": "#990000",
"aliases": [
@@ -16782,7 +16784,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#00CDD7",
"aliases": []
},
{
@@ -16932,10 +16934,10 @@
"plain-wordmark"
]
},
- "color": "#494949",
+ "color": "#21759B",
"aliases": []
},
- {
+ {
"name": "xai",
"altnames": [
"X AI",
@@ -16945,7 +16947,7 @@
"AI",
"assistant",
"language-model",
- "llm"
+ "llm"
],
"versions": {
"svg": [
@@ -17213,7 +17215,7 @@
"plain-wordmark"
]
},
- "color": "#000000",
+ "color": "#FB406D",
"aliases": []
},
{
@@ -17368,7 +17370,7 @@
"line-wordmark"
]
},
- "color": "#000",
+ "color": "#F15A24",
"aliases": []
},
{
@@ -17386,7 +17388,7 @@
"plain"
]
},
- "color": "#443e38",
+ "color": "#685B4F",
"aliases": []
}
]
diff --git a/docs/CNAME b/docs/CNAME
deleted file mode 100644
index 0d1b34d93..000000000
--- a/docs/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-devicon.dev
\ No newline at end of file
diff --git a/docs/assets/css/discord-logo.svg b/docs/assets/css/discord-logo.svg
deleted file mode 100644
index 36ca2de72..000000000
--- a/docs/assets/css/discord-logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/docs/assets/css/style.css b/docs/assets/css/style.css
deleted file mode 100644
index 2ae904529..000000000
--- a/docs/assets/css/style.css
+++ /dev/null
@@ -1,484 +0,0 @@
-@charset "UTF-8";
-@import '//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.min.css';
-@import url(https://fonts.googleapis.com/css?family=Lato:300,400,700);
-@import url(https://fonts.googleapis.com/css?family=Damion);
-:root {
- /* color */
- --primaryColor: #3D9561;
- --primaryColorDark: #2D804E;
- --primaryColorLight: #4AB475;
- --grey: #4c6857;
-
- /* sizing */
- --listItemPadding: 0.4rem;
-}
-
-html {
- box-sizing: border-box; }
-
-*, *::after, *::before {
- box-sizing: inherit; }
-
-.discord-logo:before {
- content: "";
- background-image: url("discord-logo.svg");
- height: 40px;
- width: 40px;
- display: inline-block;
- background-size: cover;
-}
-
-/* General Blueprint Style */
-*,
-*:after,
-*:before {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box; }
-
-body,
-html {
- margin: 0;
- padding: 0;
- font-size: 100%; }
-
-.clearfix:before,
-.clearfix:after {
- display: table;
- content: ' '; }
-
-.clearfix:after {
- clear: both; }
-
-body {
- font-family: 'Lato', Calibri, Arial, sans-serif; }
-
-a {
- color: #f0f0f0;
-}
-
-a:hover {
- color: #000; }
-
-.cbp-ig-grid {
- list-style: none;
- padding: 0 0 50px;
- margin: 0; }
-
-.cbp-ig-grid:before,
-.cbp-ig-grid:after {
- content: " ";
- display: table; }
-
-.cbp-ig-grid:after {
- clear: both; }
-
-.cbp-ig-grid li {
- width: 25%;
- float: left;
- height: 200px;
- text-align: center; }
-
-.cbp-ig-grid li > span {
- display: block;
- height: 100%;
- color: var(--primaryColor);
- -webkit-transition: background 0.2s;
- -moz-transition: background 0.2s;
- transition: background 0.2s;
- cursor: pointer; }
-
-.cbp-ig-icon {
- padding: 30px 0 0;
- display: block;
- -webkit-transition: -webkit-transform 0.2s;
- transition: -moz-transform 0.2s;
- transition: transform 0.2s; }
-
-.cbp-ig-icon:before {
- font-family: 'devicon';
- font-size: 6em;
- speak: none;
- font-style: normal;
- font-weight: normal;
- font-variant: normal;
- text-transform: none;
- line-height: 1;
- -webkit-font-smoothing: antialiased; }
-
-.cbp-ig-grid .cbp-ig-title {
- margin: 20px 0 10px;
- padding: 20px 0 0;
- font-size: 1em;
- position: relative;
- -webkit-transition: -webkit-transform 0.2s;
- -moz-transition: -moz-transform 0.2s;
- transition: transform 0.2s; }
-
-.cbp-ig-grid .cbp-ig-title:before {
- content: '';
- position: absolute;
- background: var(--primaryColor);
- width: 60px;
- height: 2px;
- top: 0;
- left: 50%;
- margin: 0 0 0 -30px;
- -webkit-transition: margin-top 0.2s;
- -moz-transition: margin-top 0.2s;
- transition: margin-top 0.2s; }
-
-.cbp-ig-grid li > span:hover {
- background: var(--primaryColor); }
-
-.cbp-ig-grid li > span:hover .cbp-ig-icon {
- -webkit-transform: translateY(10px);
- -moz-transform: translateY(10px);
- -ms-transform: translateY(10px);
- transform: translateY(10px); }
-
-.cbp-ig-grid li > span:hover .cbp-ig-icon:before,
-.cbp-ig-grid li > span:hover .cbp-ig-title {
- color: #fff; }
-
-.cbp-ig-grid li > span:hover .cbp-ig-title {
- -webkit-transform: translateY(-30px);
- -moz-transform: translateY(-30px);
- -ms-transform: translateY(-30px);
- transform: translateY(-30px); }
-
-.cbp-ig-grid li > span:hover .cbp-ig-title:before {
- background: #fff;
- margin-top: 80px; }
-
-@media screen and (max-width: 62.75em) {
- .cbp-ig-grid li {
- width: 50%; } }
-
-@media screen and (max-width: 41.6em) {
- .cbp-ig-grid li {
- width: 100%; } }
-
-@media screen and (max-width: 25em) {
- .cbp-ig-grid {
- font-size: 80%; } }
-
-html {
- background: whitesmoke; }
-
-html,
-body {
- color: #323232;
- font-size: 14px;
- font-family: "Lato", Calibri, Arial, sans-serif;
- line-height: 1.5; }
-
-::-webkit-input-placeholder {
- color: #4f755e; }
-
-:-moz-placeholder {
- color: #4f755e; }
-
-::-moz-placeholder {
- color: #4f755e; }
-
-:-ms-input-placeholder {
- color: #4f755e; }
-
-html,
-body {
- min-width: 900px; }
-
-header {
- position: fixed;
- top: 0;
- bottom: 0;
- overflow: auto;
- padding: 0 2rem;
- width: 480px;
- color: whitesmoke;
- background: var(--primaryColor); }
- header > h1,
- header > h3 {
- font-weight: 400;
- font-family: "Damion", sans-serif;
- text-align: center; }
- header > h1 {
- margin: 1rem 0 0;
- font-size: 5rem; }
- header > h1 > span {
- font-size: 2rem; }
- header > h2 {
- font-weight: 400;
- font-size: 1.3rem; }
- header .buttonLink {
- margin: 2rem 0 0;
- font-weight: 900;
- font-size: 1.3rem;
- text-align: center; }
- header .buttonLink i {
- position: relative;
- top: 12px;
- left: -10px;
- font-size: 3rem; }
- header .buttonLink > a {
- padding: 1.3rem 1.8rem;
- border: 6px solid var(--primaryColor);
- color: var(--primaryColor);
- background: whitesmoke;
- text-decoration: none;}
- header .buttonLink a:hover {
- border-color: whitesmoke; }
- header > h3 {
- margin: 4rem 0 0;
- font-size: 3rem;
- text-align: left; }
- header > h5 {
- margin: 0;
- font-weight: 400;
- font-style: italic;
- font-size: 1.2rem; }
- header > ul {
- margin: 0;
- padding: 0;
- list-style: none; }
- header > ul h4 {
- margin: 0;
- border-bottom: 1px solid whitesmoke;
- font-size: 1.5rem; }
- header > ul li {
- margin: .8rem 0 2rem; }
- header .icons-list {
- margin: 1rem 0;
- padding: 0;
- list-style: none;
- position: relative; }
- header .icons-list > div {
- display: inline; }
-
- header .icons-list li {
- position: relative;
- display: inline-block;
- width: 6.5rem;
- margin: .5rem .3rem;
- padding: var(--listItemPadding);
- cursor: pointer;
- border: 5px solid var(--primaryColor); }
-
- header .icons-list li:hover {
- border: 5px solid var(--primaryColorLight);
- border-radius: 5px; }
-
- header .icons-list li:hover::before {
- content: ' ';
- position: absolute;
- bottom: -18px;
- left: 25px;
- display: block;
- width: 0px;
- height: 0px;
- border-left: 15px solid transparent;
- border-right: 15px solid transparent;
- border-top: 15px solid var(--primaryColorLight); }
-
- header .icons-list li.selected-version {
- border: 5px solid var(--primaryColorLight);
- border-radius: 5px; }
-
- header .icons-list li.selected-version::before {
- position: absolute;
- bottom: -19px;
- left: 25px;
- display: block;
- width: 0;
- height: 0;
- border-top: 15px solid var(--primaryColorLight);
- border-right: 15px solid transparent;
- border-left: 15px solid transparent;
- content: ' '; }
-
- header .icons-list i,
- .svgLogo {
- font-size: 5rem;
- position: absolute;
- left: 0;
- top: 0;
- margin: var(--listItemPadding);
- }
-
- header .icons-list img {
- max-width: 100%; }
-
-
-/** color picker */
-.colorPicker {
- height: 0.8em;
- width: 0.8em;
- border-radius: 50%;
-}
-
-.colorPicker:hover {
- cursor: pointer;
- border: 1px solid whitesmoke;
-}
-
-.colorPickerMenu {
- position: absolute;
- font-size: 1rem;
- background-color: var(--primaryColor);
- border-radius: 0.2em;
- border: 1px solid var(--grey);
- transform: translate(0, -30%);
- padding: 1em;
- margin-left: 1em;
- font-weight: normal;
- z-index: 1;
- display: none;
- -webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.3);
- box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.3);
-}
-
-.colorPickerMenuCloseBtn > span:hover {
- cursor: pointer;
-}
-
-.colorPickerBtn {
- margin: auto;
- margin-top: 0.5em;
- width: min-content;
- background-color: var(--primaryColor);
- border-radius: 1em;
- border: 1px solid var(--grey);
- display: inline-block;
-}
-
-.colorPickerBtn:hover {
- background-color: var(--grey);
-}
-
-.checkerboardInput {
- width: 1.25em;
- height: 1.25em;
- position: relative;
- top: 0.2em;
-}
-
-.checkerboardInput:hover {
- cursor: pointer;
-}
-
-input[type='color'] {
- width: 1.25em;
- height: 1.25em;
- padding: 0;
-}
-
-input[type='color']:hover {
- cursor: pointer;
-}
-
-/** Copy Btn */
-
-.copyBtn {
- height: 1.25em;
- width: 1.25em;
- margin-left: 0.25em;
- position: relative;
- top: 0.5em;
- border-radius: 20%;
- padding: 0.25em;
- box-sizing: content-box;
- transition: background-color 0.25s;
-}
-
-.copyBtn:hover {
- cursor: pointer;
- background-color: var(--primaryColorDark);
-}
-
-.tooltip {
- visibility: hidden;
- background-color: var(--primaryColorDark);
- border-radius: 0.25em;
- padding: 0.25em;
-}
-
-.borders {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: -1;
- border: 8px solid var(--primaryColor); }
-
-.main {
- margin: 0 0 0 480px; }
-
-.result {
- max-width: 75px;
-}
-
-.computed-data {
- color: var(--primaryColor);
- font-weight: bold;
- list-style: none;
- padding: 0;
- width: 80%;
- margin: 25px auto;
- display: flex;
-}
-
-.computed-data li {
- width: 33.33%;
- text-align: center; }
-
-.search {
- text-align: center;
- margin: 4rem 0 1rem 0; }
-
- .search input {
- padding: .5rem 1rem;
- border: 0;
- border-bottom: 2px solid var(--primaryColor);
- color: var(--primaryColor);
- background: none;
- font-size: 1.2rem;
- text-align: center; }
-
-::-webkit-input-placeholder {
- color: var(--primaryColor); }
-
-:-moz-placeholder {
- /* Firefox 18- */
- color: var(--primaryColor); }
-
-::-moz-placeholder {
- /* Firefox 19+ */
- color: var(--primaryColor); }
-
-:-ms-input-placeholder {
- color: var(--primaryColor); }
-
-/* Code related CSS */
-
-.cde {
- white-space: nowrap;
- padding: 1rem;
- border-radius: 4px;
- color: var(--grey);
- background: var(--primaryColorLight);
- font-size: .9rem;
- font-family: courier;
- overflow: auto; }
-
-.cde-ind {
- padding: 0 0 0 .5rem; }
-
-.cde-com {
- color: var(--grey);
- opacity: .5; }
-
-footer {
- margin-top: 6rem;
- text-align: center; }
diff --git a/docs/assets/img/checkerboard.png b/docs/assets/img/checkerboard.png
deleted file mode 100644
index 1ae989dd5..000000000
Binary files a/docs/assets/img/checkerboard.png and /dev/null differ
diff --git a/docs/assets/img/color_wheel.png b/docs/assets/img/color_wheel.png
deleted file mode 100644
index 65767af81..000000000
Binary files a/docs/assets/img/color_wheel.png and /dev/null differ
diff --git a/docs/assets/img/copy.svg b/docs/assets/img/copy.svg
deleted file mode 100644
index 2ee0e55f0..000000000
--- a/docs/assets/img/copy.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-copy
-
-
diff --git a/docs/assets/img/logo.png b/docs/assets/img/logo.png
deleted file mode 100644
index 11c448ae7..000000000
Binary files a/docs/assets/img/logo.png and /dev/null differ
diff --git a/docs/assets/js/script.js b/docs/assets/js/script.js
deleted file mode 100644
index ded17c898..000000000
--- a/docs/assets/js/script.js
+++ /dev/null
@@ -1,321 +0,0 @@
-var devicon = angular.module('devicon', ['ngSanitize', 'ngAnimate']);
-
-/*
-||==============================================================
-|| Devicons controller
-||==============================================================
-*/
-
-devicon.controller('IconListCtrl', function($scope, $http, $compile) {
-
- // Determination of the latest release tagging
- // which is used for showing in the header of the page
- // as well as for CDN links
- var gitHubPath = 'devicons/devicon';
- var url = 'https://api.github.com/repos/' + gitHubPath + '/tags';
-
- $scope.latestReleaseTagging = 'latest';
- $http.get(url).success(function (data) {
- if(data.length > 0) {
- $scope.latestReleaseTagging = data[0].name;
- }
- }).error(function () {
- console.log('Unable to determine latest release version, fallback to master.')
- });
-
- var versionStr = '@' + $scope.latestReleaseTagging;
- var baseUrl
-
- // Make sure one of the files exist, otherwise, use fallback link.
- var path = '/devicon.json';
- var xhr = new XMLHttpRequest();
- xhr.open('HEAD', path, false);
- xhr.send();
- if (xhr.status == "404") {
- baseUrl = `https://cdn.jsdelivr.net/gh/${gitHubPath}${versionStr}/`
- } else {
- baseUrl = `/`;
- }
-
- $scope.baseUrl = baseUrl
-
- // Get devicon.json
- $http.get(baseUrl + 'devicon.json').success(function(data) {
-
- /*
- | Re-format devicon.json
- |-----------------------------------------
- */
-
- // icons related stuff
- $scope.icons = [];
- $scope.selectedIcon = {};
-
- // Miscellaneous stuff
- $scope.totalFonts = 0; // Total fonts and SVGs combined
-
- // background color related stuff
- // default is the default site background color
- $scope.DEFAULT_BACKGROUND = "#3D9561";
- $scope.fontBackground = $scope.DEFAULT_BACKGROUND;
- $scope.svgBackground = $scope.DEFAULT_BACKGROUND;
-
- // whether to display the checkerboard img in the background
- // for the font and svg respectively
- $scope.fontDisplayChecker = false;
- $scope.svgDisplayChecker = false;
-
- // Loop through devicon.json
- angular.forEach(data, function(devicon, key) {
-
- // New icon format
- var icon = {
- name: devicon.name,
- altnames: devicon.altnames,
- svg: devicon.versions.svg,
- font: devicon.versions.font,
- main: ""
- };
-
- $scope.totalFonts += devicon.versions.font.length + devicon.versions.svg.length;
-
- // Loop through devicon.json icons
- for (var i = 0; i < devicon.versions.font.length; i++) {
-
- // Store all versions that should become main in order
- var mainVersionsArray = [
- "plain",
- "line",
- "original",
- "plain-wordmark",
- "line-wordmark",
- "original-wordmark",
- ];
-
- // Loop through mainVersionsArray
- for (var j = 0; j < mainVersionsArray.length; j++) {
-
- // Check if icon version can be "main", if not continue, if yes break the loops
- if (devicon.name + devicon.versions.font[i] == devicon.name + mainVersionsArray[j]) {
- icon.main = devicon.name + "-" + devicon.versions.font[i];
- i = 99999; // break first loop (and second)
- }
- }
- }
-
- // Push new icon format to $scope.icons
- $scope.icons.push(icon);
- });
-
- // Select first icon by default in scope
- $scope.selectedIcon = $scope.icons[0];
- $scope.selectedFontIcon = $scope.icons[0].font[0];
- $scope.selectedSvgIcon = $scope.selectSvg($scope.icons[0].svg[0], 0);
- $scope.selectedFontIndex = 0;
- $scope.selectedSvgIndex = 0;
-
- // Computes miscellaneous data
- $scope.avgFonts = $scope.totalFonts / $scope.icons.length // Avg number of fonts and SVGs combined
-
- /*------ End of "Re-format devicon.json" ------*/
- });
-
- /*
- | Change selected icon
- | param icon: the new icon.
- |--------------------------------
- */
- $scope.selectIcon = function(icon) {
- $scope.selectedIcon = icon;
- $scope.selectedFontIcon = icon.font[0];
- $scope.selectedFontIndex = 0;
- $scope.selectedSvgIcon = $scope.selectSvg(icon.svg[0], 0);
- $scope.selectedSvgIndex = 0;
-
- // reset color
- $scope.fontBackground = $scope.DEFAULT_BACKGROUND;
- $scope.svgBackground = $scope.DEFAULT_BACKGROUND;
- }
- /*---- End of "Change selected icon" ----*/
-
-
- /*
- | Change selected icon font version
- |--------------------------------
- */
- $scope.selectFont = function(fontVersion, colored, index) {
- $scope.selectedFontIcon = fontVersion;
- $scope.colored = colored ? true : false;
- $scope.selectedFontIndex = index;
- }
- /*---- End of "Change selected font icon" ----*/
-
- /*
- | Change selected icon svg version
- |--------------------------------
- */
- $scope.selectSvg = function(svgVersion, index) {
-
- $http.get(baseUrl + 'icons/' + $scope.selectedIcon.name + '/' + $scope.selectedIcon.name + '-' + svgVersion + '.svg').success(function(data){
-
- var svgElement = angular.element(data);
- var innerSvgElement = null;
-
- /**
- * Loop trough svg image to find
- * the actual svg content (not any comments or stuff
- * we don't care for).
- * See https://github.com/devicons/devicon/issues/444#issuecomment-753699913
- */
- for (const [key, value] of Object.entries(svgElement)) {
- /** [object SVGSVGElement] ensures we have the actual svg content */
- if(value.toString() == '[object SVGSVGElement]') {
- innerSvgElement = value;
- break;
- }
- }
-
- if(innerSvgElement === null) {
- console.error('Could not find content of given SVG.')
- } else {
- var innerSVG = (innerSvgElement.innerHTML);
- $scope.selectedSvgIcon = innerSVG;
- $scope.selectedSvgIndex = index;
- }
- });
- }
-
- /*---- End of "Change selected svg icon" ----*/
-
- /**
- * Copy the text located using `id` into the user's clipboard.
- * @param {Event} event - a JS Event object.
- * @param {String} id - id of the element we are copying its text
- * content from.
- */
- $scope.copyToClipboard = function(event, id) {
- let text = document.getElementById(id).textContent
- navigator.clipboard.writeText(text)
- .then(() => {
- $scope.displayTooltip("Copied", event.target)
- })
- .catch(() => {
- $scope.displayTooltip("Failed to copy", event.target)
- })
- }
-
- /**
- * Display a tooltip.
- * @param {String} text - text the tooltip should have.
- * @param {Element} copyBtn - the copyBtn element, which is an
- */
- $scope.displayTooltip = function(text, copyBtn) {
- let tooltip = copyBtn.parentElement.getElementsByClassName("tooltip")[0]
- tooltip.textContent = text
- // reset opacity (for some reason, default opacity is null)
- tooltip.style.opacity = 1
- tooltip.style.visibility = "visible"
-
- // create fade out effect after 2 sec
- setTimeout(() => {
- let count = 10
- let intervalObj
- intervalObj = setInterval(() => {
- tooltip.style.opacity -= 0.1
- if (--count == 0) {
- clearInterval(intervalObj)
- tooltip.style.visibility = "hidden"
- }
- }, 50)
- }, 2000)
- }
-
- /**
- * Display the color picker.
- * @param {String} id - id of the menu we are showing.
- */
- $scope.toggleColorPickerMenu = function(id) {
- let menu = document.getElementById(id)
- menu.style.display = menu.style.display == "none" || menu.style.display == "" ? "inherit" : "none"
- }
-});
-
-/*================ End of "Devicons controller" ================*/
-
-/*
-||==================================================================
-|| Convert icon img to svg
-||==================================================================
-*/
-
-devicon.directive('imgToSvg', function ($http, $compile) {
-
- var baseUrl = window.location.href;
-
- return {
- link : function($scope, $element, $attrs) {
-
- $attrs.$observe('src', function(val){
-
- $http.get(baseUrl + val).success(function(data){
-
- var svg = angular.element(data);
- svg = svg.removeAttr('xmlns');
- svg = svg.addClass('not-colored');
- svg = svg.attr('svg-color', '');
- var $e = $compile(svg)($scope);
- $element.replaceWith($e);
- $element = $e;
- });
- });
- }
- };
-});
-
-/*================ End of "Convert icon img to svg" ================*/
-
-/*
-||==================================================================
-|| Add color to svg when hovering
-||==================================================================
-*/
-
-devicon.directive('svgColor', function () {
-
- return {
- link : function($scope, $element, $attrs) {
- $element.on('mouseenter', function(){
- $element.removeClass('not-colored');
- });
- $element.on('mouseleave', function(){
- $element.addClass('not-colored');
- });
- }
- };
-});
-
-/*================ End of "Add color to svg when hovering" ================*/
-
-/*
-||==================================================================
-|| Show all icons on click
-||==================================================================
-*/
-
-devicon.directive('iconDetails', function ($http, $compile) {
-
- return {
- template: '
',
- replace: true,
- scope: {
- icon: "="
- },
- compile: function CompilingFunction($templateElement) {
- $element.on('click', function(){
- $templateElement.replaceWith(this.template);
- });
- }
- };
-});
-
-/*================ End of "Add color to svg when hovering" ================*/
diff --git a/docs/browserconfig.xml b/docs/browserconfig.xml
deleted file mode 100644
index fe44cae80..000000000
--- a/docs/browserconfig.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
- #da532c
-
-
-
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100644
index 80f1fbf8c..000000000
--- a/docs/index.html
+++ /dev/null
@@ -1,248 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
DEVICON | All programming languages and development tools related icons font
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- To use this website, JavaScript needs to be enabled.
- You can come back when you turn it on though :)
-
-
-
-
-
-
- Devicon is a set of icons representing programming languages, designing, and development tools. You can use it as a font or directly copy/paste the SVG code into your project.
- *Please read the legal conditions of using the logos here at the bottom of this header
- (Super) Quick Setup
- First select an icon on the right, then select the version below and copy/paste the code into your project.
-
-
-
- Font versions
-
-
-
-
-
-
- Place this in your header (once per HTML file)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Place this in your body
-
-
-
-
-
-
- <i class="devicon-{{selectedIcon.name}}-{{selectedFontIcon}} colored "></i>
-
- *To change the size, change the <i>'s `font-size`.
-
-
-
- SVG versions
-
-
-
-
-
-
-
-
-
-
-
-
- Using <img> element
-
-
-
-
-
-
- <img src="{{baseUrl}}icons/{{selectedIcon.name}}/{{selectedIcon.name}}-{{selectedIcon.svg[selectedSvgIndex]}}.svg" />
-
- *To change the size, change the <img>'s `height` and `width`.
-
-
-
-
- Using Pure SVG
-
-
-
-
-
-
- <svg viewBox="0 0 128 128">
-
{{selectedSvgIcon}}
- </svg>
-
- *To change the size, change the <svg>'s `height` and `width`.
-
-
-
- GitHub repository
- If you prefer a local install, you can download all the files on the GitHub repository.
- Check out our ultimate guide in order to compile Devicon locally.
-
- DOWNLOAD
-
-
- GO TO THE REPOSITORY
-
-
- CONTRIBUTE
-
-
- DISCORD COMMUNITY
-
-
- Contact
- If you have any legal concerns regarding copyrights or want to report an abuse, please reach out to us via info@devicon.dev or our Discord community . Any code/logo contributions should be made through our GitHub repository listed above.
-
-
- Originally created by Konpa (under the MIT License ) and
- supported by many contributors .
- Copyright © 2015 Konpa
-
- Final font built with IcoMoon
-
- *All product names, logos, and brandsare property of their respective owners. All company, product and service names used in this website are for identification purposes only. Usage of these names, logos, and brands does not imply endorsement of Devicon or its members. All icons/SVGs in this project are not monetized in anyway. It is up to the user to use the logo properly according to the company/group's brand policy. Usage of this site or any icons/SVGs from Devicon means acknowledgement of these conditions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/manifest.json b/docs/manifest.json
deleted file mode 100644
index eca47a649..000000000
--- a/docs/manifest.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "name": "Devicon",
- "icons": [
- {
- "src": "\/logos/android-chrome-36x36.png",
- "sizes": "36x36",
- "type": "image\/png",
- "density": "0.75"
- },
- {
- "src": "\/logos/android-chrome-48x48.png",
- "sizes": "48x48",
- "type": "image\/png",
- "density": "1.0"
- },
- {
- "src": "\/logos/android-chrome-72x72.png",
- "sizes": "72x72",
- "type": "image\/png",
- "density": "1.5"
- },
- {
- "src": "\/logos/android-chrome-96x96.png",
- "sizes": "96x96",
- "type": "image\/png",
- "density": "2.0"
- },
- {
- "src": "\/logos/android-chrome-144x144.png",
- "sizes": "144x144",
- "type": "image\/png",
- "density": "3.0"
- },
- {
- "src": "\/logos/android-chrome-192x192.png",
- "sizes": "192x192",
- "type": "image\/png",
- "density": "4.0"
- }
- ]
-}
diff --git a/docs/wiki/import_icomoon.PNG b/docs/wiki/import_icomoon.PNG
deleted file mode 100644
index aa6f93064..000000000
Binary files a/docs/wiki/import_icomoon.PNG and /dev/null differ
diff --git a/docs/wiki/issue_form.png b/docs/wiki/issue_form.png
deleted file mode 100644
index 13b46b187..000000000
Binary files a/docs/wiki/issue_form.png and /dev/null differ
diff --git a/docs/wiki/organization_rule.PNG b/docs/wiki/organization_rule.PNG
deleted file mode 100644
index 3a8ec5d57..000000000
Binary files a/docs/wiki/organization_rule.PNG and /dev/null differ
diff --git a/docs/wiki/svg_standards.PNG b/docs/wiki/svg_standards.PNG
deleted file mode 100644
index 4df0e4a37..000000000
Binary files a/docs/wiki/svg_standards.PNG and /dev/null differ
diff --git a/icons/githubcopilot/githubcopilot-original-wordmark.svg b/icons/githubcopilot/githubcopilot-original-wordmark.svg
index 0e61c98ed..be5e6221f 100644
--- a/icons/githubcopilot/githubcopilot-original-wordmark.svg
+++ b/icons/githubcopilot/githubcopilot-original-wordmark.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/icons/githubcopilot/githubcopilot-original.svg b/icons/githubcopilot/githubcopilot-original.svg
index 4d3d0d75b..332bd024d 100644
--- a/icons/githubcopilot/githubcopilot-original.svg
+++ b/icons/githubcopilot/githubcopilot-original.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/package.json b/package.json
index aab7b26e7..88efa00fb 100644
--- a/package.json
+++ b/package.json
@@ -12,9 +12,11 @@
"build-icons:linux:macOS": "python ./.github/scripts/icomoon_build_githubless.py ./.github/scripts/build_assets/geckodriver-v0.32.2-linux64/geckodriver ./icomoon.json ./devicon.json ./icons ./ --headless",
"build-icons:windows": "python ./.github/scripts/icomoon_build_githubless.py ./.github/scripts/build_assets/geckodriver-v0.32.2-win64/geckodriver.exe ./icomoon.json ./devicon.json ./icons ./ --headless",
"build-icons:default": "echo 'Unsupported OS' && exit 1",
- "dev": "concurrently \"npm:open-browser\" \"npm:start-local-server\"",
- "start-local-server": "python -m http.server 8000",
- "open-browser": "node -e \"import('open').then(pkg => pkg.default('http://localhost:8000/docs'))\""
+ "dev": "npm run site:dev",
+ "site:dev": "pnpm --dir site dev",
+ "site:build": "pnpm --dir site build",
+ "site:preview": "pnpm --dir site preview",
+ "site:check": "pnpm --dir site check"
},
"repository": {
"type": "git",
diff --git a/site/.gitignore b/site/.gitignore
new file mode 100644
index 000000000..4e120c1bc
--- /dev/null
+++ b/site/.gitignore
@@ -0,0 +1,26 @@
+node_modules
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
+
+# Generated assets
+/static/devicon.json
diff --git a/site/.npmrc b/site/.npmrc
new file mode 100644
index 000000000..dd75c6b69
--- /dev/null
+++ b/site/.npmrc
@@ -0,0 +1,2 @@
+engine-strict=true
+verify-deps-before-run=false
diff --git a/site/LICENSE b/site/LICENSE
new file mode 100644
index 000000000..f306172b9
--- /dev/null
+++ b/site/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) 2025 - present devicon
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/site/README.md b/site/README.md
new file mode 100644
index 000000000..c65b7f84c
--- /dev/null
+++ b/site/README.md
@@ -0,0 +1,36 @@
+# Devicon.dev
+
+Website for devicon
+
+## Running locally
+
+You'll need node and pnpm setup.
+
+First install dependencies with:
+
+```bash
+pnpm install
+```
+
+Then start server with:
+
+```bash
+pnpm run dev
+
+# or start the server and open the app in a new browser tab
+pnpm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```bash
+pnpm run build
+```
+
+You can preview the production build with `pnpm run preview`.
+
+## Acknowledgements
+
+Design for this webapp is heavily inspired by [@risbi0](https://github.com/risbi0)'s [work](https://risbi0.github.io/devicon-new-ui/) on revamping devicon website
diff --git a/site/biome.json b/site/biome.json
new file mode 100644
index 000000000..1dbde9f84
--- /dev/null
+++ b/site/biome.json
@@ -0,0 +1,43 @@
+{
+ "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
+ "vcs": {
+ "enabled": false,
+ "clientKind": "git",
+ "useIgnoreFile": false
+ },
+ "files": {
+ "ignoreUnknown": false,
+ "includes": [
+ "src/**/*.ts",
+ "src/**/*.js",
+ "vite.config.ts",
+ "svelte.config.js"
+ ]
+ },
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space",
+ "indentWidth": 2
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true
+ }
+ },
+ "javascript": {
+ "formatter": {
+ "quoteStyle": "double",
+ "indentWidth": 2,
+ "semicolons": "asNeeded"
+ }
+ },
+ "assist": {
+ "enabled": true,
+ "actions": {
+ "source": {
+ "organizeImports": "on"
+ }
+ }
+ }
+}
diff --git a/site/package.json b/site/package.json
new file mode 100644
index 000000000..a25065434
--- /dev/null
+++ b/site/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "devicons.dev",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "prepare": "svelte-kit sync || echo ''",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "format": "biome format --write .",
+ "lint": "biome lint ."
+ },
+ "devDependencies": {
+ "@biomejs/biome": "2.2.0",
+ "@sveltejs/adapter-auto": "^4.0.0",
+ "@sveltejs/adapter-static": "^3.0.10",
+ "@sveltejs/kit": "^2.20.6",
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
+ "@types/node": "^26.6.6",
+ "svelte": "^5.0.0",
+ "svelte-check": "^4.0.0",
+ "typescript": "^5.0.0",
+ "vite": "^6.4.1",
+ "vitest": "^3.2.4"
+ },
+ "dependencies": {
+ "@tailwindcss/vite": "^4.0.12",
+ "devicon": "^2.18.0",
+ "tailwindcss": "^4.0.12"
+ }
+}
diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml
new file mode 100644
index 000000000..fbafeefa0
--- /dev/null
+++ b/site/pnpm-lock.yaml
@@ -0,0 +1,1770 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@tailwindcss/vite':
+ specifier: ^4.0.12
+ version: 4.0.12(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ devicon:
+ specifier: ^2.18.0
+ version: 2.18.0
+ tailwindcss:
+ specifier: ^4.0.12
+ version: 4.0.12
+ devDependencies:
+ '@biomejs/biome':
+ specifier: 2.2.0
+ version: 2.2.0
+ '@sveltejs/adapter-auto':
+ specifier: ^4.0.0
+ version: 4.0.0(@sveltejs/kit@2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))
+ '@sveltejs/adapter-static':
+ specifier: ^3.0.10
+ version: 3.0.10(@sveltejs/kit@2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))
+ '@sveltejs/kit':
+ specifier: ^2.20.6
+ version: 2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ '@sveltejs/vite-plugin-svelte':
+ specifier: ^5.0.0
+ version: 5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ '@types/node':
+ specifier: ^26.6.6
+ version: 26.6.6
+ svelte:
+ specifier: ^5.0.0
+ version: 5.20.5
+ svelte-check:
+ specifier: ^4.0.0
+ version: 4.1.4(picomatch@4.0.3)(svelte@5.20.5)(typescript@5.8.2)
+ typescript:
+ specifier: ^5.0.0
+ version: 5.8.2
+ vite:
+ specifier: ^6.4.1
+ version: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+ vitest:
+ specifier: ^3.2.4
+ version: 3.2.4(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+
+packages:
+
+ '@ampproject/remapping@2.3.0':
+ resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
+ engines: {node: '>=6.0.0'}
+
+ '@biomejs/biome@2.2.0':
+ resolution: {integrity: sha512-3On3RSYLsX+n9KnoSgfoYlckYBoU6VRM22cw1gB4Y0OuUVSYd/O/2saOJMrA4HFfA1Ff0eacOvMN1yAAvHtzIw==}
+ engines: {node: '>=14.21.3'}
+ hasBin: true
+
+ '@biomejs/cli-darwin-arm64@2.2.0':
+ resolution: {integrity: sha512-zKbwUUh+9uFmWfS8IFxmVD6XwqFcENjZvEyfOxHs1epjdH3wyyMQG80FGDsmauPwS2r5kXdEM0v/+dTIA9FXAg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@biomejs/cli-darwin-x64@2.2.0':
+ resolution: {integrity: sha512-+OmT4dsX2eTfhD5crUOPw3RPhaR+SKVspvGVmSdZ9y9O/AgL8pla6T4hOn1q+VAFBHuHhsdxDRJgFCSC7RaMOw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@biomejs/cli-linux-arm64-musl@2.2.0':
+ resolution: {integrity: sha512-egKpOa+4FL9YO+SMUMLUvf543cprjevNc3CAgDNFLcjknuNMcZ0GLJYa3EGTCR2xIkIUJDVneBV3O9OcIlCEZQ==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-arm64@2.2.0':
+ resolution: {integrity: sha512-6eoRdF2yW5FnW9Lpeivh7Mayhq0KDdaDMYOJnH9aT02KuSIX5V1HmWJCQQPwIQbhDh68Zrcpl8inRlTEan0SXw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64-musl@2.2.0':
+ resolution: {integrity: sha512-I5J85yWwUWpgJyC1CcytNSGusu2p9HjDnOPAFG4Y515hwRD0jpR9sT9/T1cKHtuCvEQ/sBvx+6zhz9l9wEJGAg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64@2.2.0':
+ resolution: {integrity: sha512-5UmQx/OZAfJfi25zAnAGHUMuOd+LOsliIt119x2soA2gLggQYrVPA+2kMUxR6Mw5M1deUF/AWWP2qpxgH7Nyfw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-win32-arm64@2.2.0':
+ resolution: {integrity: sha512-n9a1/f2CwIDmNMNkFs+JI0ZjFnMO0jdOyGNtihgUNFnlmd84yIYY2KMTBmMV58ZlVHjgmY5Y6E1hVTnSRieggA==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@biomejs/cli-win32-x64@2.2.0':
+ resolution: {integrity: sha512-Nawu5nHjP/zPKTIryh2AavzTc/KEg4um/MxWdXW0A6P/RZOyIpa7+QSjeXwAwX/utJGaCoXRPWtF3m5U/bB3Ww==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/aix-ppc64@0.25.11':
+ resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.11':
+ resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.11':
+ resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.11':
+ resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.11':
+ resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.11':
+ resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.11':
+ resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.11':
+ resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.11':
+ resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.11':
+ resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.11':
+ resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.11':
+ resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.11':
+ resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.11':
+ resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.11':
+ resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.11':
+ resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.11':
+ resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.11':
+ resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.11':
+ resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.11':
+ resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.11':
+ resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.11':
+ resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.11':
+ resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.11':
+ resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.11':
+ resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.11':
+ resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@jridgewell/gen-mapping@0.3.8':
+ resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/set-array@1.2.1':
+ resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.0':
+ resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+
+ '@polka/url@1.0.0-next.29':
+ resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
+
+ '@rollup/rollup-android-arm-eabi@4.52.5':
+ resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.52.5':
+ resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.52.5':
+ resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.52.5':
+ resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.52.5':
+ resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.52.5':
+ resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.5':
+ resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.5':
+ resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.5':
+ resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.52.5':
+ resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.5':
+ resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.5':
+ resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.5':
+ resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.5':
+ resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.5':
+ resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.52.5':
+ resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.52.5':
+ resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openharmony-arm64@4.52.5':
+ resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.5':
+ resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.5':
+ resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.52.5':
+ resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.52.5':
+ resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@sveltejs/adapter-auto@4.0.0':
+ resolution: {integrity: sha512-kmuYSQdD2AwThymQF0haQhM8rE5rhutQXG4LNbnbShwhMO4qQGnKaaTy+88DuNSuoQDi58+thpq8XpHc1+oEKQ==}
+ peerDependencies:
+ '@sveltejs/kit': ^2.0.0
+
+ '@sveltejs/adapter-static@3.0.10':
+ resolution: {integrity: sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==}
+ peerDependencies:
+ '@sveltejs/kit': ^2.0.0
+
+ '@sveltejs/kit@2.20.6':
+ resolution: {integrity: sha512-ImUkSQ//Xf4N9r0HHAe5vRA7RyQ7U1Ue1YUT235Ig+IiIqbsixEulHTHrP5LtBiC8xOkJoPZQ1VZ/nWHNOaGGw==}
+ engines: {node: '>=18.13'}
+ hasBin: true
+ peerDependencies:
+ '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0
+ svelte: ^4.0.0 || ^5.0.0-next.0
+ vite: ^5.0.3 || ^6.0.0
+
+ '@sveltejs/vite-plugin-svelte-inspector@4.0.1':
+ resolution: {integrity: sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22}
+ peerDependencies:
+ '@sveltejs/vite-plugin-svelte': ^5.0.0
+ svelte: ^5.0.0
+ vite: ^6.0.0
+
+ '@sveltejs/vite-plugin-svelte@5.0.3':
+ resolution: {integrity: sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22}
+ peerDependencies:
+ svelte: ^5.0.0
+ vite: ^6.0.0
+
+ '@tailwindcss/node@4.0.12':
+ resolution: {integrity: sha512-a6J11K1Ztdln9OrGfoM75/hChYPcHYGNYimqciMrvKXRmmPaS8XZTHhdvb5a3glz4Kd4ZxE1MnuFE2c0fGGmtg==}
+
+ '@tailwindcss/oxide-android-arm64@4.0.12':
+ resolution: {integrity: sha512-dAXCaemu3mHLXcA5GwGlQynX8n7tTdvn5i1zAxRvZ5iC9fWLl5bGnjZnzrQqT7ttxCvRwdVf3IHUnMVdDBO/kQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.0.12':
+ resolution: {integrity: sha512-vPNI+TpJQ7sizselDXIJdYkx9Cu6JBdtmRWujw9pVIxW8uz3O2PjgGGzL/7A0sXI8XDjSyRChrUnEW9rQygmJQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.0.12':
+ resolution: {integrity: sha512-RL/9jM41Fdq4Efr35C5wgLx98BirnrfwuD+zgMFK6Ir68HeOSqBhW9jsEeC7Y/JcGyPd3MEoJVIU4fAb7YLg7A==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.0.12':
+ resolution: {integrity: sha512-7WzWiax+LguJcMEimY0Q4sBLlFXu1tYxVka3+G2M9KmU/3m84J3jAIV4KZWnockbHsbb2XgrEjtlJKVwHQCoRA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12':
+ resolution: {integrity: sha512-X9LRC7jjE1QlfIaBbXjY0PGeQP87lz5mEfLSVs2J1yRc9PSg1tEPS9NBqY4BU9v5toZgJgzKeaNltORyTs22TQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.0.12':
+ resolution: {integrity: sha512-i24IFNq2402zfDdoWKypXz0ZNS2G4NKaA82tgBlE2OhHIE+4mg2JDb5wVfyP6R+MCm5grgXvurcIcKWvo44QiQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.0.12':
+ resolution: {integrity: sha512-LmOdshJBfAGIBG0DdBWhI0n5LTMurnGGJCHcsm9F//ISfsHtCnnYIKgYQui5oOz1SUCkqsMGfkAzWyNKZqbGNw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.0.12':
+ resolution: {integrity: sha512-OSK667qZRH30ep8RiHbZDQfqkXjnzKxdn0oRwWzgCO8CoTxV+MvIkd0BWdQbYtYuM1wrakARV/Hwp0eA/qzdbw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.0.12':
+ resolution: {integrity: sha512-uylhWq6OWQ8krV8Jk+v0H/3AZKJW6xYMgNMyNnUbbYXWi7hIVdxRKNUB5UvrlC3RxtgsK5EAV2i1CWTRsNcAnA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.0.12':
+ resolution: {integrity: sha512-XDLnhMoXZEEOir1LK43/gHHwK84V1GlV8+pAncUAIN2wloeD+nNciI9WRIY/BeFTqES22DhTIGoilSO39xDb2g==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.0.12':
+ resolution: {integrity: sha512-I/BbjCLpKDQucvtn6rFuYLst1nfFwSMYyPzkx/095RE+tuzk5+fwXuzQh7T3fIBTcbn82qH/sFka7yPGA50tLw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.0.12':
+ resolution: {integrity: sha512-DWb+myvJB9xJwelwT9GHaMc1qJj6MDXRDR0CS+T8IdkejAtu8ctJAgV4r1drQJLPeS7mNwq2UHW2GWrudTf63A==}
+ engines: {node: '>= 10'}
+
+ '@tailwindcss/vite@4.0.12':
+ resolution: {integrity: sha512-JM3gp601UJiryIZ9R2bSqalzcOy15RCybQ1Q+BJqDEwVyo4LkWKeqQAcrpHapWXY31OJFTuOUVBFDWMhzHm2Bg==}
+ peerDependencies:
+ vite: ^5.2.0 || ^6
+
+ '@types/chai@5.2.3':
+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
+ '@types/cookie@0.6.0':
+ resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
+
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
+ '@types/estree@1.0.6':
+ resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/node@26.6.6':
+ resolution: {integrity: sha512-MzQj+8Kx3XI40OmUAE6Qoh58ZMNstNNMwn2nfd3qWsfe7nDNSqJNzes4njhz6AHwrSHOffSLwXU6yb474Q4aog==}
+
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
+
+ '@vitest/mocker@3.2.4':
+ resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
+
+ '@vitest/runner@3.2.4':
+ resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
+
+ '@vitest/snapshot@3.2.4':
+ resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
+
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
+
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
+
+ acorn-typescript@1.4.13:
+ resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==}
+ peerDependencies:
+ acorn: '>=8.9.0'
+
+ acorn@8.14.0:
+ resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
+ axobject-query@4.1.0:
+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+ engines: {node: '>= 0.4'}
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ chai@5.3.3:
+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
+ engines: {node: '>=18'}
+
+ check-error@2.1.1:
+ resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
+ engines: {node: '>= 16'}
+
+ chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+ engines: {node: '>= 14.16.0'}
+
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ cookie@0.6.0:
+ resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
+ engines: {node: '>= 0.6'}
+
+ debug@4.4.0:
+ resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ deep-eql@5.0.2:
+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
+ engines: {node: '>=6'}
+
+ deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+
+ detect-libc@2.0.3:
+ resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+ engines: {node: '>=8'}
+
+ devalue@5.3.2:
+ resolution: {integrity: sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==}
+
+ devicon@2.18.0:
+ resolution: {integrity: sha512-jmLZPdTfO9d0GlnTX8Qw2SxZj71My6WAVEZtgmWErVju/uSUqmk2hxKzXo9Pw7IfqV9PEwcOKrywZA1etryRPA==}
+
+ enhanced-resolve@5.18.1:
+ resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
+ engines: {node: '>=10.13.0'}
+
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+
+ esbuild@0.25.11:
+ resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ esm-env@1.2.2:
+ resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
+
+ esrap@1.4.5:
+ resolution: {integrity: sha512-CjNMjkBWWZeHn+VX+gS8YvFwJ5+NDhg8aWZBSFJPR8qQduDNjbJodA2WcwCm7uQa5Rjqj+nZvVmceg1RbHFB9g==}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ expect-type@1.2.2:
+ resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
+ engines: {node: '>=12.0.0'}
+
+ fdir@6.4.3:
+ resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ import-meta-resolve@4.2.0:
+ resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
+
+ is-reference@3.0.3:
+ resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
+
+ jiti@2.4.2:
+ resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
+ hasBin: true
+
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+
+ kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+
+ lightningcss-darwin-arm64@1.29.2:
+ resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.29.2:
+ resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.29.2:
+ resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.29.2:
+ resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.29.2:
+ resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-arm64-musl@1.29.2:
+ resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-x64-gnu@1.29.2:
+ resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-linux-x64-musl@1.29.2:
+ resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.29.2:
+ resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.29.2:
+ resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.29.2:
+ resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
+ engines: {node: '>= 12.0.0'}
+
+ locate-character@3.0.0:
+ resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
+
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
+
+ magic-string@0.30.17:
+ resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+
+ magic-string@0.30.19:
+ resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
+
+ mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+
+ mrmime@2.0.1:
+ resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
+ engines: {node: '>=10'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ pathval@2.0.1:
+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
+ engines: {node: '>= 14.16'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
+
+ rollup@4.52.5:
+ resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ sade@1.8.1:
+ resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
+ engines: {node: '>=6'}
+
+ set-cookie-parser@2.7.1:
+ resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ sirv@3.0.2:
+ resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
+ engines: {node: '>=18'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+
+ strip-literal@3.1.0:
+ resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
+
+ svelte-check@4.1.4:
+ resolution: {integrity: sha512-v0j7yLbT29MezzaQJPEDwksybTE2Ups9rUxEXy92T06TiA0cbqcO8wAOwNUVkFW6B0hsYHA+oAX3BS8b/2oHtw==}
+ engines: {node: '>= 18.0.0'}
+ hasBin: true
+ peerDependencies:
+ svelte: ^4.0.0 || ^5.0.0-next.0
+ typescript: '>=5.0.0'
+
+ svelte@5.20.5:
+ resolution: {integrity: sha512-dpu2lTPVsAAgZFKpF7A9741sBCdXGogfxFU4aQeVgun7GVNCSVheTzj0FsT7g9OsLhBaMX4lKLwVIvmzQGytmQ==}
+ engines: {node: '>=18'}
+
+ tailwindcss@4.0.12:
+ resolution: {integrity: sha512-bT0hJo91FtncsAMSsMzUkoo/iEU0Xs5xgFgVC9XmdM9bw5MhZuQFjPNl6wxAE0SiQF/YTZJa+PndGWYSDtuxAg==}
+
+ tapable@2.2.1:
+ resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
+ engines: {node: '>=6'}
+
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+
+ tinyrainbow@2.0.0:
+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
+ engines: {node: '>=14.0.0'}
+
+ tinyspy@4.0.4:
+ resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
+ engines: {node: '>=14.0.0'}
+
+ totalist@3.0.1:
+ resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
+ engines: {node: '>=6'}
+
+ typescript@5.8.2:
+ resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@8.9.0:
+ resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==}
+
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+
+ vite@6.4.1:
+ resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitefu@1.0.6:
+ resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==}
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
+ vitest@3.2.4:
+ resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/debug': ^4.1.12
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/debug':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ zimmerframe@1.1.2:
+ resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
+
+snapshots:
+
+ '@ampproject/remapping@2.3.0':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.8
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@biomejs/biome@2.2.0':
+ optionalDependencies:
+ '@biomejs/cli-darwin-arm64': 2.2.0
+ '@biomejs/cli-darwin-x64': 2.2.0
+ '@biomejs/cli-linux-arm64': 2.2.0
+ '@biomejs/cli-linux-arm64-musl': 2.2.0
+ '@biomejs/cli-linux-x64': 2.2.0
+ '@biomejs/cli-linux-x64-musl': 2.2.0
+ '@biomejs/cli-win32-arm64': 2.2.0
+ '@biomejs/cli-win32-x64': 2.2.0
+
+ '@biomejs/cli-darwin-arm64@2.2.0':
+ optional: true
+
+ '@biomejs/cli-darwin-x64@2.2.0':
+ optional: true
+
+ '@biomejs/cli-linux-arm64-musl@2.2.0':
+ optional: true
+
+ '@biomejs/cli-linux-arm64@2.2.0':
+ optional: true
+
+ '@biomejs/cli-linux-x64-musl@2.2.0':
+ optional: true
+
+ '@biomejs/cli-linux-x64@2.2.0':
+ optional: true
+
+ '@biomejs/cli-win32-arm64@2.2.0':
+ optional: true
+
+ '@biomejs/cli-win32-x64@2.2.0':
+ optional: true
+
+ '@esbuild/aix-ppc64@0.25.11':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/android-arm@0.25.11':
+ optional: true
+
+ '@esbuild/android-x64@0.25.11':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.11':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.11':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.11':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.11':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.11':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.11':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.11':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.11':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.11':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.11':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.11':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.11':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.11':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.11':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.11':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.11':
+ optional: true
+
+ '@jridgewell/gen-mapping@0.3.8':
+ dependencies:
+ '@jridgewell/set-array': 1.2.1
+ '@jridgewell/sourcemap-codec': 1.5.0
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/set-array@1.2.1': {}
+
+ '@jridgewell/sourcemap-codec@1.5.0': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ '@polka/url@1.0.0-next.29': {}
+
+ '@rollup/rollup-android-arm-eabi@4.52.5':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.52.5':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.52.5':
+ optional: true
+
+ '@sveltejs/adapter-auto@4.0.0(@sveltejs/kit@2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))':
+ dependencies:
+ '@sveltejs/kit': 2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ import-meta-resolve: 4.2.0
+
+ '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))':
+ dependencies:
+ '@sveltejs/kit': 2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+
+ '@sveltejs/kit@2.20.6(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))':
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ '@types/cookie': 0.6.0
+ cookie: 0.6.0
+ devalue: 5.3.2
+ esm-env: 1.2.2
+ import-meta-resolve: 4.2.0
+ kleur: 4.1.5
+ magic-string: 0.30.19
+ mrmime: 2.0.1
+ sade: 1.8.1
+ set-cookie-parser: 2.7.1
+ sirv: 3.0.2
+ svelte: 5.20.5
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+
+ '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))':
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ debug: 4.4.0
+ svelte: 5.20.5
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))':
+ dependencies:
+ '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.20.5)(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ debug: 4.4.0
+ deepmerge: 4.3.1
+ kleur: 4.1.5
+ magic-string: 0.30.17
+ svelte: 5.20.5
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+ vitefu: 1.0.6(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ transitivePeerDependencies:
+ - supports-color
+
+ '@tailwindcss/node@4.0.12':
+ dependencies:
+ enhanced-resolve: 5.18.1
+ jiti: 2.4.2
+ tailwindcss: 4.0.12
+
+ '@tailwindcss/oxide-android-arm64@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.0.12':
+ optional: true
+
+ '@tailwindcss/oxide@4.0.12':
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.0.12
+ '@tailwindcss/oxide-darwin-arm64': 4.0.12
+ '@tailwindcss/oxide-darwin-x64': 4.0.12
+ '@tailwindcss/oxide-freebsd-x64': 4.0.12
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.12
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.0.12
+ '@tailwindcss/oxide-linux-arm64-musl': 4.0.12
+ '@tailwindcss/oxide-linux-x64-gnu': 4.0.12
+ '@tailwindcss/oxide-linux-x64-musl': 4.0.12
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.0.12
+ '@tailwindcss/oxide-win32-x64-msvc': 4.0.12
+
+ '@tailwindcss/vite@4.0.12(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))':
+ dependencies:
+ '@tailwindcss/node': 4.0.12
+ '@tailwindcss/oxide': 4.0.12
+ lightningcss: 1.29.2
+ tailwindcss: 4.0.12
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+
+ '@types/chai@5.2.3':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+ assertion-error: 2.0.1
+
+ '@types/cookie@0.6.0': {}
+
+ '@types/deep-eql@4.0.2': {}
+
+ '@types/estree@1.0.6': {}
+
+ '@types/estree@1.0.8': {}
+
+ '@types/node@26.6.6':
+ dependencies:
+ undici-types: 8.9.0
+
+ '@vitest/expect@3.2.4':
+ dependencies:
+ '@types/chai': 5.2.3
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ tinyrainbow: 2.0.0
+
+ '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))':
+ dependencies:
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.19
+ optionalDependencies:
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+
+ '@vitest/pretty-format@3.2.4':
+ dependencies:
+ tinyrainbow: 2.0.0
+
+ '@vitest/runner@3.2.4':
+ dependencies:
+ '@vitest/utils': 3.2.4
+ pathe: 2.0.3
+ strip-literal: 3.1.0
+
+ '@vitest/snapshot@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ magic-string: 0.30.19
+ pathe: 2.0.3
+
+ '@vitest/spy@3.2.4':
+ dependencies:
+ tinyspy: 4.0.4
+
+ '@vitest/utils@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.2.1
+ tinyrainbow: 2.0.0
+
+ acorn-typescript@1.4.13(acorn@8.14.0):
+ dependencies:
+ acorn: 8.14.0
+
+ acorn@8.14.0: {}
+
+ aria-query@5.3.2: {}
+
+ assertion-error@2.0.1: {}
+
+ axobject-query@4.1.0: {}
+
+ cac@6.7.14: {}
+
+ chai@5.3.3:
+ dependencies:
+ assertion-error: 2.0.1
+ check-error: 2.1.1
+ deep-eql: 5.0.2
+ loupe: 3.2.1
+ pathval: 2.0.1
+
+ check-error@2.1.1: {}
+
+ chokidar@4.0.3:
+ dependencies:
+ readdirp: 4.1.2
+
+ clsx@2.1.1: {}
+
+ cookie@0.6.0: {}
+
+ debug@4.4.0:
+ dependencies:
+ ms: 2.1.3
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ deep-eql@5.0.2: {}
+
+ deepmerge@4.3.1: {}
+
+ detect-libc@2.0.3: {}
+
+ devalue@5.3.2: {}
+
+ devicon@2.18.0: {}
+
+ enhanced-resolve@5.18.1:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.2.1
+
+ es-module-lexer@1.7.0: {}
+
+ esbuild@0.25.11:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.11
+ '@esbuild/android-arm': 0.25.11
+ '@esbuild/android-arm64': 0.25.11
+ '@esbuild/android-x64': 0.25.11
+ '@esbuild/darwin-arm64': 0.25.11
+ '@esbuild/darwin-x64': 0.25.11
+ '@esbuild/freebsd-arm64': 0.25.11
+ '@esbuild/freebsd-x64': 0.25.11
+ '@esbuild/linux-arm': 0.25.11
+ '@esbuild/linux-arm64': 0.25.11
+ '@esbuild/linux-ia32': 0.25.11
+ '@esbuild/linux-loong64': 0.25.11
+ '@esbuild/linux-mips64el': 0.25.11
+ '@esbuild/linux-ppc64': 0.25.11
+ '@esbuild/linux-riscv64': 0.25.11
+ '@esbuild/linux-s390x': 0.25.11
+ '@esbuild/linux-x64': 0.25.11
+ '@esbuild/netbsd-arm64': 0.25.11
+ '@esbuild/netbsd-x64': 0.25.11
+ '@esbuild/openbsd-arm64': 0.25.11
+ '@esbuild/openbsd-x64': 0.25.11
+ '@esbuild/openharmony-arm64': 0.25.11
+ '@esbuild/sunos-x64': 0.25.11
+ '@esbuild/win32-arm64': 0.25.11
+ '@esbuild/win32-ia32': 0.25.11
+ '@esbuild/win32-x64': 0.25.11
+
+ esm-env@1.2.2: {}
+
+ esrap@1.4.5:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ expect-type@1.2.2: {}
+
+ fdir@6.4.3(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ fsevents@2.3.3:
+ optional: true
+
+ graceful-fs@4.2.11: {}
+
+ import-meta-resolve@4.2.0: {}
+
+ is-reference@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.6
+
+ jiti@2.4.2: {}
+
+ js-tokens@9.0.1: {}
+
+ kleur@4.1.5: {}
+
+ lightningcss-darwin-arm64@1.29.2:
+ optional: true
+
+ lightningcss-darwin-x64@1.29.2:
+ optional: true
+
+ lightningcss-freebsd-x64@1.29.2:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.29.2:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.29.2:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.29.2:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.29.2:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.29.2:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.29.2:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.29.2:
+ optional: true
+
+ lightningcss@1.29.2:
+ dependencies:
+ detect-libc: 2.0.3
+ optionalDependencies:
+ lightningcss-darwin-arm64: 1.29.2
+ lightningcss-darwin-x64: 1.29.2
+ lightningcss-freebsd-x64: 1.29.2
+ lightningcss-linux-arm-gnueabihf: 1.29.2
+ lightningcss-linux-arm64-gnu: 1.29.2
+ lightningcss-linux-arm64-musl: 1.29.2
+ lightningcss-linux-x64-gnu: 1.29.2
+ lightningcss-linux-x64-musl: 1.29.2
+ lightningcss-win32-arm64-msvc: 1.29.2
+ lightningcss-win32-x64-msvc: 1.29.2
+
+ locate-character@3.0.0: {}
+
+ loupe@3.2.1: {}
+
+ magic-string@0.30.17:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ magic-string@0.30.19:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ mri@1.2.0: {}
+
+ mrmime@2.0.1: {}
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.11: {}
+
+ pathe@2.0.3: {}
+
+ pathval@2.0.1: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.3: {}
+
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ readdirp@4.1.2: {}
+
+ rollup@4.52.5:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.52.5
+ '@rollup/rollup-android-arm64': 4.52.5
+ '@rollup/rollup-darwin-arm64': 4.52.5
+ '@rollup/rollup-darwin-x64': 4.52.5
+ '@rollup/rollup-freebsd-arm64': 4.52.5
+ '@rollup/rollup-freebsd-x64': 4.52.5
+ '@rollup/rollup-linux-arm-gnueabihf': 4.52.5
+ '@rollup/rollup-linux-arm-musleabihf': 4.52.5
+ '@rollup/rollup-linux-arm64-gnu': 4.52.5
+ '@rollup/rollup-linux-arm64-musl': 4.52.5
+ '@rollup/rollup-linux-loong64-gnu': 4.52.5
+ '@rollup/rollup-linux-ppc64-gnu': 4.52.5
+ '@rollup/rollup-linux-riscv64-gnu': 4.52.5
+ '@rollup/rollup-linux-riscv64-musl': 4.52.5
+ '@rollup/rollup-linux-s390x-gnu': 4.52.5
+ '@rollup/rollup-linux-x64-gnu': 4.52.5
+ '@rollup/rollup-linux-x64-musl': 4.52.5
+ '@rollup/rollup-openharmony-arm64': 4.52.5
+ '@rollup/rollup-win32-arm64-msvc': 4.52.5
+ '@rollup/rollup-win32-ia32-msvc': 4.52.5
+ '@rollup/rollup-win32-x64-gnu': 4.52.5
+ '@rollup/rollup-win32-x64-msvc': 4.52.5
+ fsevents: 2.3.3
+
+ sade@1.8.1:
+ dependencies:
+ mri: 1.2.0
+
+ set-cookie-parser@2.7.1: {}
+
+ siginfo@2.0.0: {}
+
+ sirv@3.0.2:
+ dependencies:
+ '@polka/url': 1.0.0-next.29
+ mrmime: 2.0.1
+ totalist: 3.0.1
+
+ source-map-js@1.2.1: {}
+
+ stackback@0.0.2: {}
+
+ std-env@3.10.0: {}
+
+ strip-literal@3.1.0:
+ dependencies:
+ js-tokens: 9.0.1
+
+ svelte-check@4.1.4(picomatch@4.0.3)(svelte@5.20.5)(typescript@5.8.2):
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ chokidar: 4.0.3
+ fdir: 6.4.3(picomatch@4.0.3)
+ picocolors: 1.1.1
+ sade: 1.8.1
+ svelte: 5.20.5
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - picomatch
+
+ svelte@5.20.5:
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@jridgewell/sourcemap-codec': 1.5.0
+ '@types/estree': 1.0.6
+ acorn: 8.14.0
+ acorn-typescript: 1.4.13(acorn@8.14.0)
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ clsx: 2.1.1
+ esm-env: 1.2.2
+ esrap: 1.4.5
+ is-reference: 3.0.3
+ locate-character: 3.0.0
+ magic-string: 0.30.17
+ zimmerframe: 1.1.2
+
+ tailwindcss@4.0.12: {}
+
+ tapable@2.2.1: {}
+
+ tinybench@2.9.0: {}
+
+ tinyexec@0.3.2: {}
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tinypool@1.1.1: {}
+
+ tinyrainbow@2.0.0: {}
+
+ tinyspy@4.0.4: {}
+
+ totalist@3.0.1: {}
+
+ typescript@5.8.2: {}
+
+ undici-types@8.9.0: {}
+
+ vite-node@3.2.4(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2):
+ dependencies:
+ esbuild: 0.25.11
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.52.5
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 26.6.6
+ fsevents: 2.3.3
+ jiti: 2.4.2
+ lightningcss: 1.29.2
+
+ vitefu@1.0.6(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)):
+ optionalDependencies:
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+
+ vitest@3.2.4(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2):
+ dependencies:
+ '@types/chai': 5.2.3
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.2.2
+ magic-string: 0.30.19
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 6.4.1(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+ vite-node: 3.2.4(@types/node@26.6.6)(jiti@2.4.2)(lightningcss@1.29.2)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 26.6.6
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
+ zimmerframe@1.1.2: {}
diff --git a/site/pnpm-workspace.yaml b/site/pnpm-workspace.yaml
new file mode 100644
index 000000000..5ed0b5af0
--- /dev/null
+++ b/site/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+allowBuilds:
+ esbuild: true
diff --git a/site/src/app.css b/site/src/app.css
new file mode 100644
index 000000000..7e220c561
--- /dev/null
+++ b/site/src/app.css
@@ -0,0 +1,144 @@
+@import "tailwindcss";
+@custom-variant dark (&:where(.dark, .dark *));
+
+@theme {
+ --font-sans: "Geist", "Geist Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
+
+ --color-dark-bg: #09090b;
+ --color-surface-900: #11131a;
+ --color-surface-850: #181b24;
+ --color-surface-800: #222634;
+
+ /* Devicon Brand Tokens */
+ --color-devicon-primary: #10b981;
+ --color-devicon-primary-dark: #059669;
+ --color-devicon-primary-light: #34d399;
+ --color-devicon-accent: #3ecf8e;
+ --color-devicon-shield: #60be86;
+ --color-devicon-shield-light: #65d693;
+ --color-devicon-shield-dark: #558d6c;
+ --color-devicon-shield-mid: #5aa579;
+
+ --color-devicon-emerald: #10b981;
+ --color-devicon-emerald-light: #34d399;
+ --color-devicon-emerald-dark: #059669;
+
+ --color-border-subtle: rgba(255, 255, 255, 0.07);
+ --color-border-hover: rgba(255, 255, 255, 0.15);
+
+ --primaryColor: #10b981;
+ --primaryColorDark: #059669;
+ --primaryColorLight: #34d399;
+}
+
+html {
+ font-family: var(--font-sans);
+ scroll-behavior: smooth;
+}
+
+/* Prevent full-page repaint/layout lag across 600+ icon cards during theme toggle */
+html.disable-transitions,
+html.disable-transitions *:not(.theme-toggle-icon, .theme-toggle-icon *) {
+ transition: none !important;
+}
+
+.base-container {
+ @apply mx-auto w-full px-4 sm:px-6 lg:px-8 max-w-7xl;
+}
+
+.checkerboard {
+ background-image: repeating-conic-gradient(#d1d5db 0% 25%, #f3f4f6 0% 50%);
+ background-size: 16px 16px;
+ background-color: #f3f4f6;
+}
+
+:global(.dark) .checkerboard,
+.dark .checkerboard {
+ background-image: repeating-conic-gradient(#222634 0% 25%, #11131a 0% 50%);
+ background-size: 16px 16px;
+ background-color: #11131a;
+}
+
+.no-scrollbar,
+.code-snippet {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+
+.no-scrollbar::-webkit-scrollbar,
+.code-snippet::-webkit-scrollbar {
+ display: none;
+}
+
+@keyframes marquee {
+ 0% {
+ transform: translateX(0%);
+ }
+ 100% {
+ transform: translateX(-50%);
+ }
+}
+
+.animate-marquee {
+ display: flex;
+ width: max-content;
+ animation: marquee 40s linear infinite;
+}
+
+.animate-marquee:hover {
+ animation-play-state: paused;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *,
+ ::before,
+ ::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+
+ .animate-marquee {
+ animation: none !important;
+ }
+}
+
+/* Devicon Developer Grid Background */
+.bg-devicon-grid {
+ background-image:
+ linear-gradient(to right, rgba(16, 185, 129, 0.05) 1px, transparent 1px),
+ linear-gradient(to bottom, rgba(16, 185, 129, 0.05) 1px, transparent 1px);
+ background-size: 36px 36px;
+}
+
+:global(.dark) .bg-devicon-grid,
+.dark .bg-devicon-grid {
+ background-image:
+ linear-gradient(to right, rgba(16, 185, 129, 0.04) 1px, transparent 1px),
+ linear-gradient(to bottom, rgba(16, 185, 129, 0.04) 1px, transparent 1px);
+ background-size: 36px 36px;
+}
+
+/* Devicon Engineering Margin Stripes */
+.bg-devicon-stripes {
+ background-image: repeating-linear-gradient(
+ -45deg,
+ rgba(16, 185, 129, 0.05) 0,
+ rgba(16, 185, 129, 0.05) 1px,
+ transparent 0,
+ transparent 10px
+ );
+}
+
+:global(.dark) .bg-devicon-stripes,
+.dark .bg-devicon-stripes {
+ background-image: repeating-linear-gradient(
+ -45deg,
+ rgba(16, 185, 129, 0.07) 0,
+ rgba(16, 185, 129, 0.07) 1px,
+ transparent 0,
+ transparent 10px
+ );
+}
diff --git a/site/src/app.d.ts b/site/src/app.d.ts
new file mode 100644
index 000000000..c0c081684
--- /dev/null
+++ b/site/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {}
diff --git a/site/src/app.html b/site/src/app.html
new file mode 100644
index 000000000..4bd62609c
--- /dev/null
+++ b/site/src/app.html
@@ -0,0 +1,27 @@
+
+
+
+
+
DEVICON | All programming languages and development tools related icons font
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+
%sveltekit.body%
+
+
diff --git a/site/src/components/darkMode/DarkModeToggle.svelte b/site/src/components/darkMode/DarkModeToggle.svelte
new file mode 100644
index 000000000..6d0f04d9c
--- /dev/null
+++ b/site/src/components/darkMode/DarkModeToggle.svelte
@@ -0,0 +1,41 @@
+
+
+
+ {#if $isDarkMode}
+
+
+
+ {:else}
+
+
+
+ {/if}
+
diff --git a/site/src/components/filters/CategoryChips.svelte b/site/src/components/filters/CategoryChips.svelte
new file mode 100644
index 000000000..cfdb7c4a2
--- /dev/null
+++ b/site/src/components/filters/CategoryChips.svelte
@@ -0,0 +1,45 @@
+
+
+
+ {#each categories as category}
+ {@const isActive = $selectedCategory === category.id}
+ {@const count = $categoryCounts?.[category.id] ?? 0}
+ setSelectedCategory(category.id)}
+ class="cursor-pointer inline-flex items-center gap-1.5 whitespace-nowrap rounded-lg px-2.5 py-1.5 text-xs font-medium transition-all {isActive
+ ? 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border border-emerald-500/30 font-semibold shadow-2xs'
+ : 'border border-transparent text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-white/[0.04]'}"
+ >
+ {category.label}
+ {#if count > 0}
+
+ {count}
+
+ {/if}
+
+ {/each}
+
diff --git a/site/src/components/filters/FiltersBar.svelte b/site/src/components/filters/FiltersBar.svelte
new file mode 100644
index 000000000..2facd5795
--- /dev/null
+++ b/site/src/components/filters/FiltersBar.svelte
@@ -0,0 +1,63 @@
+
+
+
diff --git a/site/src/components/filters/SearchBar.svelte b/site/src/components/filters/SearchBar.svelte
new file mode 100644
index 000000000..27d244575
--- /dev/null
+++ b/site/src/components/filters/SearchBar.svelte
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {#if $searchTerm}
+
setSearchTerm("")}
+ class="absolute inset-y-0 right-0 flex items-center pr-2 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200 cursor-pointer"
+ aria-label="Clear search"
+ >
+
+
+
+
+
+ {/if}
+
diff --git a/site/src/components/filters/SortDropdown.svelte b/site/src/components/filters/SortDropdown.svelte
new file mode 100644
index 000000000..bfde8959b
--- /dev/null
+++ b/site/src/components/filters/SortDropdown.svelte
@@ -0,0 +1,42 @@
+
+
+
+
+ {#each sortOptions as opt}
+ {opt.label}
+ {/each}
+
+
+
+
+
+
diff --git a/site/src/components/filters/TagsDropdown.svelte b/site/src/components/filters/TagsDropdown.svelte
new file mode 100644
index 000000000..978ecf239
--- /dev/null
+++ b/site/src/components/filters/TagsDropdown.svelte
@@ -0,0 +1,99 @@
+
+
+
+
(isDropdownOpen = !isDropdownOpen)}
+ class="flex w-full cursor-pointer items-center justify-between rounded-lg border border-slate-200 bg-white py-1.5 px-2.5 text-xs font-medium text-slate-700 outline-none transition hover:border-slate-300 dark:border-white/[0.08] dark:bg-[#11131a] dark:text-slate-200 dark:hover:border-white/[0.15]"
+ aria-expanded={isDropdownOpen}
+ aria-haspopup="true"
+ >
+ {label}
+
+
+
+
+
+
+ {#if isDropdownOpen}
+
+
(isDropdownOpen = false)}
+ aria-label="Close dropdown"
+ >
+
+
+
+
+ {#each $availableTags as tag}
+ {@const isChecked = $selectedTags.includes(tag)}
+ toggleTag(tag)}
+ >
+
+ {tag}
+
+ {/each}
+
+
+
+
+ setSelectedTags([])}
+ >
+ Reset tags
+
+
+
+ {/if}
+
diff --git a/site/src/components/filters/VersionDropdown.svelte b/site/src/components/filters/VersionDropdown.svelte
new file mode 100644
index 000000000..0178d7615
--- /dev/null
+++ b/site/src/components/filters/VersionDropdown.svelte
@@ -0,0 +1,45 @@
+
+
+
+
+ {#each versionOptions as opt}
+ {opt.label}
+ {/each}
+
+
+
+
+
+
diff --git a/site/src/components/footer/Footer.svelte b/site/src/components/footer/Footer.svelte
new file mode 100644
index 000000000..8249237f6
--- /dev/null
+++ b/site/src/components/footer/Footer.svelte
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Devicon
+
+
+ v{$latestVersion}
+
+
+
+
+ An open-source collection of developer icons for programming languages, frameworks, cloud services, and software tools.
+
+
+
+
+
+
+
+
+
+
+
+
+ Contributors
+
+
+ Devicon is built and maintained by hundreds of open-source contributors across the globe.
+
+
+
+
+
+ Contributor graph via contrib.rocks .
+
+
+
+
+
+
+
+ All product names, logos, and brands are property of their respective owners. All company,
+ product and service names used in this website are for identification purposes only. Usage of
+ these names, logos, and brands does not imply endorsement of Devicon or its members. All
+ icons/SVGs in this project are not monetized in any way. It is up to the user to use the logo
+ properly according to the company/group's brand policy.
+
+
+
+
+ Originally created by Konpa (MIT License). Webfont compiled with Icomoon .
+
+
+ Released under the MIT License .
+
+
+
+
+
diff --git a/site/src/components/header/Header.svelte b/site/src/components/header/Header.svelte
new file mode 100644
index 000000000..3b5cec1d6
--- /dev/null
+++ b/site/src/components/header/Header.svelte
@@ -0,0 +1,34 @@
+
+
+
+
+ Devicon
+
+ v{$latestVersion}
+
+
+
+ Icons about programming languages, software development, and graphic design
+ tools.
+
+
+
+
+
+
+
+
diff --git a/site/src/components/header/HeaderSnippet.svelte b/site/src/components/header/HeaderSnippet.svelte
new file mode 100644
index 000000000..487c7c810
--- /dev/null
+++ b/site/src/components/header/HeaderSnippet.svelte
@@ -0,0 +1,37 @@
+
+
+
+
For CSS usage, paste the code in the <head> of your HTML
+
+
{snippet}
+
+ copyToClipboard(snippet)}
+ aria-label="Copy link tag"
+ >
+
+
+
+
+
+
+
diff --git a/site/src/components/header/HeaderStats.svelte b/site/src/components/header/HeaderStats.svelte
new file mode 100644
index 000000000..03bfcb84d
--- /dev/null
+++ b/site/src/components/header/HeaderStats.svelte
@@ -0,0 +1,19 @@
+
+
+
+
Total Icons
+
+ {$icons.length}
+
+
+
+
Total Versions
+
+ {$totalVersions}
+
+
+
\ No newline at end of file
diff --git a/site/src/components/hero/Hero.svelte b/site/src/components/hero/Hero.svelte
new file mode 100644
index 000000000..e0a759907
--- /dev/null
+++ b/site/src/components/hero/Hero.svelte
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+ Icons for developers , developers, developers!
+
+
+
+
+ {$icons.length > 0 ? $icons.length.toLocaleString() : "660"} technology icons and {$totalVersions > 0 ? $totalVersions.toLocaleString() : "2,100"} SVG variants for modern software engineering. Free and open source under MIT.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ โK
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+
diff --git a/site/src/components/hero/HeroMosaic.svelte b/site/src/components/hero/HeroMosaic.svelte
new file mode 100644
index 000000000..cc812f70a
--- /dev/null
+++ b/site/src/components/hero/HeroMosaic.svelte
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+ Technology Mosaic
+
+
+ v{$latestVersion}
+ โข
+ {$icons.length > 0 ? $icons.length.toLocaleString() : "660"} ICONS
+
+
+
+
+
+ {#each mosaicItems as item (item.name)}
+ {#if item.isCenter}
+
+
handleTechClick("devicon")}
+ class="group relative flex aspect-square flex-col items-center justify-center rounded-xl border-2 border-emerald-500/50 bg-gradient-to-br from-emerald-500/20 via-emerald-500/10 to-transparent p-2 shadow-md shadow-emerald-500/10 transition-transform duration-150 hover:scale-105 hover:border-emerald-500 hover:shadow-emerald-500/25 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500 sm:rounded-2xl sm:p-2.5"
+ title="Devicon - Click to view all icons"
+ aria-label="Devicon library centerpiece"
+ >
+
+
+
+
+
+
+
+
+
+
+ DEVICON
+
+
+ {:else}
+ {@const iconObj = getIcon(item.name, item.version)}
+ {@const isDark = isDarkLogo(iconObj)}
+ {@const isWhite = isWhiteLogo(iconObj)}
+
handleTechClick(item.name)}
+ class="{item.hiddenMobile ? 'hidden sm:flex' : 'flex'} group relative aspect-square flex-col items-center justify-center rounded-xl border border-slate-200/80 bg-white/70 p-2 shadow-2xs transition-all duration-150 hover:-translate-y-0.5 hover:border-emerald-500/40 hover:bg-emerald-500/5 hover:shadow-xs dark:border-white/[0.06] dark:bg-white/[0.025] dark:hover:border-emerald-500/40 dark:hover:bg-emerald-500/10 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/50 sm:rounded-2xl sm:p-2.5"
+ title={`Filter icons for ${item.label}`}
+ aria-label={`Search for ${item.label} icons`}
+ >
+ handleImageError(e, iconObj, item.version)}
+ class="size-6 object-contain transition-transform duration-150 group-hover:scale-110 sm:size-7 md:size-8 {isDark ? 'dark:invert' : ''} {isWhite ? 'invert dark:filter-none' : ''}"
+ />
+
+ {item.label}
+
+
+ {/if}
+ {/each}
+
+
diff --git a/site/src/components/hero/IconMarquee.svelte b/site/src/components/hero/IconMarquee.svelte
new file mode 100644
index 000000000..fc16650e0
--- /dev/null
+++ b/site/src/components/hero/IconMarquee.svelte
@@ -0,0 +1,62 @@
+
+
+
+
+ {#each [...marqueeIcons, ...marqueeIcons] as item, idx (`${item.name}-${idx}`)}
+ handleTechClick(item.name)}
+ class="flex items-center gap-2 px-2.5 py-1.5 opacity-60 hover:opacity-100 transition-opacity cursor-pointer select-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 dark:focus-visible:ring-white/20 rounded-md"
+ title={`Filter icons for ${item.label}`}
+ aria-label={`Search for ${item.label} icons`}
+ >
+
+
+ {item.label}
+
+
+ {/each}
+
+
diff --git a/site/src/components/iconGrid/IconCard.svelte b/site/src/components/iconGrid/IconCard.svelte
new file mode 100644
index 000000000..8bd93bdc6
--- /dev/null
+++ b/site/src/components/iconGrid/IconCard.svelte
@@ -0,0 +1,86 @@
+
+
+
openIconModal(icon)}
+ aria-label={`View ${icon.name} details and code integration`}
+>
+ {#if isSelected}
+
+
+
+
+
+ {/if}
+
+
+
+
handleImageError(e, defaultSvgVersion)}
+ class="size-10 sm:size-11 object-contain transition-transform duration-150 group-hover:scale-105 {isDark
+ ? 'dark:invert'
+ : ''} {isWhite ? 'invert dark:filter-none' : ''}"
+ />
+
+
+
+
+
+ {icon.name}
+
+
+
+ {totalCount}
+ {totalCount === 1 ? "variant" : "variants"}
+
+
+
diff --git a/site/src/components/iconGrid/IconGrid.svelte b/site/src/components/iconGrid/IconGrid.svelte
new file mode 100644
index 000000000..e7ede58a0
--- /dev/null
+++ b/site/src/components/iconGrid/IconGrid.svelte
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ {#if $isLoading}
+ Loading developer icons...
+ {:else}
+ Showing {icons.length} icons
+ {/if}
+
+
+
+ {#if $isLoading}
+
+
+ {#each Array(24) as _, i (i)}
+
+ {/each}
+
+ {:else if icons.length === 0}
+
+
+
+
+
+ No icons found matching your filters
+
+
+ Try adjusting your search query, selecting a different category, or resetting all filters.
+
+
+
+
+
+
+
+ Reset all filters
+
+
+ {:else}
+
+
+ {#each icons as icon (icon.name)}
+
+ {/each}
+
+ {/if}
+
diff --git a/site/src/components/integrations/IntegrationsSection.svelte b/site/src/components/integrations/IntegrationsSection.svelte
new file mode 100644
index 000000000..183f1f617
--- /dev/null
+++ b/site/src/components/integrations/IntegrationsSection.svelte
@@ -0,0 +1,191 @@
+
+
+
diff --git a/site/src/components/modal/IconModal.svelte b/site/src/components/modal/IconModal.svelte
new file mode 100644
index 000000000..79f597356
--- /dev/null
+++ b/site/src/components/modal/IconModal.svelte
@@ -0,0 +1,735 @@
+
+
+
+ {#if $selectedIcon}
+
+
+
+
+
+
+
+
+
+
+
+ {#if rawSvgText && !isLoadingSvg}
+
+
+ {@html rawSvgText}
+
+ {:else if currentSvgUrl}
+
handleImageError(e, selectedVersion)}
+ class="size-full object-contain transition-transform {isDark && bgMode === 'dark' ? 'invert' : ''} {isWhite && bgMode === 'light' ? 'invert' : ''}"
+ />
+ {/if}
+
+
+
+ {#if copiedFeedback}
+
+
+
+
+
{copiedFeedback}
+
+ {/if}
+
+
+
+
+
+
+
+
+ Surface:
+ setBgMode("dark")}
+ class="size-5 rounded bg-[#11131a] border transition cursor-pointer {bgMode === 'dark' ? 'border-emerald-500 ring-1 ring-emerald-500/50' : 'border-white/20'}"
+ title="Dark surface"
+ aria-label="Dark Surface"
+ >
+ setBgMode("light")}
+ class="size-5 rounded bg-white border transition cursor-pointer {bgMode === 'light' ? 'border-emerald-500 ring-1 ring-emerald-500/50' : 'border-slate-300'}"
+ title="Light surface"
+ aria-label="Light Surface"
+ >
+ setBgMode("checkerboard")}
+ class="size-5 rounded checkerboard border transition cursor-pointer {bgMode === 'checkerboard' ? 'border-emerald-500 ring-1 ring-emerald-500/50' : 'border-slate-300 dark:border-white/20'}"
+ title="Checkerboard surface"
+ aria-label="Checkerboard Surface"
+ >
+ setBgMode("transparent")}
+ class="flex size-5 items-center justify-center rounded border border-dashed transition cursor-pointer text-[10px] {bgMode === 'transparent' ? 'border-emerald-500 text-emerald-500 ring-1 ring-emerald-500/50' : 'border-slate-300 text-slate-400 dark:border-white/20'}"
+ title="Transparent surface"
+ aria-label="Transparent Surface"
+ >
+ โ
+
+
+
+
+
+
+ Colored
+
+
+
+
+
+
Scale:
+
+ {#each previewSizes as size}
+ (previewSize = size)}
+ class="rounded px-1.5 py-0.5 font-mono text-[10px] font-semibold transition cursor-pointer {previewSize === size
+ ? 'bg-slate-900 text-white dark:bg-white/15 dark:text-white'
+ : 'text-slate-500 hover:bg-slate-200 dark:text-slate-400 dark:hover:bg-white/5'}"
+ aria-label={`Preview at ${size}px`}
+ >
+ {size}px
+
+ {/each}
+
+
+
+
+
+
+
+
+ Variants ({availableVariants.length})
+
+
+ โ
+ โ cycle
+
+
+
+
+ {#each availableVariants as version}
+ {@const isSelected = selectedVersion === version}
+
(selectedVersion = version)}
+ class="flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs transition-colors cursor-pointer {isSelected
+ ? 'border-emerald-500/60 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 font-medium'
+ : 'border-slate-200 bg-white hover:border-slate-300 dark:border-white/[0.06] dark:bg-[#11131a] dark:text-slate-300 dark:hover:border-white/15'}"
+ aria-label={`Select ${version} version`}
+ >
+ handleImageError(e, version)}
+ class="size-4 object-contain {isDark ? 'dark:invert' : ''} {isWhite ? 'invert dark:filter-none' : ''}"
+ />
+ {version}
+
+ {/each}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Download SVG
+
+
+
+
+
+
+
+ Copy SVG
+
+
+
+
+
+
+
+
+ Copy Class
+
+
+
+
+
+
+
+
+
+
+ Copy JSX Tag
+
+
+
+
+
+
+
+ Copy Name
+
+
+
+
+
+
+
+
+
+ (activeTab = "react")}
+ class="flex-1 rounded-md py-1.5 text-center text-xs font-medium transition-colors cursor-pointer {activeTab === 'react'
+ ? 'bg-white text-slate-900 shadow-xs dark:bg-white/10 dark:text-white'
+ : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white'}"
+ >
+ React
+
+ (activeTab = "html")}
+ class="flex-1 rounded-md py-1.5 text-center text-xs font-medium transition-colors cursor-pointer {activeTab === 'html'
+ ? 'bg-white text-slate-900 shadow-xs dark:bg-white/10 dark:text-white'
+ : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white'}"
+ >
+ HTML / Webfont
+
+ (activeTab = "svg")}
+ class="flex-1 rounded-md py-1.5 text-center text-xs font-medium transition-colors cursor-pointer {activeTab === 'svg'
+ ? 'bg-white text-slate-900 shadow-xs dark:bg-white/10 dark:text-white'
+ : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white'}"
+ >
+ Pure SVG
+
+
+
+
+ {#if activeTab === "react"}
+
+
+
+
+
Install:
+
+ {#each (["npm", "pnpm", "yarn", "bun"] as const) as pkg}
+ (activePkg = pkg)}
+ class="rounded px-1.5 py-0.5 font-mono text-[10px] font-semibold transition cursor-pointer {activePkg === pkg
+ ? 'bg-slate-900 text-white dark:bg-white/15 dark:text-white'
+ : 'text-slate-500 hover:bg-slate-200 dark:text-slate-400 dark:hover:bg-white/5'}"
+ >
+ {pkg}
+
+ {/each}
+
+
+
+
+
+
+
+
`}
+ language="tsx"
+ code={reactSnippet}
+ />
+
+
+
+
+ Official package: react-devicons
+
+
+ Docs
+ โ
+
+
+
+ {:else if activeTab === "html"}
+
+
+
+
+
+
+ Webfont Live Preview
+
+ {#if fontVersions.length > 1}
+
+ Version:
+ {#each fontVersions as fVer}
+ (selectedFontVersion = fVer)}
+ class="rounded px-2 py-0.5 font-mono text-[10px] font-semibold transition cursor-pointer {selectedFontVersion === fVer
+ ? 'bg-slate-900 text-white dark:bg-white/15 dark:text-white'
+ : 'text-slate-500 hover:bg-slate-200 dark:text-slate-400 dark:hover:bg-white/5'}"
+ >
+ {fVer}
+
+ {/each}
+
+ {/if}
+
+
+
+
+
+
+
+
+ Rendered with CSS class devicon-{$selectedIcon.name}-{effectiveFontVersion}{coloredSuffix}.
+
+
+
+
+
+
+
+
+
+
+ Inherits currentColor to adapt seamlessly to light and dark backgrounds.
+
+
+
+
+
+
+ {#if isDark}
+
+ Note: This icon has dark brand coloring and may have low contrast on dark backgrounds. Use the theme-adaptive snippet above for dark modes.
+
+ {/if}
+
+
+ {:else}
+
+
+ {#if isLoadingSvg}
+
+ Loading SVG markup...
+
+ {:else if svgFetchError}
+
+ Failed to load raw SVG markup. You can download the SVG file directly using the button on the left.
+
+ {:else}
+
+
+
+ {/if}
+
+ {/if}
+
+
+ {/if}
+
diff --git a/site/src/components/modal/IconModalHeader.svelte b/site/src/components/modal/IconModalHeader.svelte
new file mode 100644
index 000000000..794d3a1c3
--- /dev/null
+++ b/site/src/components/modal/IconModalHeader.svelte
@@ -0,0 +1,34 @@
+
+
+
+
+
+ {title}
+
+ {#if tags && tags.length > 0}
+
+ {#each tags.slice(0, 3) as tag}
+
+ #{tag}
+
+ {/each}
+
+ {/if}
+
+
+
+
+
+
+
+
+
diff --git a/site/src/components/modal/IconSelector/FontVersionSelector.svelte b/site/src/components/modal/IconSelector/FontVersionSelector.svelte
new file mode 100644
index 000000000..f935be49f
--- /dev/null
+++ b/site/src/components/modal/IconSelector/FontVersionSelector.svelte
@@ -0,0 +1,100 @@
+
+
+
+
{title}
+
+
+ Colored
+
+
+
+{#if versions.length > 0}
+
+ {#each versions as version}
+ selectVersion(version)}
+ aria-label={`Select ${version} version`}
+ >
+
+
+ {/each}
+
+
+
+
{codeSnippet}
+
+ copyToClipboard(codeSnippet)}
+ aria-label="Copy code snippet"
+ >
+
+
+
+
+
+
+{:else}
+
No font versions available
+{/if}
diff --git a/site/src/components/modal/IconSelector/SVGVersionSelector.svelte b/site/src/components/modal/IconSelector/SVGVersionSelector.svelte
new file mode 100644
index 000000000..4a546006d
--- /dev/null
+++ b/site/src/components/modal/IconSelector/SVGVersionSelector.svelte
@@ -0,0 +1,306 @@
+
+
+
{title}
+
+{#if versions.length > 0}
+
+ {#each versions as version}
+
selectVersion(version)}
+ aria-label={`Select ${version} version`}
+ >
+ handleImageError(e, version)}
+ alt={`${selectedIcon.name} (${version})`}
+ class="h-full"
+ />
+
+ {/each}
+
+
+
+
+ (activeTab = "svg")}
+ aria-label="Pure SVG format"
+ >
+ Pure SVG
+
+ (activeTab = "img")}
+ aria-label="<img> Element format"
+ >
+ <img> Element
+
+
+
+
+ {#if activeTab === "svg"}
+
+
+
+
+ Download SVG
+
+
+
+ copyToClipboard(formattedSvgText)}
+ disabled={isLoadingSvg || !formattedSvgText}
+ aria-label="Copy Pure SVG"
+ >
+
+
+
+ Copy Pure SVG
+
+
+ {:else}
+
+ copyToClipboard(imgSnippet)}
+ aria-label="Copy Tag"
+ >
+
+
+
+ Copy <img> Tag
+
+
+ {/if}
+
+
+
+
+ {#if activeTab === "svg"}
+ {#if isLoadingSvg}
+
Loading SVG content...
+ {:else if svgFetchError}
+
Failed to load SVG markup.
+ {:else}
+
{formattedSvgText}
+ {/if}
+ {:else}
+
{imgSnippet}
+ {/if}
+
+{:else}
+
No SVG versions available
+{/if}
diff --git a/site/src/components/modal/Modal.svelte b/site/src/components/modal/Modal.svelte
new file mode 100644
index 000000000..114c26cd0
--- /dev/null
+++ b/site/src/components/modal/Modal.svelte
@@ -0,0 +1,31 @@
+
+
+{#if isOpen}
+
+{/if}
diff --git a/site/src/components/navigation/Navbar.svelte b/site/src/components/navigation/Navbar.svelte
new file mode 100644
index 000000000..23af41b89
--- /dev/null
+++ b/site/src/components/navigation/Navbar.svelte
@@ -0,0 +1,195 @@
+
+
+
diff --git a/site/src/components/navigation/ThemeToggle.svelte b/site/src/components/navigation/ThemeToggle.svelte
new file mode 100644
index 000000000..0fad58132
--- /dev/null
+++ b/site/src/components/navigation/ThemeToggle.svelte
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/site/src/components/widgets/code/SyntaxCodeBlock.svelte b/site/src/components/widgets/code/SyntaxCodeBlock.svelte
new file mode 100644
index 000000000..cd9847f80
--- /dev/null
+++ b/site/src/components/widgets/code/SyntaxCodeBlock.svelte
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+ {#if title}
+ {title}
+ {/if}
+ {#if language}
+
+ {language}
+
+ {/if}
+
+
+
+ {#if copied}
+
+
+
+ Copied!
+ {:else}
+
+
+
+
+ Copy
+ {/if}
+
+
+
+
+
+
{@html highlightedHtml}
+
+
diff --git a/site/src/components/widgets/contact/ContactLinks.svelte b/site/src/components/widgets/contact/ContactLinks.svelte
new file mode 100644
index 000000000..4aeba74d1
--- /dev/null
+++ b/site/src/components/widgets/contact/ContactLinks.svelte
@@ -0,0 +1,42 @@
+
diff --git a/site/src/components/widgets/tooltip/Tooltip.svelte b/site/src/components/widgets/tooltip/Tooltip.svelte
new file mode 100644
index 000000000..bb764fee0
--- /dev/null
+++ b/site/src/components/widgets/tooltip/Tooltip.svelte
@@ -0,0 +1,51 @@
+
+
+
(show = true)}
+ on:mouseleave={() => (show = false)}
+ on:click={handleClick}
+>
+
+
+ {#if isVisible}
+
+ {tooltipText}
+
+ {/if}
+
+
+
diff --git a/site/src/lib/common/copyToClipboard.ts b/site/src/lib/common/copyToClipboard.ts
new file mode 100644
index 000000000..2c44184a2
--- /dev/null
+++ b/site/src/lib/common/copyToClipboard.ts
@@ -0,0 +1,2 @@
+export const copyToClipboard = async (text: string) =>
+ navigator.clipboard?.writeText(text)
diff --git a/site/src/lib/common/navigation.ts b/site/src/lib/common/navigation.ts
new file mode 100644
index 000000000..dca85c744
--- /dev/null
+++ b/site/src/lib/common/navigation.ts
@@ -0,0 +1,16 @@
+export function scrollToSection(id: string, e?: Event): void {
+ if (e) {
+ e.preventDefault()
+ }
+
+ if (typeof document !== "undefined") {
+ const el = document.getElementById(id)
+ if (el) {
+ el.scrollIntoView({ behavior: "smooth", block: "start" })
+ }
+ }
+
+ if (typeof window !== "undefined" && window.location.hash) {
+ window.history.replaceState(null, "", window.location.pathname + window.location.search)
+ }
+}
diff --git a/site/src/lib/index.ts b/site/src/lib/index.ts
new file mode 100644
index 000000000..856f2b6c3
--- /dev/null
+++ b/site/src/lib/index.ts
@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.
diff --git a/site/src/lib/stores/iconStore.ts b/site/src/lib/stores/iconStore.ts
new file mode 100644
index 000000000..a2328f66d
--- /dev/null
+++ b/site/src/lib/stores/iconStore.ts
@@ -0,0 +1,549 @@
+import { writable, derived, get, type Writable, type Readable } from "svelte/store"
+import { base } from "$app/paths"
+import {
+ CURRENT_VERSION,
+ type IIcon,
+ type IconVersions,
+ type SortOption,
+ type CategoryOption,
+} from "$lib/types/types"
+
+export const icons: Writable
= writable([])
+export const availableTags: Writable = writable([])
+export const searchTerm: Writable = writable("")
+export const selectedTags: Writable = writable([])
+export const selectedCategory: Writable = writable("all")
+export const selectedVersionFilter: Writable = writable("all")
+export const isDarkMode: Writable = writable(true)
+export const selectedIcon: Writable = writable(null)
+export const isModalOpen: Writable = writable(false)
+export const isLoading: Writable = writable(false)
+export const error: Writable = writable(null)
+export const latestVersion: Writable = writable(CURRENT_VERSION)
+export const sortOption: Writable = writable("name-asc")
+
+export function setSortOption(option: SortOption): void {
+ sortOption.set(option)
+}
+
+export function setSelectedCategory(category: CategoryOption): void {
+ selectedCategory.set(category)
+}
+
+export function setSelectedVersionFilter(version: string): void {
+ selectedVersionFilter.set(version)
+}
+
+const CANONICAL_ORDER = [
+ "original",
+ "original-wordmark",
+ "plain",
+ "plain-wordmark",
+ "line",
+ "line-wordmark",
+]
+
+export function getIconAllVariants(icon: IIcon): string[] {
+ if (!icon) return []
+ const variants = new Set([
+ ...(icon.versions?.svg || []),
+ ...(icon.versions?.font || []),
+ ])
+
+ for (const aliasObj of icon.aliases || []) {
+ if (aliasObj?.alias) {
+ variants.add(aliasObj.alias)
+ }
+ if (aliasObj?.base === "original" && aliasObj?.alias === "plain") {
+ if (variants.has("original-wordmark")) {
+ variants.add("plain-wordmark")
+ }
+ }
+ if (aliasObj?.base === "plain" && aliasObj?.alias === "original") {
+ if (variants.has("plain-wordmark")) {
+ variants.add("original-wordmark")
+ }
+ }
+ }
+
+ // Second pass in case wordmark was added during alias processing
+ for (const aliasObj of icon.aliases || []) {
+ if (aliasObj?.base === "original" && aliasObj?.alias === "plain") {
+ if (variants.has("original-wordmark")) {
+ variants.add("plain-wordmark")
+ }
+ }
+ if (aliasObj?.base === "plain" && aliasObj?.alias === "original") {
+ if (variants.has("plain-wordmark")) {
+ variants.add("original-wordmark")
+ }
+ }
+ }
+
+ return Array.from(variants).sort((a, b) => {
+ const idxA = CANONICAL_ORDER.indexOf(a)
+ const idxB = CANONICAL_ORDER.indexOf(b)
+ if (idxA !== -1 && idxB !== -1) return idxA - idxB
+ if (idxA !== -1) return -1
+ if (idxB !== -1) return 1
+ return a.localeCompare(b)
+ })
+}
+
+export function resolveSvgVersion(icon: IIcon, variant: string): string {
+ if (!icon) return "original"
+
+ if (icon.versions?.svg?.includes(variant as IconVersions)) {
+ return variant
+ }
+
+ for (const alias of icon.aliases || []) {
+ if (
+ alias.alias === variant &&
+ icon.versions?.svg?.includes(alias.base as IconVersions)
+ ) {
+ return alias.base
+ }
+ }
+
+ if (variant.endsWith("-wordmark")) {
+ const root = variant.replace(/-wordmark$/, "")
+ for (const alias of icon.aliases || []) {
+ if (alias.alias === root) {
+ const baseWordmark = `${alias.base}-wordmark` as IconVersions
+ if (icon.versions?.svg?.includes(baseWordmark)) {
+ return baseWordmark
+ }
+ }
+ }
+ }
+
+ return icon.versions?.svg?.[0] || "original"
+}
+
+export function hexToHsl(hex: string): { h: number; s: number; l: number } {
+ if (!hex || typeof hex !== "string") {
+ return { h: 0, s: 0, l: 0 }
+ }
+
+ let cleaned = hex.trim().replace(/^#/, "")
+
+ // Support 3, 4, 6, or 8 digit hex codes
+ if (cleaned.length === 3 || cleaned.length === 4) {
+ cleaned = cleaned
+ .slice(0, 3)
+ .split("")
+ .map((c) => c + c)
+ .join("")
+ } else if (cleaned.length >= 6) {
+ cleaned = cleaned.slice(0, 6)
+ } else {
+ return { h: 0, s: 0, l: 0 }
+ }
+
+ const num = parseInt(cleaned, 16)
+ if (Number.isNaN(num)) {
+ return { h: 0, s: 0, l: 0 }
+ }
+
+ const r = ((num >> 16) & 255) / 255
+ const g = ((num >> 8) & 255) / 255
+ const b = (num & 255) / 255
+
+ const max = Math.max(r, g, b)
+ const min = Math.min(r, g, b)
+ let h = 0
+ let s = 0
+ const l = (max + min) / 2
+
+ if (max !== min) {
+ const d = max - min
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
+
+ switch (max) {
+ case r:
+ h = (g - b) / d + (g < b ? 6 : 0)
+ break
+ case g:
+ h = (b - r) / d + 2
+ break
+ case b:
+ h = (r - g) / d + 4
+ break
+ }
+ h /= 6
+ }
+
+ return { h, s, l }
+}
+
+export function isDarkLogo(icon: IIcon): boolean {
+ if (!icon) return false
+ if (icon.theme === "dark") return true
+ if (icon.theme === "light" || icon.theme === "color") return false
+ if (!icon.color) return false
+ const { s, l } = hexToHsl(icon.color)
+ return s < 0.20 && l < 0.35
+}
+
+export function isWhiteLogo(icon: IIcon): boolean {
+ if (!icon) return false
+ if (icon.theme === "light") return true
+ if (icon.theme === "dark" || icon.theme === "color") return false
+ if (!icon.color) return false
+ const { s, l } = hexToHsl(icon.color)
+ return s < 0.20 && l > 0.85
+}
+
+export function getIconSvgCandidates(
+ icon: IIcon,
+ version: IconVersions | string,
+ ver?: string,
+): string[] {
+ const resolved = resolveSvgVersion(icon, version)
+ const v = ver || get(latestVersion) || CURRENT_VERSION
+ const localUrl = `${base}/icons/${icon.name}/${icon.name}-${resolved}.svg`
+ const npmUrl = `https://cdn.jsdelivr.net/npm/devicon@${v}/icons/${icon.name}/${icon.name}-${resolved}.svg`
+ const ghUrl = `https://cdn.jsdelivr.net/gh/devicons/devicon@master/icons/${icon.name}/${icon.name}-${resolved}.svg`
+
+ if (import.meta.env.DEV) {
+ return [localUrl, npmUrl, ghUrl]
+ }
+ return [npmUrl, ghUrl, localUrl]
+}
+
+export function getIconSvgUrl(
+ icon: IIcon,
+ version: IconVersions | string,
+ ver?: string,
+): string {
+ const candidates = getIconSvgCandidates(icon, version, ver)
+ return candidates[0]
+}
+
+export function getIconFallbackSvgUrl(
+ icon: IIcon,
+ version: IconVersions | string,
+ currentSrc?: string,
+): string {
+ const candidates = getIconSvgCandidates(icon, version)
+ if (!currentSrc) return candidates[1] || candidates[0]
+ const index = candidates.findIndex(
+ (c) => currentSrc === c || currentSrc.endsWith(c),
+ )
+ if (index >= 0 && index < candidates.length - 1) {
+ return candidates[index + 1]
+ }
+ return candidates[candidates.length - 1]
+}
+
+async function fetchLatestVersion(): Promise {
+ try {
+ const npmResponse = await fetch("https://registry.npmjs.org/devicon/latest")
+ if (npmResponse.ok) {
+ const npmData = await npmResponse.json()
+ if (npmData?.version) {
+ return npmData.version
+ }
+ }
+ } catch {
+ // try github fallback
+ }
+
+ try {
+ const response = await fetch(
+ "https://api.github.com/repos/devicons/devicon/releases/latest",
+ )
+ if (response.ok) {
+ const data = await response.json()
+ if (data?.tag_name) {
+ return data.tag_name.replace(/^v/, "")
+ }
+ }
+ } catch {
+ // ignore
+ }
+
+ return CURRENT_VERSION
+}
+
+export async function fetchIconsData(): Promise {
+ isLoading.set(true)
+ error.set(null)
+
+ try {
+ const version = await fetchLatestVersion()
+ latestVersion.set(version)
+
+ let response: Response | null = null
+
+ // 1. Try local devicon.json first (enables local dev without CDN latency)
+ try {
+ const localResponse = await fetch(`${base}/devicon.json`)
+ if (localResponse.ok) {
+ response = localResponse
+ }
+ } catch {
+ // fallback to CDN
+ }
+
+ // 2. Fall back to jsdelivr npm CDN
+ if (!response) {
+ try {
+ const cdnResponse = await fetch(
+ `https://cdn.jsdelivr.net/npm/devicon@${version}/devicon.json`,
+ )
+ if (cdnResponse.ok) {
+ response = cdnResponse
+ }
+ } catch {
+ // fallback to github master
+ }
+ }
+
+ // 3. Fall back to GitHub master
+ if (!response) {
+ response = await fetch(
+ "https://raw.githubusercontent.com/devicons/devicon/master/devicon.json",
+ )
+ }
+
+ if (!response.ok) {
+ throw new Error(`Failed to fetch icons: ${response.statusText}`)
+ }
+
+ const iconsData: IIcon[] = await response.json()
+
+ const availableTagsSet = new Set()
+ iconsData.forEach((icon) => {
+ if (icon.tags && Array.isArray(icon.tags)) {
+ for (const tag of icon.tags) {
+ availableTagsSet.add(tag)
+ }
+ }
+ })
+
+ const sortedTags = Array.from(availableTagsSet).sort()
+
+ icons.set(iconsData)
+ availableTags.set(sortedTags)
+
+ initializeDarkMode()
+ } catch (err) {
+ const message = err instanceof Error ? err.message : String(err)
+ console.error("Error fetching icons:", err)
+ error.set(message)
+ icons.set([])
+ availableTags.set([])
+ } finally {
+ isLoading.set(false)
+ }
+}
+
+function initializeDarkMode(): void {
+ if (typeof window !== "undefined") {
+ const storedDarkMode = localStorage.getItem("darkMode")
+ const isDark = storedDarkMode !== "false"
+
+ isDarkMode.set(isDark)
+
+ if (isDark) {
+ document.documentElement.classList.add("dark")
+ } else {
+ document.documentElement.classList.remove("dark")
+ }
+ }
+}
+
+export function initializeStore(
+ initialIcons: IIcon[],
+ initialTags: string[],
+): void {
+ icons.set(initialIcons)
+ availableTags.set(initialTags)
+ initializeDarkMode()
+}
+
+const CATEGORY_TAG_MAP: Record = {
+ all: [],
+ language: ["language", "programming"],
+ framework: ["framework"],
+ database: ["database", "nosql", "sql"],
+ library: ["library"],
+ cloud: ["cloud", "devops", "hosting", "server", "cloud-computing"],
+ tool: [
+ "tool",
+ "editor",
+ "ide",
+ "automation",
+ "build",
+ "vcs",
+ "version-control",
+ "design",
+ ],
+}
+
+export const categoryCounts: Readable> = derived(
+ [icons],
+ ([$icons]) => {
+ const counts: Record = {
+ all: $icons.length,
+ language: 0,
+ framework: 0,
+ database: 0,
+ library: 0,
+ cloud: 0,
+ tool: 0,
+ }
+
+ for (const icon of $icons) {
+ const lowerTags = (icon.tags || []).map((t) => t.toLowerCase())
+
+ for (const cat of [
+ "language",
+ "framework",
+ "database",
+ "library",
+ "cloud",
+ "tool",
+ ] as const) {
+ const mapped = CATEGORY_TAG_MAP[cat]
+ const matches = lowerTags.some(
+ (tag) => tag === cat || mapped?.includes(tag),
+ )
+ if (matches) {
+ counts[cat]++
+ }
+ }
+ }
+
+ return counts
+ },
+)
+
+export const filteredIcons: Readable = derived(
+ [icons, searchTerm, selectedTags, selectedCategory, selectedVersionFilter, sortOption],
+ ([
+ $icons,
+ $searchTerm,
+ $selectedTags,
+ $selectedCategory,
+ $selectedVersionFilter,
+ $sortOption,
+ ]) => {
+ const query = $searchTerm.trim().toLowerCase()
+
+ const filtered = $icons.filter((icon) => {
+ const matchesSearch =
+ query === "" ||
+ icon.name.toLowerCase().includes(query) ||
+ Boolean(icon.altnames?.some((alt) => alt.toLowerCase().includes(query)))
+
+ const matchesTags =
+ $selectedTags.length === 0 ||
+ Boolean(icon.tags && $selectedTags.every((tag) => icon.tags.includes(tag)))
+
+ const matchesCategory =
+ $selectedCategory === "all" ||
+ Boolean(
+ icon.tags?.some((tag) => {
+ const lowerTag = tag.toLowerCase()
+ if (lowerTag === $selectedCategory) return true
+ const mapped = CATEGORY_TAG_MAP[$selectedCategory]
+ return mapped?.includes(lowerTag)
+ }),
+ )
+
+ const allVariants = getIconAllVariants(icon)
+ const matchesVersion =
+ $selectedVersionFilter === "all" ||
+ Boolean(
+ allVariants.some((v) =>
+ $selectedVersionFilter === "wordmark"
+ ? v.includes("wordmark")
+ : v.startsWith($selectedVersionFilter),
+ ),
+ )
+
+ return matchesSearch && matchesTags && matchesCategory && matchesVersion
+ })
+
+ if ($sortOption === "name-asc") {
+ return [...filtered].sort((a, b) => a.name.localeCompare(b.name))
+ }
+ if ($sortOption === "name-desc") {
+ return [...filtered].sort((a, b) => b.name.localeCompare(a.name))
+ }
+ if ($sortOption === "most-versions") {
+ return [...filtered].sort((a, b) => {
+ return getIconAllVariants(b).length - getIconAllVariants(a).length
+ })
+ }
+ if ($sortOption === "newest") {
+ return [...filtered].reverse()
+ }
+
+ return filtered
+ },
+)
+
+export const totalVersions: Readable = derived([icons], ([$icons]) =>
+ $icons.reduce(
+ (acc, icon) => acc + getIconAllVariants(icon).length,
+ 0,
+ ),
+)
+
+export function setSearchTerm(term: string): void {
+ searchTerm.set(term)
+}
+
+export function setSelectedTags(tags: string[]): void {
+ selectedTags.set(tags)
+}
+
+export function clearFilters(): void {
+ searchTerm.set("")
+ selectedTags.set([])
+ selectedCategory.set("all")
+ selectedVersionFilter.set("all")
+}
+
+export function toggleDarkMode(): void {
+ if (typeof window !== "undefined") {
+ document.documentElement.classList.add("disable-transitions")
+ }
+
+ isDarkMode.update((current) => {
+ const newValue = !current
+
+ if (typeof window !== "undefined") {
+ localStorage.setItem("darkMode", newValue.toString())
+
+ if (newValue) {
+ document.documentElement.classList.add("dark")
+ } else {
+ document.documentElement.classList.remove("dark")
+ }
+
+ // Flush computed style reflow so theme changes instantly without intermediate transitions
+ window.getComputedStyle(document.documentElement).opacity
+
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove("disable-transitions")
+ })
+ }
+
+ return newValue
+ })
+}
+
+export function openIconModal(icon: IIcon): void {
+ selectedIcon.set(icon)
+ isModalOpen.set(true)
+}
+
+export function closeIconModal(): void {
+ selectedIcon.set(null)
+ isModalOpen.set(false)
+}
diff --git a/site/src/lib/types/types.ts b/site/src/lib/types/types.ts
new file mode 100644
index 000000000..423b4ff2b
--- /dev/null
+++ b/site/src/lib/types/types.ts
@@ -0,0 +1,40 @@
+export const CURRENT_VERSION = "2.18.0"
+
+export type SortOption = "name-asc" | "name-desc" | "most-versions" | "newest"
+
+export type CategoryOption =
+ | "all"
+ | "language"
+ | "framework"
+ | "database"
+ | "library"
+ | "cloud"
+ | "tool"
+
+export type IntegrationTab = "react" | "html" | "svg"
+
+export type IconVersions =
+ | "plain"
+ | "line"
+ | "original"
+ | "plain-wordmark"
+ | "line-wordmark"
+ | "original-wordmark"
+
+export type IconType = "svg" | "font"
+
+export interface IIcon {
+ name: string
+ altnames: string[]
+ tags: string[]
+ versions: {
+ svg: IconVersions[]
+ font: IconVersions[]
+ }
+ color: string
+ aliases: {
+ base: IconVersions
+ alias: IconVersions
+ }[]
+ theme?: "dark" | "light" | "color"
+}
diff --git a/site/src/routes/+layout.svelte b/site/src/routes/+layout.svelte
new file mode 100644
index 000000000..1ee51f86b
--- /dev/null
+++ b/site/src/routes/+layout.svelte
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {@render children()}
+
+
+
diff --git a/site/src/routes/+layout.ts b/site/src/routes/+layout.ts
new file mode 100644
index 000000000..440bfd494
--- /dev/null
+++ b/site/src/routes/+layout.ts
@@ -0,0 +1,2 @@
+export const prerender = true
+export const ssr = true
diff --git a/site/src/routes/+page.svelte b/site/src/routes/+page.svelte
new file mode 100644
index 000000000..b08bfb285
--- /dev/null
+++ b/site/src/routes/+page.svelte
@@ -0,0 +1,103 @@
+
+
+
+ DEVICON | All programming languages and development tools related icons font
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if $isModalOpen}
+
+ {/if}
+
+
+ {#if showBackToTop}
+
+
+
+
+
+ {/if}
+
diff --git a/site/static/CNAME b/site/static/CNAME
new file mode 100644
index 000000000..08253f49a
--- /dev/null
+++ b/site/static/CNAME
@@ -0,0 +1 @@
+devicon.dev
diff --git a/docs/logos/android-chrome-144x144.png b/site/static/android-chrome-144x144.png
similarity index 100%
rename from docs/logos/android-chrome-144x144.png
rename to site/static/android-chrome-144x144.png
diff --git a/docs/logos/android-chrome-192x192.png b/site/static/android-chrome-192x192.png
similarity index 100%
rename from docs/logos/android-chrome-192x192.png
rename to site/static/android-chrome-192x192.png
diff --git a/docs/logos/android-chrome-36x36.png b/site/static/android-chrome-36x36.png
similarity index 100%
rename from docs/logos/android-chrome-36x36.png
rename to site/static/android-chrome-36x36.png
diff --git a/docs/logos/android-chrome-48x48.png b/site/static/android-chrome-48x48.png
similarity index 100%
rename from docs/logos/android-chrome-48x48.png
rename to site/static/android-chrome-48x48.png
diff --git a/docs/logos/android-chrome-72x72.png b/site/static/android-chrome-72x72.png
similarity index 100%
rename from docs/logos/android-chrome-72x72.png
rename to site/static/android-chrome-72x72.png
diff --git a/docs/logos/android-chrome-96x96.png b/site/static/android-chrome-96x96.png
similarity index 100%
rename from docs/logos/android-chrome-96x96.png
rename to site/static/android-chrome-96x96.png
diff --git a/docs/logos/apple-touch-icon-114x114.png b/site/static/apple-touch-icon-114x114.png
similarity index 100%
rename from docs/logos/apple-touch-icon-114x114.png
rename to site/static/apple-touch-icon-114x114.png
diff --git a/docs/logos/apple-touch-icon-120x120.png b/site/static/apple-touch-icon-120x120.png
similarity index 100%
rename from docs/logos/apple-touch-icon-120x120.png
rename to site/static/apple-touch-icon-120x120.png
diff --git a/docs/logos/apple-touch-icon-144x144.png b/site/static/apple-touch-icon-144x144.png
similarity index 100%
rename from docs/logos/apple-touch-icon-144x144.png
rename to site/static/apple-touch-icon-144x144.png
diff --git a/docs/logos/apple-touch-icon-152x152.png b/site/static/apple-touch-icon-152x152.png
similarity index 100%
rename from docs/logos/apple-touch-icon-152x152.png
rename to site/static/apple-touch-icon-152x152.png
diff --git a/docs/logos/apple-touch-icon-180x180.png b/site/static/apple-touch-icon-180x180.png
similarity index 100%
rename from docs/logos/apple-touch-icon-180x180.png
rename to site/static/apple-touch-icon-180x180.png
diff --git a/docs/logos/apple-touch-icon-57x57.png b/site/static/apple-touch-icon-57x57.png
similarity index 100%
rename from docs/logos/apple-touch-icon-57x57.png
rename to site/static/apple-touch-icon-57x57.png
diff --git a/docs/logos/apple-touch-icon-60x60.png b/site/static/apple-touch-icon-60x60.png
similarity index 100%
rename from docs/logos/apple-touch-icon-60x60.png
rename to site/static/apple-touch-icon-60x60.png
diff --git a/docs/logos/apple-touch-icon-72x72.png b/site/static/apple-touch-icon-72x72.png
similarity index 100%
rename from docs/logos/apple-touch-icon-72x72.png
rename to site/static/apple-touch-icon-72x72.png
diff --git a/docs/logos/apple-touch-icon-76x76.png b/site/static/apple-touch-icon-76x76.png
similarity index 100%
rename from docs/logos/apple-touch-icon-76x76.png
rename to site/static/apple-touch-icon-76x76.png
diff --git a/docs/logos/apple-touch-icon-precomposed.png b/site/static/apple-touch-icon-precomposed.png
similarity index 100%
rename from docs/logos/apple-touch-icon-precomposed.png
rename to site/static/apple-touch-icon-precomposed.png
diff --git a/docs/logos/apple-touch-icon.png b/site/static/apple-touch-icon.png
similarity index 100%
rename from docs/logos/apple-touch-icon.png
rename to site/static/apple-touch-icon.png
diff --git a/docs/logos/favicon-16x16.png b/site/static/favicon-16x16.png
similarity index 100%
rename from docs/logos/favicon-16x16.png
rename to site/static/favicon-16x16.png
diff --git a/docs/logos/favicon-32x32.png b/site/static/favicon-32x32.png
similarity index 100%
rename from docs/logos/favicon-32x32.png
rename to site/static/favicon-32x32.png
diff --git a/docs/logos/favicon-96x96.png b/site/static/favicon-96x96.png
similarity index 100%
rename from docs/logos/favicon-96x96.png
rename to site/static/favicon-96x96.png
diff --git a/docs/logos/favicon.ico b/site/static/favicon.ico
similarity index 100%
rename from docs/logos/favicon.ico
rename to site/static/favicon.ico
diff --git a/docs/logos/mstile-144x144.png b/site/static/mstile-144x144.png
similarity index 100%
rename from docs/logos/mstile-144x144.png
rename to site/static/mstile-144x144.png
diff --git a/docs/logos/mstile-150x150.png b/site/static/mstile-150x150.png
similarity index 100%
rename from docs/logos/mstile-150x150.png
rename to site/static/mstile-150x150.png
diff --git a/docs/logos/mstile-310x150.png b/site/static/mstile-310x150.png
similarity index 100%
rename from docs/logos/mstile-310x150.png
rename to site/static/mstile-310x150.png
diff --git a/docs/logos/mstile-310x310.png b/site/static/mstile-310x310.png
similarity index 100%
rename from docs/logos/mstile-310x310.png
rename to site/static/mstile-310x310.png
diff --git a/docs/logos/mstile-70x70.png b/site/static/mstile-70x70.png
similarity index 100%
rename from docs/logos/mstile-70x70.png
rename to site/static/mstile-70x70.png
diff --git a/docs/logos/safari-pinned-tab.svg b/site/static/safari-pinned-tab.svg
similarity index 100%
rename from docs/logos/safari-pinned-tab.svg
rename to site/static/safari-pinned-tab.svg
diff --git a/site/svelte.config.js b/site/svelte.config.js
new file mode 100644
index 000000000..a3dc7e889
--- /dev/null
+++ b/site/svelte.config.js
@@ -0,0 +1,27 @@
+import adapter from "@sveltejs/adapter-static"
+import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://svelte.dev/docs/kit/integrations
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+
+ kit: {
+ // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
+ // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+ // See https://svelte.dev/docs/kit/adapters for more information about adapters.
+ adapter: adapter({
+ pages: "build",
+ assets: "build",
+ fallback: "404.html",
+ precompress: false,
+ strict: true,
+ }),
+ paths: {
+ base: process.env.BASE_PATH ?? "",
+ },
+ },
+}
+
+export default config
diff --git a/site/tsconfig.json b/site/tsconfig.json
new file mode 100644
index 000000000..f4d0a0e16
--- /dev/null
+++ b/site/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
+ //
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+ // from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/site/vite.config.ts b/site/vite.config.ts
new file mode 100644
index 000000000..f9a523f11
--- /dev/null
+++ b/site/vite.config.ts
@@ -0,0 +1,80 @@
+import { sveltekit } from "@sveltejs/kit/vite"
+import { defineConfig, type Plugin, type Connect } from "vite"
+import tailwindcss from "@tailwindcss/vite"
+import fs from "node:fs"
+import path from "node:path"
+import { fileURLToPath } from "node:url"
+
+function deviconLocalPlugin(): Plugin {
+ const jsonPath = fileURLToPath(new URL("../devicon.json", import.meta.url))
+ const iconsDir = fileURLToPath(new URL("../icons", import.meta.url))
+
+ const middleware: Connect.NextHandleFunction = (req, res, next) => {
+ if (!req.url) {
+ return next()
+ }
+ const cleanUrl = req.url.split("?")[0]
+
+ if (cleanUrl === "/devicon.json" || cleanUrl.endsWith("/devicon.json")) {
+ if (fs.existsSync(jsonPath)) {
+ res.setHeader("Content-Type", "application/json")
+ res.setHeader("Cache-Control", "no-cache")
+ fs.createReadStream(jsonPath).on("error", next).pipe(res)
+ return
+ }
+ }
+
+ const iconsPrefix = "/icons/"
+ const iconsIndex = cleanUrl.indexOf(iconsPrefix)
+ if (iconsIndex !== -1) {
+ const relative = decodeURIComponent(cleanUrl.slice(iconsIndex + iconsPrefix.length))
+ const filePath = path.resolve(iconsDir, relative)
+ if (
+ filePath.startsWith(iconsDir) &&
+ fs.existsSync(filePath) &&
+ fs.statSync(filePath).isFile()
+ ) {
+ let content = fs.readFileSync(filePath, "utf8")
+ if (!content.includes("xmlns=")) {
+ content = content.replace(",
+})