Merge branch 'main' into homepage-2025
@@ -12,3 +12,15 @@ pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
*.scss
|
||||
|
||||
# Assets
|
||||
*.jpg
|
||||
*.png
|
||||
*.webp
|
||||
*.avif
|
||||
|
||||
# Media
|
||||
*.mp3
|
||||
*.wav
|
||||
*.mp4
|
||||
*.mpv
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@appwrite.io/console": "^0.6.4",
|
||||
"@appwrite.io/pink": "~0.26.0",
|
||||
"@appwrite.io/pink-icons": "~0.26.0",
|
||||
"@appwrite.io/repo": "github:appwrite/appwrite#1.6.x",
|
||||
"@appwrite.io/repo": "github:appwrite/appwrite#main",
|
||||
"@eslint/compat": "^1.2.7",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@fingerprintjs/fingerprintjs": "^4.5.1",
|
||||
|
||||
10
pnpm-lock.yaml
generated
@@ -28,8 +28,8 @@ importers:
|
||||
specifier: ~0.26.0
|
||||
version: 0.26.0
|
||||
'@appwrite.io/repo':
|
||||
specifier: github:appwrite/appwrite#1.6.x
|
||||
version: https://codeload.github.com/appwrite/appwrite/tar.gz/8b23d4bab1057eea089fa301b756495b7d207bfd
|
||||
specifier: github:appwrite/appwrite#main
|
||||
version: https://codeload.github.com/appwrite/appwrite/tar.gz/00e3397b5632ccfee7306b14e5ad636f256fb192
|
||||
'@eslint/compat':
|
||||
specifier: ^1.2.7
|
||||
version: 1.2.7(eslint@9.22.0(jiti@2.4.2))
|
||||
@@ -284,8 +284,8 @@ packages:
|
||||
'@appwrite.io/pink@0.26.0':
|
||||
resolution: {integrity: sha512-iPeGE56pauzxuIXt15ZswjKCErwp3QdF3XOlJZfyYY7J2nirra85JNTL+3lWuFIf8yYWL7NbvCjhf8ig79TgwA==}
|
||||
|
||||
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/8b23d4bab1057eea089fa301b756495b7d207bfd':
|
||||
resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/8b23d4bab1057eea089fa301b756495b7d207bfd}
|
||||
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/00e3397b5632ccfee7306b14e5ad636f256fb192':
|
||||
resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/00e3397b5632ccfee7306b14e5ad636f256fb192}
|
||||
version: 0.0.0
|
||||
|
||||
'@babel/runtime@7.26.10':
|
||||
@@ -4063,7 +4063,7 @@ snapshots:
|
||||
normalize.css: 8.0.1
|
||||
the-new-css-reset: 1.11.3
|
||||
|
||||
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/8b23d4bab1057eea089fa301b756495b7d207bfd': {}
|
||||
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/00e3397b5632ccfee7306b14e5ad636f256fb192': {}
|
||||
|
||||
'@babel/runtime@7.26.10':
|
||||
dependencies:
|
||||
|
||||
13
src/app.css
@@ -89,8 +89,11 @@
|
||||
--animate-scale-out: scale-out 200ms ease-out forwards;
|
||||
--animate-caret-blink: caret-blink 1s ease-in-out infinite;
|
||||
--animate-enter:
|
||||
fade-in 0.25s ease-out both, blur 0.25s ease-out both, up 0.25s ease-in-out both;
|
||||
--animate-scroll-deprecate: scroll-deprecate 60s linear infinite;
|
||||
fade-in 0.75s ease-in-out both, blur 0.75s ease-in-out both, up 0.75s ease-in-out both;
|
||||
--animate-scroll: scroll 60s linear infinite;
|
||||
--animate-scroll-x: scroll-x var(--speed, 30s) linear infinite var(--direction, forwards);
|
||||
--animate-scroll-y: scroll-y 60s linear infinite forwards;
|
||||
|
||||
--animate-fade-in: fade-in 0.5s ease-in-out both;
|
||||
--animate-fade-out: fade-out 0.5s ease-in-out both;
|
||||
--animate-scroll-x: scroll-x var(--speed, 30s) linear infinite var(--direction, forwards);
|
||||
@@ -284,10 +287,10 @@
|
||||
/* Font sizes */
|
||||
--text-x-micro: 0.625rem;
|
||||
--text-x-micro--line-height: 0.875rem;
|
||||
--text-x-micro--letter-spacing: var(--tracking-tighter);
|
||||
--text-x-micro--letter-spacing: var(--tracking-loose);
|
||||
--text-micro: 0.75rem;
|
||||
--text-micro--line-height: 1rem;
|
||||
--text-micro--letter-spacing: var(--tracking-tighter);
|
||||
--text-micro--letter-spacing: var(--tracking-loose);
|
||||
--text-caption: 0.875rem;
|
||||
--text-caption--line-height: 1.375rem;
|
||||
--text-caption--letter-spacing: var(--tracking-tight);
|
||||
@@ -332,9 +335,9 @@
|
||||
}
|
||||
|
||||
@utility container {
|
||||
max-width: 75rem;
|
||||
margin-inline: auto;
|
||||
padding-inline: 1.25rem;
|
||||
max-width: 75rem;
|
||||
}
|
||||
|
||||
@utility border-gradient {
|
||||
|
||||
@@ -122,20 +122,12 @@ const securityheaders: Handle = async ({ event, resolve }) => {
|
||||
return response;
|
||||
};
|
||||
|
||||
const bannerRewriter: Handle = async ({ event, resolve }) => {
|
||||
const response = await resolve(event, {
|
||||
transformPageChunk: ({ html }) => html.replace('%aw_banner_key%', BANNER_KEY)
|
||||
});
|
||||
return response;
|
||||
};
|
||||
|
||||
const fontPreloader: Handle = async ({ event, resolve }) => {
|
||||
return resolve(event, {
|
||||
preload: ({ type }) => {
|
||||
return type === 'font' || type === 'js' || type === 'css';
|
||||
}
|
||||
});
|
||||
};
|
||||
// const bannerRewriter: Handle = async ({ event, resolve }) => {
|
||||
// const response = await resolve(event, {
|
||||
// transformPageChunk: ({ html }) => html.replace('%aw_banner_key%', BANNER_KEY)
|
||||
// });
|
||||
// return response;
|
||||
// };
|
||||
|
||||
const initSession: Handle = async ({ event, resolve }) => {
|
||||
const session = await createInitSessionClient(event.cookies);
|
||||
@@ -199,10 +191,4 @@ const initSession: Handle = async ({ event, resolve }) => {
|
||||
return response;
|
||||
};
|
||||
|
||||
export const handle = sequence(
|
||||
redirecter,
|
||||
fontPreloader,
|
||||
bannerRewriter,
|
||||
securityheaders,
|
||||
initSession
|
||||
);
|
||||
export const handle = sequence(redirecter, securityheaders, initSession);
|
||||
|
||||
1
src/icons/optimized/remix.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M4.500 4.430 L 4.500 5.864 7.558 5.875 C 10.958 5.886,10.756 5.873,11.250 6.116 C 11.552 6.264,11.697 6.387,11.864 6.637 C 12.064 6.937,12.138 7.207,12.141 7.650 C 12.144 8.103,12.095 8.350,11.942 8.643 C 11.800 8.914,11.631 9.070,11.317 9.219 C 10.830 9.450,10.919 9.444,7.542 9.458 L 4.500 9.470 4.500 10.917 L 4.500 12.364 7.425 12.375 C 10.607 12.388,10.509 12.382,10.893 12.579 C 11.334 12.804,11.577 13.269,11.664 14.050 C 11.726 14.604,11.771 15.911,11.748 16.458 L 11.724 17.000 13.434 17.000 L 15.144 17.000 15.123 16.025 C 15.075 13.762,14.977 13.042,14.624 12.350 C 14.520 12.148,14.418 12.014,14.202 11.800 C 13.868 11.468,13.649 11.331,13.213 11.181 C 12.873 11.064,12.813 11.033,12.926 11.033 C 13.030 11.033,13.525 10.872,13.717 10.775 C 14.682 10.288,15.313 9.298,15.470 8.023 C 15.521 7.616,15.487 6.775,15.404 6.363 C 15.064 4.683,14.059 3.644,12.344 3.201 C 11.653 3.022,11.706 3.025,7.975 3.010 L 4.500 2.996 4.500 4.430 M4.500 15.916 L 4.500 17.000 6.652 17.000 L 8.804 17.000 8.794 16.158 L 8.783 15.317 8.692 15.161 C 8.642 15.076,8.544 14.971,8.475 14.928 L 8.350 14.850 6.425 14.841 L 4.500 14.831 4.500 15.916 " fill="#2D2D31" stroke="none" fill-rule="evenodd"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -42,15 +42,16 @@ $web-icon-play: "\ea29";
|
||||
$web-icon-plus: "\ea2a";
|
||||
$web-icon-product-hunt: "\ea2b";
|
||||
$web-icon-refine: "\ea2c";
|
||||
$web-icon-rest: "\ea2d";
|
||||
$web-icon-search: "\ea2e";
|
||||
$web-icon-sendgrid: "\ea2f";
|
||||
$web-icon-star: "\ea30";
|
||||
$web-icon-system: "\ea31";
|
||||
$web-icon-textmagic: "\ea32";
|
||||
$web-icon-tiktok: "\ea33";
|
||||
$web-icon-twitter: "\ea34";
|
||||
$web-icon-vue: "\ea35";
|
||||
$web-icon-x: "\ea36";
|
||||
$web-icon-ycombinator: "\ea37";
|
||||
$web-icon-youtube: "\ea38";
|
||||
$web-icon-remix: "\ea2d";
|
||||
$web-icon-rest: "\ea2e";
|
||||
$web-icon-search: "\ea2f";
|
||||
$web-icon-sendgrid: "\ea30";
|
||||
$web-icon-star: "\ea31";
|
||||
$web-icon-system: "\ea32";
|
||||
$web-icon-textmagic: "\ea33";
|
||||
$web-icon-tiktok: "\ea34";
|
||||
$web-icon-twitter: "\ea35";
|
||||
$web-icon-vue: "\ea36";
|
||||
$web-icon-x: "\ea37";
|
||||
$web-icon-ycombinator: "\ea38";
|
||||
$web-icon-youtube: "\ea39";
|
||||
|
||||
@@ -263,76 +263,82 @@
|
||||
"className": "web-icon-refine",
|
||||
"unicode": ""
|
||||
},
|
||||
"rest": {
|
||||
"remix": {
|
||||
"encodedCode": "\\ea2d",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-rest",
|
||||
"className": "web-icon-remix",
|
||||
"unicode": ""
|
||||
},
|
||||
"search": {
|
||||
"rest": {
|
||||
"encodedCode": "\\ea2e",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-search",
|
||||
"className": "web-icon-rest",
|
||||
"unicode": ""
|
||||
},
|
||||
"sendgrid": {
|
||||
"search": {
|
||||
"encodedCode": "\\ea2f",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-sendgrid",
|
||||
"className": "web-icon-search",
|
||||
"unicode": ""
|
||||
},
|
||||
"star": {
|
||||
"sendgrid": {
|
||||
"encodedCode": "\\ea30",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-star",
|
||||
"className": "web-icon-sendgrid",
|
||||
"unicode": ""
|
||||
},
|
||||
"system": {
|
||||
"star": {
|
||||
"encodedCode": "\\ea31",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-system",
|
||||
"className": "web-icon-star",
|
||||
"unicode": ""
|
||||
},
|
||||
"textmagic": {
|
||||
"system": {
|
||||
"encodedCode": "\\ea32",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-textmagic",
|
||||
"className": "web-icon-system",
|
||||
"unicode": ""
|
||||
},
|
||||
"tiktok": {
|
||||
"textmagic": {
|
||||
"encodedCode": "\\ea33",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-tiktok",
|
||||
"className": "web-icon-textmagic",
|
||||
"unicode": ""
|
||||
},
|
||||
"twitter": {
|
||||
"tiktok": {
|
||||
"encodedCode": "\\ea34",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-twitter",
|
||||
"className": "web-icon-tiktok",
|
||||
"unicode": ""
|
||||
},
|
||||
"vue": {
|
||||
"twitter": {
|
||||
"encodedCode": "\\ea35",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-vue",
|
||||
"className": "web-icon-twitter",
|
||||
"unicode": ""
|
||||
},
|
||||
"x": {
|
||||
"vue": {
|
||||
"encodedCode": "\\ea36",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-x",
|
||||
"className": "web-icon-vue",
|
||||
"unicode": ""
|
||||
},
|
||||
"ycombinator": {
|
||||
"x": {
|
||||
"encodedCode": "\\ea37",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-ycombinator",
|
||||
"className": "web-icon-x",
|
||||
"unicode": ""
|
||||
},
|
||||
"youtube": {
|
||||
"ycombinator": {
|
||||
"encodedCode": "\\ea38",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-youtube",
|
||||
"className": "web-icon-ycombinator",
|
||||
"unicode": ""
|
||||
},
|
||||
"youtube": {
|
||||
"encodedCode": "\\ea39",
|
||||
"prefix": "web-icon",
|
||||
"className": "web-icon-youtube",
|
||||
"unicode": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,39 +152,42 @@
|
||||
.web-icon-refine:before {
|
||||
content: '\ea2c';
|
||||
}
|
||||
.web-icon-rest:before {
|
||||
.web-icon-remix:before {
|
||||
content: '\ea2d';
|
||||
}
|
||||
.web-icon-search:before {
|
||||
.web-icon-rest:before {
|
||||
content: '\ea2e';
|
||||
}
|
||||
.web-icon-sendgrid:before {
|
||||
.web-icon-search:before {
|
||||
content: '\ea2f';
|
||||
}
|
||||
.web-icon-star:before {
|
||||
.web-icon-sendgrid:before {
|
||||
content: '\ea30';
|
||||
}
|
||||
.web-icon-system:before {
|
||||
.web-icon-star:before {
|
||||
content: '\ea31';
|
||||
}
|
||||
.web-icon-textmagic:before {
|
||||
.web-icon-system:before {
|
||||
content: '\ea32';
|
||||
}
|
||||
.web-icon-tiktok:before {
|
||||
.web-icon-textmagic:before {
|
||||
content: '\ea33';
|
||||
}
|
||||
.web-icon-twitter:before {
|
||||
.web-icon-tiktok:before {
|
||||
content: '\ea34';
|
||||
}
|
||||
.web-icon-vue:before {
|
||||
.web-icon-twitter:before {
|
||||
content: '\ea35';
|
||||
}
|
||||
.web-icon-x:before {
|
||||
.web-icon-vue:before {
|
||||
content: '\ea36';
|
||||
}
|
||||
.web-icon-ycombinator:before {
|
||||
.web-icon-x:before {
|
||||
content: '\ea37';
|
||||
}
|
||||
.web-icon-youtube:before {
|
||||
.web-icon-ycombinator:before {
|
||||
content: '\ea38';
|
||||
}
|
||||
.web-icon-youtube:before {
|
||||
content: '\ea39';
|
||||
}
|
||||
|
||||
@@ -60,18 +60,19 @@
|
||||
.web-icon-plus:before { content: "\ea2a"; }
|
||||
.web-icon-product-hunt:before { content: "\ea2b"; }
|
||||
.web-icon-refine:before { content: "\ea2c"; }
|
||||
.web-icon-rest:before { content: "\ea2d"; }
|
||||
.web-icon-search:before { content: "\ea2e"; }
|
||||
.web-icon-sendgrid:before { content: "\ea2f"; }
|
||||
.web-icon-star:before { content: "\ea30"; }
|
||||
.web-icon-system:before { content: "\ea31"; }
|
||||
.web-icon-textmagic:before { content: "\ea32"; }
|
||||
.web-icon-tiktok:before { content: "\ea33"; }
|
||||
.web-icon-twitter:before { content: "\ea34"; }
|
||||
.web-icon-vue:before { content: "\ea35"; }
|
||||
.web-icon-x:before { content: "\ea36"; }
|
||||
.web-icon-ycombinator:before { content: "\ea37"; }
|
||||
.web-icon-youtube:before { content: "\ea38"; }
|
||||
.web-icon-remix:before { content: "\ea2d"; }
|
||||
.web-icon-rest:before { content: "\ea2e"; }
|
||||
.web-icon-search:before { content: "\ea2f"; }
|
||||
.web-icon-sendgrid:before { content: "\ea30"; }
|
||||
.web-icon-star:before { content: "\ea31"; }
|
||||
.web-icon-system:before { content: "\ea32"; }
|
||||
.web-icon-textmagic:before { content: "\ea33"; }
|
||||
.web-icon-tiktok:before { content: "\ea34"; }
|
||||
.web-icon-twitter:before { content: "\ea35"; }
|
||||
.web-icon-vue:before { content: "\ea36"; }
|
||||
.web-icon-x:before { content: "\ea37"; }
|
||||
.web-icon-ycombinator:before { content: "\ea38"; }
|
||||
.web-icon-youtube:before { content: "\ea39"; }
|
||||
|
||||
$web-icon-apple: "\ea01";
|
||||
$web-icon-appwrite: "\ea02";
|
||||
@@ -117,15 +118,16 @@ $web-icon-play: "\ea29";
|
||||
$web-icon-plus: "\ea2a";
|
||||
$web-icon-product-hunt: "\ea2b";
|
||||
$web-icon-refine: "\ea2c";
|
||||
$web-icon-rest: "\ea2d";
|
||||
$web-icon-search: "\ea2e";
|
||||
$web-icon-sendgrid: "\ea2f";
|
||||
$web-icon-star: "\ea30";
|
||||
$web-icon-system: "\ea31";
|
||||
$web-icon-textmagic: "\ea32";
|
||||
$web-icon-tiktok: "\ea33";
|
||||
$web-icon-twitter: "\ea34";
|
||||
$web-icon-vue: "\ea35";
|
||||
$web-icon-x: "\ea36";
|
||||
$web-icon-ycombinator: "\ea37";
|
||||
$web-icon-youtube: "\ea38";
|
||||
$web-icon-remix: "\ea2d";
|
||||
$web-icon-rest: "\ea2e";
|
||||
$web-icon-search: "\ea2f";
|
||||
$web-icon-sendgrid: "\ea30";
|
||||
$web-icon-star: "\ea31";
|
||||
$web-icon-system: "\ea32";
|
||||
$web-icon-textmagic: "\ea33";
|
||||
$web-icon-tiktok: "\ea34";
|
||||
$web-icon-twitter: "\ea35";
|
||||
$web-icon-vue: "\ea36";
|
||||
$web-icon-x: "\ea37";
|
||||
$web-icon-ycombinator: "\ea38";
|
||||
$web-icon-youtube: "\ea39";
|
||||
|
||||
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 80 KiB |
3
src/icons/svg/remix.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.5876 3C13.8692 3 15.5 4.71409 15.5 7.45218C15.5 9.50017 14.3524 10.8358 12.8022 11.0584C14.1108 11.3478 14.8758 12.1715 15.0168 13.7965L15.0372 14.0953L15.055 14.3747L15.0704 14.636L15.0811 14.8331L15.0926 15.0656L15.0985 15.1983L15.107 15.4091L15.1138 15.6082L15.1172 15.7226L15.1218 15.906L15.1258 16.1156L15.1272 16.2169L15.1298 16.5105L15.1306 16.8168L15.1307 17H11.7465L11.7467 16.9236L11.7479 16.7752L11.7499 16.6307L11.7558 16.2806L11.7572 16.1633L11.7584 15.9792L11.7582 15.8615L11.7573 15.7381L11.7559 15.6413L11.7531 15.5057L11.7491 15.3618L11.7437 15.2089L11.7368 15.046L11.7327 14.9605L11.7258 14.827L11.7178 14.6866L11.7055 14.4883L11.6949 14.3307C11.6918 14.2821 11.6883 14.2347 11.6843 14.1883L11.6756 14.0972C11.5639 13.0207 11.1748 12.5807 10.5084 12.434L10.4523 12.4224C10.4144 12.4152 10.3757 12.4088 10.3361 12.4032L10.2761 12.3955C10.2659 12.3943 10.2558 12.3931 10.2456 12.392L10.1836 12.3861L10.1204 12.3812L10.0559 12.3774L9.99079 12.3746L9.92444 12.3728L9.85685 12.3719L4.5 12.3718V9.45568H9.98364C10.0733 9.45568 10.1602 9.45381 10.2443 9.45L10.3275 9.44555L10.4088 9.43978L10.4883 9.43269C10.5014 9.43139 10.5145 9.43004 10.5274 9.42864L10.6041 9.41952C10.6546 9.41299 10.7039 9.40555 10.752 9.39717L10.8232 9.3839C11.713 9.20685 12.1579 8.68846 12.1579 7.67686C12.1579 6.54159 11.4332 5.85355 9.98364 5.85355H4.5V3H10.5876ZM8.07828 14.8261C8.52228 14.8261 8.70805 15.0966 8.77423 15.3556L8.78296 15.3928L8.79013 15.4297L8.79479 15.4588L8.79679 15.4732L8.80013 15.5017L8.80264 15.5295L8.80361 15.5432L8.80497 15.57L8.80539 15.5831L8.80572 15.6086V17H4.5V14.8261H8.07828Z" fill="#2D2D31"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -1,12 +1,11 @@
|
||||
import { Analytics, type AnalyticsPlugin } from 'analytics';
|
||||
import Plausible from 'plausible-tracker';
|
||||
import posthogEvent from 'posthog-js';
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
import { page } from '$app/state';
|
||||
import { ENV } from '$lib/system';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
import posthogEvent from 'posthog-js';
|
||||
import Plausible from 'plausible-tracker';
|
||||
import { Analytics, type AnalyticsPlugin } from 'analytics';
|
||||
|
||||
type Payload = {
|
||||
payload: {
|
||||
event: string;
|
||||
@@ -55,30 +54,20 @@ const analytics = Analytics({
|
||||
plugins: [plausible('appwrite.io')]
|
||||
});
|
||||
|
||||
export type TrackEventArgs = {
|
||||
plausible?: { name: string; data?: object };
|
||||
posthog?: { name: string };
|
||||
};
|
||||
export type TrackEventArgs = { name: string; data?: object };
|
||||
|
||||
export const trackEvent = async (platforms: TrackEventArgs) => {
|
||||
if (!isTrackingAllowed()) {
|
||||
export const trackEvent = (eventArgs?: string | TrackEventArgs): void => {
|
||||
if (!eventArgs || ENV.TEST) return;
|
||||
|
||||
const path = page.route.id ?? '';
|
||||
const name = typeof eventArgs === 'string' ? eventArgs : eventArgs.name;
|
||||
const data = typeof eventArgs === 'string' ? { path } : { ...eventArgs.data, path };
|
||||
|
||||
if (ENV.DEV || ENV.PREVIEW) {
|
||||
console.log(`[Analytics] Event:`, name, data);
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPage = get(page);
|
||||
const path = currentPage.route.id ?? '';
|
||||
|
||||
if (ENV.DEV || ENV.PREVIEW) {
|
||||
console.log(`[Analytics] Event`, platforms.plausible, platforms.posthog);
|
||||
} else {
|
||||
if (platforms.plausible) {
|
||||
await analytics.track(platforms.plausible.name, { ...platforms.plausible.data, path });
|
||||
}
|
||||
|
||||
if (platforms.posthog) {
|
||||
posthogEvent.capture(platforms.posthog.name);
|
||||
}
|
||||
}
|
||||
posthogEvent.capture(name, data);
|
||||
analytics.track(name, data).then();
|
||||
};
|
||||
|
||||
export const isTrackingAllowed = () => !ENV.TEST;
|
||||
|
||||
@@ -1,26 +1,34 @@
|
||||
export function write(text: string, cb: (v: string) => void, duration = 500) {
|
||||
if (text.length === 0) {
|
||||
cb('');
|
||||
return Promise.resolve();
|
||||
}
|
||||
const step = duration / text.length;
|
||||
let i = 0;
|
||||
return new Promise((resolve) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
cb(text.slice(0, ++i));
|
||||
if (i === text.length) {
|
||||
clearInterval(interval);
|
||||
resolve(undefined);
|
||||
resolve();
|
||||
}
|
||||
}, step);
|
||||
});
|
||||
}
|
||||
|
||||
export function unwrite(text: string, cb: (v: string) => void, duration = 500) {
|
||||
if (text.length === 0) {
|
||||
cb('');
|
||||
return Promise.resolve();
|
||||
}
|
||||
const step = duration / text.length;
|
||||
let i = text.length;
|
||||
return new Promise((resolve) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
cb(text.slice(0, --i));
|
||||
if (i === 0) {
|
||||
clearInterval(interval);
|
||||
resolve(undefined);
|
||||
resolve();
|
||||
}
|
||||
}, step);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
>
|
||||
<div class="flex max-w-3xs flex-col items-center justify-center gap-5 text-center">
|
||||
<h2 class="text-label text-primary font-aeonik-pro">{heading}</h2>
|
||||
<Button href={getAppwriteDashboardUrl()}>{label}</Button>
|
||||
<Button href={getAppwriteDashboardUrl()} event="blog-cta-get_started_btn-click"
|
||||
>{label}</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createAccordion, melt } from '@melt-ui/svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { createAccordion, melt } from '@melt-ui/svelte';
|
||||
|
||||
export let noBorder = false;
|
||||
|
||||
@@ -38,7 +39,8 @@
|
||||
{ label: 'Messaging', href: '/products/messaging' },
|
||||
{ label: 'Storage', href: '/products/storage' },
|
||||
{ label: 'Realtime', href: '/docs/apis/realtime' },
|
||||
{ label: 'Network', href: '/docs/products/network' }
|
||||
{ label: 'Network', href: '/docs/products/network' },
|
||||
{ label: 'Hosting', href: '/docs/products/sites' }
|
||||
],
|
||||
Learn: [
|
||||
{ label: 'Blog', href: '/blog' },
|
||||
@@ -111,7 +113,16 @@
|
||||
<ul class="web-footer-nav-secondary-list text-sub-body">
|
||||
{#each items as { href, label, target, rel }}
|
||||
<li>
|
||||
<a class="web-link" {href} {target} {rel}>{label}</a>
|
||||
<a
|
||||
class="web-link"
|
||||
{href}
|
||||
{target}
|
||||
{rel}
|
||||
onclick={() =>
|
||||
trackEvent(
|
||||
`footer-${label.toLowerCase().replace(' ', '_')}-click`
|
||||
)}>{label}</a
|
||||
>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
@@ -141,7 +152,16 @@
|
||||
>
|
||||
{#each items as { href, label, target, rel }}
|
||||
<li>
|
||||
<a class="web-link" {href} {target} {rel}>{label}</a>
|
||||
<a
|
||||
class="web-link"
|
||||
{href}
|
||||
{target}
|
||||
{rel}
|
||||
onclick={() =>
|
||||
trackEvent(
|
||||
`footer-${label.toLowerCase().replace(' ', '_')}-click`
|
||||
)}>{label}</a
|
||||
>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
@@ -1,31 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { browser } from '$app/environment';
|
||||
import { getAppwriteDashboardUrl } from '$lib/utils/dashboard';
|
||||
import { Button } from '$lib/components/ui';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { getAppwriteDashboardUrl } from '$lib/utils/dashboard';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { class: className }: Props = $props();
|
||||
|
||||
const isLoggedIn = browser && 'loggedIn' in document.body.dataset;
|
||||
|
||||
function getTrackingEventName() {
|
||||
return browser ? (isLoggedIn ? 'Go to console' : 'Start building') : 'Start building';
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button
|
||||
class={classNames('web-u-inline-width-100-percent-mobile', className)}
|
||||
href={getAppwriteDashboardUrl()}
|
||||
onclick={() =>
|
||||
trackEvent({
|
||||
plausible: { name: `${getTrackingEventName()} in header` },
|
||||
...(isLoggedIn ? {} : { posthog: { name: 'get-started-btn_nav_click' } })
|
||||
})}
|
||||
event="main-get_started_btn_nav-click"
|
||||
class={classNames('web-u-inline-width-100-percent-mobile', className)}
|
||||
>
|
||||
<span class="hidden group-[&[data-logged-in]]/body:block" aria-hidden={!isLoggedIn}
|
||||
>Go to Console</span
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { socials } from '$lib/constants';
|
||||
import ThemeSelect from './ThemeSelect.svelte';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
export let variant: 'homepage' | 'docs' = 'homepage';
|
||||
|
||||
@@ -39,9 +40,27 @@
|
||||
></iframe>
|
||||
|
||||
<ul class="flex gap-4">
|
||||
<li><a class="web-link" href="/terms">Terms</a></li>
|
||||
<li><a class="web-link" href="/privacy">Privacy</a></li>
|
||||
<li><a class="web-link" href="/cookies">Cookies</a></li>
|
||||
<li>
|
||||
<a
|
||||
class="web-link"
|
||||
href="/terms"
|
||||
onclick={() => trackEvent(`footer-terms-click`)}>Terms</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="web-link"
|
||||
href="/privacy"
|
||||
onclick={() => trackEvent(`footer-privacy-click`)}>Privacy</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="web-link"
|
||||
href="/cookies"
|
||||
onclick={() => trackEvent(`footer-cookies-click`)}>Cookies</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -68,11 +87,19 @@
|
||||
</div>
|
||||
<ul class="web-main-footer-grid-1-column-3 web-main-footer-links items-start">
|
||||
<li>
|
||||
<a href="/discord" target="_blank" rel="noopener noreferrer">Support</a>
|
||||
<a
|
||||
href="/discord"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onclick={() => trackEvent(`footer-support-click`)}>Support</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://appwrite.online" target="_blank" rel="noopener noreferrer"
|
||||
>Status</a
|
||||
<a
|
||||
href="https://appwrite.online"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onclick={() => trackEvent(`footer-appwrite_status-click`)}>Status</a
|
||||
>
|
||||
</li>
|
||||
<!-- <li>
|
||||
|
||||
@@ -41,12 +41,7 @@
|
||||
href={link.href}
|
||||
data-initialized={initialized ? '' : undefined}
|
||||
data-badge={link.showBadge ? '' : undefined}
|
||||
on:click={() => {
|
||||
trackEvent({
|
||||
plausible: { name: `${link.label} in header` },
|
||||
posthog: { name: `${link.label.toLowerCase()}_nav_click` }
|
||||
});
|
||||
}}
|
||||
onclick={() => trackEvent(`main-nav-${link.label.toLowerCase()}-nav-click`)}
|
||||
>{link.label}
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { getAppwriteDashboardUrl } from '$lib/utils/dashboard';
|
||||
import { Button, InlineTag, Icon } from '$lib/components/ui';
|
||||
import { GithubStats } from '$lib/components/shared';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
export let open = false;
|
||||
export let links: NavLink[];
|
||||
@@ -20,7 +21,12 @@
|
||||
<nav class="web-side-nav web-is-not-desktop" class:hidden={!open}>
|
||||
<div class="web-side-nav-wrapper ps-4 pe-4">
|
||||
<div class="flex items-center gap-2 px-4">
|
||||
<Button href={getAppwriteDashboardUrl('/register')} variant="secondary" class="flex-1">
|
||||
<Button
|
||||
href={getAppwriteDashboardUrl('/register')}
|
||||
variant="secondary"
|
||||
class="flex-1"
|
||||
event="mobile_nav-sign_up-click"
|
||||
>
|
||||
Sign up
|
||||
</Button>
|
||||
<IsLoggedIn class="flex-1" />
|
||||
@@ -33,7 +39,14 @@
|
||||
{#if mobileSubmenu}
|
||||
<svelte:component this={mobileSubmenu} {label} />
|
||||
{:else}
|
||||
<a class="web-side-nav-button" {href}>
|
||||
<a
|
||||
class="web-side-nav-button"
|
||||
{href}
|
||||
onclick={() =>
|
||||
trackEvent(
|
||||
`mobile-nav-${label.toLowerCase().replace(' ', '_')}-click`
|
||||
)}
|
||||
>
|
||||
<span class="text-caption">{label}</span>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script context="module" lang="ts">
|
||||
import { PUBLIC_GROWTH_ENDPOINT } from '$env/static/public';
|
||||
import { Button } from '$lib/components/ui';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
export async function newsletter(name: string, email: string) {
|
||||
const response = await fetch(`${PUBLIC_GROWTH_ENDPOINT}/newsletter/subscribe`, {
|
||||
@@ -167,7 +168,11 @@
|
||||
bind:value={email}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" disabled={submitting}>Sign up</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
event="newsletter-subscribe-submit">Sign up</Button
|
||||
>
|
||||
{#if error}
|
||||
<span class="text">
|
||||
Something went wrong. Please try again later.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { getAppwriteDashboardUrl } from '$lib/utils/dashboard';
|
||||
import { Button, type Variant } from '$lib/components/ui';
|
||||
import { getAppwriteDashboardUrl } from '$lib/utils/dashboard';
|
||||
|
||||
const plans: Array<{
|
||||
name: string;
|
||||
@@ -21,7 +20,7 @@
|
||||
buttonText: 'Get started',
|
||||
buttonLink: getAppwriteDashboardUrl('/register'),
|
||||
buttonVariant: 'secondary',
|
||||
eventName: 'Get started Free plan'
|
||||
eventName: 'footer-plans-free-click'
|
||||
},
|
||||
{
|
||||
name: 'Pro',
|
||||
@@ -33,7 +32,7 @@
|
||||
buttonText: 'Start building',
|
||||
buttonLink: getAppwriteDashboardUrl('/console?type=create&plan=tier-1'),
|
||||
buttonVariant: 'primary',
|
||||
eventName: 'Get started Pro plan'
|
||||
eventName: 'footer-plans-pro-click'
|
||||
},
|
||||
{
|
||||
name: 'Scale',
|
||||
@@ -44,7 +43,7 @@
|
||||
buttonText: 'Start building',
|
||||
buttonLink: getAppwriteDashboardUrl('/console?type=create&plan=tier-2'),
|
||||
buttonVariant: 'secondary',
|
||||
eventName: 'Get started Scale plan'
|
||||
eventName: 'footer-plans-scale-click'
|
||||
},
|
||||
{
|
||||
name: 'Enterprise',
|
||||
@@ -53,7 +52,7 @@
|
||||
buttonText: 'Contact us',
|
||||
buttonLink: '/contact-us/enterprise',
|
||||
buttonVariant: 'secondary',
|
||||
eventName: 'Get started Enterprise plan'
|
||||
eventName: 'footer-plans-enterprise-click'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
@@ -73,9 +72,9 @@
|
||||
</h2>
|
||||
<Button
|
||||
variant="transparent"
|
||||
href={getAppwriteDashboardUrl()}
|
||||
class="self-center"
|
||||
onclick={() => trackEvent({ plausible: { name: 'Get started in pre footer' } })}
|
||||
href={getAppwriteDashboardUrl()}
|
||||
event="footer-plans-get_started-click"
|
||||
>
|
||||
<span class="text">Get started</span>
|
||||
</Button>
|
||||
@@ -117,15 +116,9 @@
|
||||
{plan.description}
|
||||
</p>
|
||||
<Button
|
||||
event={plan.eventName}
|
||||
variant={plan.buttonVariant}
|
||||
href={plan.buttonLink}
|
||||
class="w-full! flex-3 self-end md:w-fit"
|
||||
onclick={() =>
|
||||
trackEvent({
|
||||
plausible: {
|
||||
name: plan.eventName
|
||||
}
|
||||
})}
|
||||
>
|
||||
<span class="text" style:padding-inline="0.5rem">{plan.buttonText}</span
|
||||
>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { melt, createCollapsible } from '@melt-ui/svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { products, sublinks } from './ProductsSubmenu.svelte';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { melt, createCollapsible } from '@melt-ui/svelte';
|
||||
import { products, sublinks } from './ProductsSubmenu.svelte';
|
||||
|
||||
export let label: string;
|
||||
|
||||
@@ -34,13 +34,11 @@
|
||||
{#each products as product}
|
||||
<a
|
||||
href={product.href}
|
||||
onclick={() =>
|
||||
trackEvent(
|
||||
`products-mobile_submenu-${product.name.toLowerCase()}-click`
|
||||
)}
|
||||
class="group flex gap-3 rounded-xl p-2 text-white transition-colors outline-none focus:bg-white/8"
|
||||
on:click={() =>
|
||||
trackEvent({
|
||||
plausible: {
|
||||
name: `${product.name} in products submenu`
|
||||
}
|
||||
})}
|
||||
>
|
||||
<div
|
||||
class="flex size-12 shrink-0 items-center justify-center rounded-lg border border-white/12 bg-white/6"
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
description: 'Set up a full-functioning messaging service.',
|
||||
icon: '/images/icons/illustrated/dark/messaging.png'
|
||||
},
|
||||
{
|
||||
name: 'Sites',
|
||||
href: '/products/sites',
|
||||
description: 'The open-source Vercel alternative.',
|
||||
icon: '/images/icons/illustrated/dark/sites.png'
|
||||
},
|
||||
{
|
||||
name: 'Realtime',
|
||||
href: '/docs/apis/realtime',
|
||||
@@ -59,12 +65,15 @@
|
||||
{
|
||||
label: 'Appwrite vs. Firebase',
|
||||
href: '/blog/post/open-source-firebase-alternative'
|
||||
},
|
||||
{
|
||||
label: 'Appwrite vs. Vercel',
|
||||
href: '/blog/post/open-source-vercel-alternative'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { dev } from '$app/environment';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { createDropdownMenu, melt } from '@melt-ui/svelte';
|
||||
@@ -117,12 +126,8 @@
|
||||
<a
|
||||
href={product.href}
|
||||
use:melt={$item}
|
||||
on:click={() =>
|
||||
trackEvent({
|
||||
plausible: {
|
||||
name: `${product.name} in products submenu`
|
||||
}
|
||||
})}
|
||||
onclick={() =>
|
||||
trackEvent(`products-submenu-${product.name.toLowerCase()}-click`)}
|
||||
class="group flex gap-3 rounded-xl p-1 text-white transition-colors outline-none focus:bg-white/8"
|
||||
>
|
||||
<div
|
||||
@@ -182,8 +187,8 @@
|
||||
class="aspect-[3/1] max-w-[7.5rem] shrink-0 rounded-xl object-cover"
|
||||
/>
|
||||
<p class="text-pretty">
|
||||
Empowering Shopify merchants with real-time store monitoring using
|
||||
StoreAlert
|
||||
Appwrited helped reduce development time by 60%, and lower server costs
|
||||
by 40%.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,10 @@
|
||||
<a
|
||||
href={platform.href}
|
||||
class="web-icon-button web-box-icon has-border-gradient"
|
||||
on:click={() => trackEvent({ plausible: { name: `${platform.name} clicked` } })}
|
||||
onclick={() =>
|
||||
trackEvent(
|
||||
`technologies-${platform.name.replace(' ', '-').toLowerCase()}-click`
|
||||
)}
|
||||
>
|
||||
<img
|
||||
src={platform.image}
|
||||
|
||||
@@ -1,55 +1,80 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { Tabs } from 'bits-ui';
|
||||
|
||||
import type { IconType } from '../ui';
|
||||
import Icon from '../ui/icon';
|
||||
import Icon from '../ui/icon/icon.svelte';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
|
||||
type Props = {
|
||||
const {
|
||||
onValueChange,
|
||||
theme = 'dark'
|
||||
}: {
|
||||
onValueChange: (value: string) => void;
|
||||
};
|
||||
theme?: 'light' | 'dark';
|
||||
} = $props();
|
||||
|
||||
const { onValueChange }: Props = $props();
|
||||
const navItems = [
|
||||
{ label: 'PoP Locations', value: 'pop-locations', icon: 'pop-locations' },
|
||||
{ label: 'Edges', value: 'edges', icon: 'edge' },
|
||||
{ label: 'Regions', value: 'regions', icon: 'regions' }
|
||||
] satisfies Array<{ label: string; value: string; icon: IconType }>;
|
||||
|
||||
const navItems: Array<{ label: string; value: string; icon: IconType }> = [
|
||||
{
|
||||
label: 'PoP Locations',
|
||||
value: 'pop-locations',
|
||||
icon: 'pop-locations'
|
||||
},
|
||||
{
|
||||
label: 'Edges',
|
||||
value: 'edges',
|
||||
icon: 'edge'
|
||||
},
|
||||
{
|
||||
label: 'Regions',
|
||||
value: 'regions',
|
||||
icon: 'regions'
|
||||
let selectedTab = $state('pop-locations');
|
||||
|
||||
function getDescription() {
|
||||
switch (selectedTab) {
|
||||
case 'pop-locations':
|
||||
return 'Points of presence ensure <50ms ping around the globe.';
|
||||
case 'edges':
|
||||
return 'Edges bring compute closer to users for faster response times.';
|
||||
case 'regions':
|
||||
return 'Regions offer data residency and redundancy across continents.';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-4 text-center">
|
||||
<Tabs.Root
|
||||
value={navItems[0].value}
|
||||
{onValueChange}
|
||||
class="flex flex-col items-center justify-center gap-12 md:-mt-8"
|
||||
onValueChange={(value) => {
|
||||
selectedTab = value;
|
||||
onValueChange(value);
|
||||
}}
|
||||
value={navItems[0]?.value}
|
||||
class="flex flex-col items-center justify-center gap-12 md:mt-9"
|
||||
>
|
||||
<Tabs.List
|
||||
class="border-smooth animate-fade-in bg-card relative grid w-full max-w-xl grid-cols-1 place-content-center gap-3 p-1 px-8 drop-shadow-md md:grid-cols-3 md:rounded-full md:border md:px-1"
|
||||
class={classNames(
|
||||
'border-smooth animate-fade-in relative grid w-full max-w-xl grid-cols-1 place-content-center gap-3 p-1 px-8 drop-shadow-md md:grid-cols-3 md:rounded-full md:border md:px-1',
|
||||
theme === 'light' ? 'md:bg[var(--card, rgba(255,255,255,0.90))]' : 'md:bg-card'
|
||||
)}
|
||||
>
|
||||
{#each navItems as { label, icon, value }, index}
|
||||
<Tabs.Trigger
|
||||
{value}
|
||||
class={classNames(
|
||||
'text-caption animate-enter text-primary bg-smooth border-smooth flex h-8 cursor-pointer items-center justify-center gap-2 rounded-full border font-medium outline-0 transition-colors hover:border-white/12',
|
||||
'group data-[state="active"]:bg-accent/4 data-[state="active"]:border-accent/36 data-[state="active"]:text-white'
|
||||
'group data-[state="active"]:bg-accent/4 data-[state="active"]:border-accent/36 data-[state="active"]:text-accent'
|
||||
)}
|
||||
style="animation-delay:{index * 75}ms;"
|
||||
>
|
||||
<Icon name={icon} class="group-data-[state='active']:text-accent -ml-2" />
|
||||
{label}</Tabs.Trigger
|
||||
>
|
||||
<Icon
|
||||
name={icon}
|
||||
class={classNames(
|
||||
'-ml-2',
|
||||
"group-data-[state='active']:text-accent",
|
||||
theme === 'light' ? 'text-[#19191C]' : 'text-inherit'
|
||||
)}
|
||||
/>
|
||||
{label}
|
||||
</Tabs.Trigger>
|
||||
{/each}
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
|
||||
{#key selectedTab}
|
||||
<p class="animate-enter text-caption px-4">
|
||||
{getDescription()}
|
||||
</p>
|
||||
{/key}
|
||||
</div>
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
theme: 'light' | 'dark';
|
||||
};
|
||||
|
||||
const { coords }: Props = $props();
|
||||
const { coords, theme = 'dark' }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if $tooltipData.city}
|
||||
@@ -33,8 +35,9 @@
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'bg-card/90 border-gradient relative z-100 flex w-[190px] flex-col gap-2 rounded-[10px] p-2 backdrop-blur-lg before:rounded-[10px] after:rounded-[10px]',
|
||||
'data-[state="closed"]:animate-menu-out data-[state="instant-open"]:animate-menu-in data-[state="delayed-open"]:animate-menu-in'
|
||||
'border-gradient relative z-100 flex w-[190px] flex-col gap-2 rounded-[10px] p-2 backdrop-blur-lg before:rounded-[10px] after:rounded-[10px]',
|
||||
'data-[state="closed"]:animate-menu-out data-[state="instant-open"]:animate-menu-in data-[state="delayed-open"]:animate-menu-in',
|
||||
theme === 'dark' ? 'bg-card/90' : 'bg[var(--card, rgba(255,255,255))]'
|
||||
)}
|
||||
>
|
||||
<span class="text-primary text-caption w-fit">
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
import { pins, type PinSegment } from './data/pins';
|
||||
import MapTooltip from './map-tooltip.svelte';
|
||||
|
||||
let dimensions = $state({
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
|
||||
let activeRegion = $state<string | null>(null);
|
||||
let activeMarker: HTMLElement | null = null;
|
||||
let activeSegment = $state<string>('pop-locations');
|
||||
@@ -62,9 +67,12 @@
|
||||
activeRegion = citySlug;
|
||||
}
|
||||
};
|
||||
|
||||
type Props = { theme: 'light' | 'dark' };
|
||||
|
||||
const { theme = 'dark' }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="relative">
|
||||
<div class="-mt-8 w-full overflow-x-scroll [scrollbar-width:none] md:overflow-x-hidden">
|
||||
<div
|
||||
class="sticky left-0 mx-auto block max-w-[calc(100vw_-_calc(var(--spacing)_*-2))] md:hidden"
|
||||
@@ -73,7 +81,7 @@
|
||||
class="web-input-text mx-auto appearance-none"
|
||||
onchange={(e) => handleSetActiveMarker(e.currentTarget.value)}
|
||||
>
|
||||
{#each pins[activeSegment as PinSegment].pins as pin}
|
||||
{#each pins[activeSegment as PinSegment] as pin}
|
||||
<option value={pin.city}>{pin.city}-({pin.code})</option>
|
||||
{/each}
|
||||
</select>
|
||||
@@ -86,6 +94,8 @@
|
||||
>
|
||||
<div
|
||||
class="relative w-full origin-bottom transform-[perspective(25px)_rotateX(1deg)_scale3d(1.4,_1.4,_1)] transition-all [scrollbar-width:none]"
|
||||
bind:clientWidth={dimensions.width}
|
||||
bind:clientHeight={dimensions.height}
|
||||
>
|
||||
<div
|
||||
class="absolute inset-0 mask-[image:url('/images/appwrite-network/map.svg')] mask-contain mask-no-repeat"
|
||||
@@ -101,23 +111,22 @@
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- TODO: reusing the same image but inverted! use a variable -->
|
||||
<img
|
||||
src="/images/appwrite-network/map.svg"
|
||||
class="pointer-events-none relative -z-10 w-full opacity-10 md:max-h-[525px]"
|
||||
draggable="false"
|
||||
alt="Map of the world"
|
||||
src="/images/appwrite-network/map.svg"
|
||||
style:filter={theme === 'light' ? 'invert()' : undefined}
|
||||
class="pointer-events-none relative -z-10 w-full opacity-10 md:max-h-[525px]"
|
||||
/>
|
||||
|
||||
{#each pins[activeSegment as PinSegment].pins as pin, index}
|
||||
{#each pins[activeSegment] as pin, index}
|
||||
<MapMarker {...pin} animate={$animate} {index} bounds={MAP_BOUNDS} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MapTooltip coords={$position} />
|
||||
|
||||
<MapNav onValueChange={(value) => (activeSegment = value)} />
|
||||
<div class="mx-auto mt-8 max-w-md text-center">
|
||||
<span class="text-center">{pins[activeSegment as PinSegment].description}</span>
|
||||
</div>
|
||||
</div>
|
||||
<MapTooltip {theme} coords={$position} />
|
||||
|
||||
<MapNav {theme} onValueChange={(value) => (activeSegment = value)} />
|
||||
|
||||
@@ -97,7 +97,11 @@
|
||||
name="email"
|
||||
bind:value={email}
|
||||
/>
|
||||
<Button type="submit" disabled={submitting}>Sign up</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
event="newsletter-subscribe-submit">Sign up</Button
|
||||
>
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
|
||||
3
src/lib/components/marketing/(assets)/icons/android.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.1672 12.7371L25.6008 8.52222C25.6437 8.45007 25.6691 8.36232 25.6691 8.26872C25.6691 7.98889 25.4429 7.76269 25.1631 7.76269C24.9768 7.76269 24.814 7.86312 24.7263 8.01327L24.7253 8.01522L22.2615 12.2828C20.4216 11.4375 18.2698 10.9441 16.0029 10.9441C13.7361 10.9441 11.5842 11.4375 9.64886 12.3218L9.74441 12.2828L7.28059 8.01424C7.19186 7.86214 7.02806 7.76074 6.84184 7.76074C6.56201 7.76074 6.33581 7.98694 6.33581 8.26677C6.33581 8.36037 6.36116 8.44714 6.40504 8.52222L6.40406 8.52027L8.83766 12.7352C4.65881 15.043 1.78256 19.2648 1.38574 24.1856L1.38281 24.2363H30.624C30.2243 19.2648 27.348 15.043 23.2433 12.7722L23.1692 12.7352L23.1672 12.7371ZM9.27154 20.0721C8.59879 20.0721 8.05376 19.527 8.05376 18.8543C8.05376 18.1815 8.59879 17.6365 9.27154 17.6365C9.94429 17.6365 10.4893 18.1815 10.4893 18.8543C10.4883 19.5261 9.94429 20.0711 9.27154 20.0721ZM22.7304 20.0721C22.0577 20.0721 21.5127 19.527 21.5127 18.8543C21.5127 18.1815 22.0577 17.6365 22.7304 17.6365C23.4032 17.6365 23.9482 18.1815 23.9482 18.8543C23.9472 19.5261 23.4032 20.0711 22.7304 20.0721Z" fill="#3DDC84"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
5
src/lib/components/marketing/(assets)/icons/angular.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.5 3L3 6.26923L4.30769 17.3846L11.5 21.3077L18.6923 17.3846L20 6.26923L11.5 3Z" fill="#DD0031"/>
|
||||
<path d="M11.5 3V21.3077L18.6923 17.3846L20 6.26923L11.5 3Z" fill="#C3002F"/>
|
||||
<path d="M11.5003 5.02307L6.18665 16.9688H8.16785L9.23605 14.2959H13.7463L14.8145 16.9688H16.7957L11.5003 5.02307ZM13.0524 12.6482H9.94819L11.5003 8.9043L13.0524 12.6482Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 489 B |
3
src/lib/components/marketing/(assets)/icons/apple.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.6437 17.5861C19.3385 18.2848 18.9772 18.928 18.5586 19.5193C17.9881 20.3255 17.5209 20.8835 17.1609 21.1934C16.6027 21.702 16.0048 21.9625 15.3644 21.9773C14.9047 21.9773 14.3504 21.8477 13.705 21.5847C13.0576 21.323 12.4626 21.1934 11.9186 21.1934C11.348 21.1934 10.7361 21.323 10.0815 21.5847C9.42602 21.8477 8.89793 21.9847 8.49417 21.9983C7.88012 22.0242 7.26806 21.7563 6.65713 21.1934C6.2672 20.8563 5.77947 20.2786 5.1952 19.4601C4.56832 18.586 4.05294 17.5725 3.64918 16.417C3.21677 15.1689 3 13.9603 3 12.7902C3 11.4498 3.29226 10.2938 3.87766 9.32509C4.33773 8.54696 4.94978 7.93316 5.71581 7.48255C6.48185 7.03195 7.30955 6.80233 8.20091 6.78763C8.68863 6.78763 9.32822 6.93714 10.123 7.23096C10.9156 7.52576 11.4245 7.67526 11.6476 7.67526C11.8144 7.67526 12.3798 7.50045 13.3382 7.15195C14.2445 6.82874 15.0094 6.69492 15.636 6.74764C17.334 6.88343 18.6097 7.54675 19.4581 8.74177C17.9395 9.6536 17.1883 10.9307 17.2032 12.5691C17.2169 13.8452 17.6841 14.9071 18.6022 15.7503C19.0183 16.1417 19.483 16.4441 20 16.6589C19.8879 16.9812 19.7695 17.2898 19.6437 17.5861ZM15.7494 2.40011C15.7494 3.40034 15.3806 4.33425 14.6456 5.19867C13.7586 6.22629 12.6857 6.8201 11.5223 6.7264C11.5075 6.60641 11.4989 6.48011 11.4989 6.3474C11.4989 5.38718 11.9207 4.35956 12.6698 3.51934C13.0438 3.09392 13.5194 2.74019 14.0962 2.45801C14.6718 2.18005 15.2162 2.02632 15.7282 2C15.7431 2.13371 15.7494 2.26744 15.7494 2.4001V2.40011Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
4
src/lib/components/marketing/(assets)/icons/astro.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.08652 19.2043C8.07508 18.292 7.77984 16.375 8.20123 14.9861C8.93188 15.8618 9.94425 16.1391 10.9929 16.2957C12.6117 16.5373 14.2016 16.447 15.7054 15.7168C15.8775 15.6332 16.0364 15.522 16.2244 15.4095C16.3655 15.8135 16.4022 16.2213 16.353 16.6364C16.2331 17.6473 15.7233 18.4282 14.9124 19.0202C14.5882 19.257 14.2451 19.4687 13.9102 19.6919C12.8814 20.3781 12.603 21.1827 12.9896 22.3531C12.9988 22.3816 13.007 22.4101 13.0278 22.4797C12.5025 22.2478 12.1188 21.91 11.8265 21.4659C11.5177 20.9971 11.3708 20.4786 11.363 19.9176C11.3592 19.6446 11.3592 19.3691 11.322 19.0999C11.2311 18.4437 10.9189 18.1499 10.3309 18.133C9.7273 18.1156 9.24985 18.4838 9.12324 19.0637C9.11358 19.1082 9.09957 19.1521 9.08556 19.2038L9.08652 19.2043Z" fill="#C3C3C6"/>
|
||||
<path d="M4 15.4113C4 15.4113 6.76558 14.0674 9.53888 14.0674L11.6299 7.61234C11.7081 7.30016 11.9367 7.08803 12.1948 7.08803C12.4528 7.08803 12.6814 7.30016 12.7597 7.61234L14.8506 14.0674C18.1352 14.0674 20.3895 15.4113 20.3895 15.4113C20.3895 15.4113 15.6919 2.64609 15.6828 2.62048C15.5479 2.24307 15.3203 2 15.0135 2H9.37651C9.06966 2 8.85124 2.24307 8.70722 2.62048C8.69706 2.64561 4 15.4113 4 15.4113Z" fill="#C3C3C6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,17 @@
|
||||
<svg width="42" height="40" viewBox="0 0 42 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.9351 33.6471V33C17.9351 27.4772 22.4122 23 27.9351 23C33.4579 23 37.9351 27.4771 37.9351 33V33.6471H27.9351H17.9351Z" fill="url(#paint0_linear_3129_11876)" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="27.9351" cy="17" r="5.4" stroke="#FD366E" stroke-width="1.2"/>
|
||||
<circle cx="14.9351" cy="13" r="5.4" stroke="#FD366E" stroke-width="1.2"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.93506 29V29.6471H14.9351H17.9351H18.502C18.8019 28.7938 19.2587 27.9181 19.8667 27.0823C20.9513 25.5915 22.3054 24.5196 23.6004 24.0055C21.8722 21.0135 18.6388 19 14.9351 19C9.41221 19 4.93506 23.4772 4.93506 29Z" fill="url(#paint1_linear_3129_11876)"/>
|
||||
<path d="M4.93506 29.6471H4.33506C4.33506 29.9784 4.60369 30.2471 4.93506 30.2471V29.6471ZM18.502 29.6471V30.2471C18.7567 30.2471 18.9836 30.0863 19.0681 29.846L18.502 29.6471ZM19.8667 27.0823L20.3519 27.4353L19.8667 27.0823ZM23.6004 24.0055L23.8218 24.5632C23.9838 24.4989 24.1099 24.3672 24.1672 24.2025C24.2244 24.0379 24.2072 23.8564 24.12 23.7054L23.6004 24.0055ZM5.53506 29.6471V29H4.33506V29.6471H5.53506ZM14.9351 29.0471H4.93506V30.2471H14.9351V29.0471ZM17.9351 29.0471H14.9351V30.2471H17.9351V29.0471ZM18.502 29.0471H17.9351V30.2471H18.502V29.0471ZM19.0681 29.846C19.3478 29.0504 19.7765 28.2262 20.3519 27.4353L19.3815 26.7294C18.7408 27.61 18.2561 28.5373 17.936 29.4481L19.0681 29.846ZM20.3519 27.4353C21.3821 26.0193 22.6503 25.0282 23.8218 24.5632L23.3791 23.4478C21.9605 24.0109 20.5206 25.1637 19.3815 26.7294L20.3519 27.4353ZM14.9351 19.6C18.4158 19.6 21.4554 21.4915 23.0809 24.3056L24.12 23.7054C22.2889 20.5354 18.8617 18.4 14.9351 18.4V19.6ZM5.53506 29C5.53506 23.8085 9.74358 19.6 14.9351 19.6V18.4C9.08084 18.4 4.33506 23.1458 4.33506 29H5.53506Z" fill="#FD366E"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_3129_11876" x1="27.9351" y1="23" x2="27.9351" y2="42" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FD366E" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#FD366E" stop-opacity="0.6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_3129_11876" x1="14.9354" y1="19" x2="14.9354" y2="38" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FD366E" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#FD366E" stop-opacity="0.6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,23 @@
|
||||
<svg width="41" height="41" viewBox="0 0 41 41" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.667 14.5V10.0556C14.667 8.58213 15.2991 7.16905 16.4244 6.12718C17.5496 5.08532 19.0757 4.5 20.667 4.5C22.2583 4.5 23.7844 5.08532 24.9096 6.12718C26.0349 7.16905 26.667 8.58213 26.667 10.0556" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M31.5559 14.5H9.7781C8.05988 14.5 6.66699 16.2909 6.66699 18.5V32.5C6.66699 34.7091 8.05988 36.5 9.7781 36.5H31.5559C33.2741 36.5 34.667 34.7091 34.667 32.5V18.5C34.667 16.2909 33.2741 14.5 31.5559 14.5Z" fill="url(#paint0_linear_3129_11900)"/>
|
||||
<path d="M9.7781 15.1H31.5559V13.9H9.7781V15.1ZM31.5559 15.1C32.8111 15.1 34.067 16.4732 34.067 18.5H35.267C35.267 16.1086 33.7371 13.9 31.5559 13.9V15.1ZM34.067 18.5V32.5H35.267V18.5H34.067ZM34.067 32.5C34.067 34.5268 32.8111 35.9 31.5559 35.9V37.1C33.7371 37.1 35.267 34.8914 35.267 32.5H34.067ZM31.5559 35.9H9.7781V37.1H31.5559V35.9ZM9.7781 35.9C8.52285 35.9 7.26699 34.5268 7.26699 32.5H6.06699C6.06699 34.8914 7.59692 37.1 9.7781 37.1V35.9ZM7.26699 32.5V18.5H6.06699V32.5H7.26699ZM7.26699 18.5C7.26699 16.4732 8.52285 15.1 9.7781 15.1V13.9C7.59692 13.9 6.06699 16.1086 6.06699 18.5H7.26699Z" fill="#FD366E"/>
|
||||
<g filter="url(#filter0_b_3129_11900)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.6755 26.1674C23.7223 25.5021 24.417 24.3322 24.417 23C24.417 20.9289 22.7381 19.25 20.667 19.25C18.5959 19.25 16.917 20.9289 16.917 23C16.917 24.3322 17.6117 25.5021 18.6585 26.1674L17.542 31.75H23.792L22.6755 26.1674Z" fill="#EDEDF0"/>
|
||||
<path d="M22.6755 26.1674L22.3537 25.6609C22.1444 25.7939 22.0385 26.0419 22.0871 26.285L22.6755 26.1674ZM18.6585 26.1674L19.2469 26.285C19.2955 26.0419 19.1896 25.7939 18.9803 25.6609L18.6585 26.1674ZM17.542 31.75L16.9536 31.6323C16.9184 31.8086 16.964 31.9914 17.078 32.1304C17.192 32.2694 17.3622 32.35 17.542 32.35V31.75ZM23.792 31.75V32.35C23.9717 32.35 24.142 32.2694 24.256 32.1304C24.37 31.9914 24.4156 31.8086 24.3803 31.6323L23.792 31.75ZM23.817 23C23.817 24.1184 23.2346 25.1012 22.3537 25.6609L22.9973 26.6738C24.2101 25.9031 25.017 24.546 25.017 23H23.817ZM20.667 19.85C22.4067 19.85 23.817 21.2603 23.817 23H25.017C25.017 20.5976 23.0694 18.65 20.667 18.65V19.85ZM17.517 23C17.517 21.2603 18.9273 19.85 20.667 19.85V18.65C18.2646 18.65 16.317 20.5976 16.317 23H17.517ZM18.9803 25.6609C18.0994 25.1012 17.517 24.1184 17.517 23H16.317C16.317 24.546 17.1239 25.9031 18.3367 26.6738L18.9803 25.6609ZM18.1303 31.8677L19.2469 26.285L18.0702 26.0497L16.9536 31.6323L18.1303 31.8677ZM23.792 31.15H17.542V32.35H23.792V31.15ZM22.0871 26.285L23.2036 31.8677L24.3803 31.6323L23.2638 26.0497L22.0871 26.285Z" fill="#FD366E"/>
|
||||
</g>
|
||||
<path d="M29.667 8.5L33.167 4" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M31.667 10.5L33.667 9.5" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<defs>
|
||||
<filter id="filter0_b_3129_11900" x="10.3169" y="12.6499" width="20.7002" height="25.7002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feGaussianBlur in="BackgroundImageFix" stdDeviation="3"/>
|
||||
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_3129_11900"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_3129_11900" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_3129_11900" x1="20.6688" y1="14.25" x2="20.6688" y2="36.75" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FD366E" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#FD366E" stop-opacity="0.32"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
17
src/lib/components/marketing/(assets)/icons/dart.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.66995 17.3279L3.59227 14.2494C3.22739 13.8739 3 13.3449 3 12.8279C3 12.5885 3.13485 12.2143 3.23664 11.9988L6.07768 6.07855L6.66995 17.3279Z" fill="#01579B"/>
|
||||
<path d="M17.2066 6.67088L14.1289 3.59242C13.8605 3.32266 13.3 3 12.8267 3C12.4195 3 12.0203 3.08199 11.7612 3.2367L6.0791 6.07846L17.2066 6.67088Z" fill="#40C4FF"/>
|
||||
<path d="M10.3389 20.9986H17.7978V17.8011L12.2334 16.0251L7.14355 17.8011L10.3389 20.9986Z" fill="#40C4FF"/>
|
||||
<path d="M6.0791 15.6709C6.0791 16.6204 6.19808 16.8544 6.67137 17.3292L7.14465 17.8026H17.7989L12.5901 11.8824L6.0791 6.07983V15.6709Z" fill="#29B6F6"/>
|
||||
<path d="M15.5491 6.07855H6.07812L17.7979 17.8013H20.9945V10.4595L17.2069 6.67097C16.6755 6.13674 16.2022 6.07855 15.5491 6.07855Z" fill="#01579B"/>
|
||||
<path opacity="0.2" d="M6.78938 17.4469C6.31609 16.9709 6.19711 16.5027 6.19711 15.671V6.19756L6.07812 6.07855V15.6696C6.07945 16.5027 6.07945 16.7328 6.78938 17.4469L7.145 17.8026L6.78938 17.4469Z" fill="white"/>
|
||||
<path opacity="0.2" d="M20.8763 10.3419V17.6836H17.6797L17.7987 17.8013H20.9953V10.4609L20.8763 10.3419Z" fill="#263238"/>
|
||||
<path opacity="0.2" d="M17.2066 6.67097C16.6196 6.08384 16.1384 6.07855 15.4311 6.07855H6.0791L6.19808 6.19756H15.4324C15.7841 6.19756 16.6765 6.13806 17.2066 6.67097Z" fill="white"/>
|
||||
<path opacity="0.2" d="M20.8771 10.3418L17.2071 6.67088L14.1294 3.59242C13.8611 3.32266 13.3005 3 12.8273 3C12.4201 3 12.0208 3.08199 11.7617 3.2367L6.07963 6.07846L3.2386 11.9987C3.1368 12.2142 3.00195 12.5885 3.00195 12.8278C3.00195 13.3448 3.22934 13.8738 3.59422 14.2493L6.43129 17.066C6.49871 17.1493 6.57803 17.2339 6.67322 17.3278L6.7922 17.4468L7.14783 17.8025L10.2255 20.881L10.3445 21H17.6844H17.8034V17.8025H21V17.7946V10.4608L20.8771 10.3418Z" fill="url(#paint0_radial_2689_27562)"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_2689_27562" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(12.0003 11.9995) scale(8.99837 9.00066)">
|
||||
<stop stop-color="white" stop-opacity="0.1"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
5
src/lib/components/marketing/(assets)/icons/deno.svg
Normal file
|
After Width: | Height: | Size: 12 KiB |
13
src/lib/components/marketing/(assets)/icons/flutter.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.647 3L5 11.7147L7.67631 14.4119L18.9996 3H13.647Z" fill="#47C5FB"/>
|
||||
<path d="M13.5868 11.0365L8.95703 15.7025L11.6432 18.4501L14.3146 15.7578L18.9998 11.0365H13.5868Z" fill="#47C5FB"/>
|
||||
<path d="M11.6427 18.4501L13.6763 20.4995H18.9993L14.3141 15.7578L11.6427 18.4501Z" fill="#00569E"/>
|
||||
<path d="M8.92627 15.7324L11.6026 13.0351L14.314 15.7578L11.6426 18.4501L8.92627 15.7324Z" fill="#00B5F8"/>
|
||||
<path d="M11.6427 18.4501L13.8671 17.7061L14.0881 15.9855L11.6427 18.4501Z" fill="url(#paint0_linear_2689_27555)" fill-opacity="0.8"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_2689_27555" x1="11.688" y1="16.793" x2="13.4506" y2="17.4232" gradientUnits="userSpaceOnUse">
|
||||
<stop/>
|
||||
<stop offset="1" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 850 B |
7
src/lib/components/marketing/(assets)/icons/go.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.89654 10.1159C1.84998 10.1159 1.83834 10.0926 1.86162 10.0577L2.10606 9.74344C2.12934 9.70852 2.18754 9.68524 2.2341 9.68524H6.38966C6.43622 9.68524 6.44786 9.72016 6.42458 9.75508L6.2267 10.0577C6.20342 10.0926 6.14522 10.1276 6.1103 10.1276L1.89654 10.1159Z" fill="#C3C3C6"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.138846 11.1874C0.0922852 11.1874 0.0806449 11.1641 0.103925 11.1292L0.34837 10.8149C0.371651 10.78 0.429852 10.7567 0.476413 10.7567H5.78435C5.83092 10.7567 5.8542 10.7916 5.84256 10.8265L5.74943 11.1059C5.73779 11.1525 5.69123 11.1757 5.64467 11.1757L0.138846 11.1874Z" fill="#C3C3C6"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.95586 12.2578C2.9093 12.2578 2.89766 12.2229 2.92094 12.188L3.08391 11.897C3.10719 11.8621 3.15375 11.8271 3.20031 11.8271H5.52835C5.57491 11.8271 5.59819 11.8621 5.59819 11.9086L5.57491 12.188C5.57491 12.2346 5.52835 12.2695 5.49343 12.2695L2.95586 12.2578Z" fill="#C3C3C6"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.0384 9.90696C14.305 10.0932 13.8045 10.2329 13.0828 10.4191C12.9082 10.4657 12.8966 10.4773 12.7453 10.3027C12.5706 10.1048 12.4426 9.9768 12.1982 9.8604C11.4648 9.49955 10.7548 9.60431 10.0913 10.035C9.29975 10.5472 8.89234 11.3038 8.90398 12.2466C8.91562 13.1779 9.55583 13.9461 10.4754 14.0742C11.2669 14.1789 11.9304 13.8996 12.4542 13.3059C12.559 13.1779 12.6521 13.0382 12.7685 12.8752C12.3495 12.8752 11.8257 12.8752 10.522 12.8752C10.2775 12.8752 10.2193 12.7239 10.3008 12.526C10.4521 12.1652 10.7315 11.5599 10.8945 11.2572C10.9294 11.1874 11.0109 11.071 11.1855 11.071H15.4225C15.3992 11.3853 15.3992 11.6996 15.3527 12.0138C15.2246 12.8519 14.9103 13.6202 14.3982 14.2953C13.5601 15.4011 12.4659 16.0879 11.0807 16.2742C9.93996 16.4255 8.8807 16.2043 7.94948 15.5059C7.0881 14.8541 6.59921 13.9927 6.47117 12.9218C6.31985 11.653 6.69234 10.5123 7.46059 9.51119C8.28705 8.42865 9.38123 7.74188 10.7199 7.49743C11.814 7.29955 12.8617 7.42759 13.8045 8.06781C14.4214 8.47521 14.8638 9.03394 15.1548 9.70908C15.2246 9.81384 15.1781 9.87204 15.0384 9.90696Z" fill="#C3C3C6"/>
|
||||
<path d="M18.8913 16.3441C17.8321 16.3208 16.8659 16.0181 16.0511 15.3197C15.3643 14.7261 14.9337 13.9695 14.794 13.0732C14.5844 11.7578 14.9453 10.5938 15.7368 9.55782C16.5866 8.44035 17.6109 7.85834 18.9961 7.6139C20.1834 7.40437 21.3009 7.52078 22.3136 8.20755C23.2331 8.83612 23.8035 9.68586 23.9548 10.8033C24.1527 12.3747 23.6987 13.6552 22.6162 14.7494C21.8479 15.5293 20.9051 16.0181 19.8225 16.2393C19.5083 16.2975 19.194 16.3091 18.8913 16.3441ZM21.6617 11.6414C21.6501 11.4901 21.6501 11.3737 21.6268 11.2573C21.4173 10.1049 20.358 9.45305 19.2522 9.70914C18.1696 9.95358 17.4712 10.6404 17.2151 11.7345C17.0056 12.6425 17.4479 13.5621 18.286 13.9345C18.9263 14.2139 19.5665 14.179 20.1834 13.8647C21.103 13.3874 21.6035 12.6425 21.6617 11.6414Z" fill="#C3C3C6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="3" y="3" width="18" height="18" rx="1" fill="#FFCA28"/>
|
||||
<path d="M14.3158 18.1646L15.6178 17.2415C15.7198 17.585 16.366 18.4007 17.1822 18.4007C17.9984 18.4007 18.3773 17.9231 18.3773 17.6064C18.3773 16.7435 17.5439 16.4393 17.1436 16.2931C17.0783 16.2693 17.0246 16.2497 16.9879 16.2326C16.969 16.2238 16.9405 16.2121 16.9039 16.1971C16.4587 16.0149 14.8162 15.3425 14.8162 13.3936C14.8162 11.2469 16.7498 11 17.187 11C17.4731 11 18.8486 11.0376 19.5336 12.4168L18.2704 13.3614C17.9935 12.7603 17.5334 12.5617 17.2502 12.5617C16.5506 12.5617 16.4049 13.1112 16.4049 13.3614C16.4049 14.0632 17.1649 14.3778 17.8067 14.6434C17.9746 14.7129 18.1345 14.7791 18.2704 14.8479C18.97 15.2021 20 15.7817 20 17.6064C20 18.5204 19.2845 20 17.4834 20C15.064 20 14.4227 18.4436 14.3158 18.1646Z" fill="#3E3E3E"/>
|
||||
<path d="M8 18.3479L9.35706 17.4253C9.46339 17.7686 9.87659 18.4015 10.4761 18.4015C11.0757 18.4015 11.3825 17.7417 11.3825 17.4253V11.203H13.0515V17.4253C13.0785 18.2835 12.6342 20 10.6736 20C8.87095 20 8.12153 18.8521 8 18.3479Z" fill="#3E3E3E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
28
src/lib/components/marketing/(assets)/icons/kotlin.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 21.0001L12.03 11.9701L21 21.0001H3Z" fill="url(#paint0_linear_2689_27616)"/>
|
||||
<path d="M3 3H12.03L3 12.5192V3Z" fill="url(#paint1_linear_2689_27616)"/>
|
||||
<path d="M12.03 3L3 12.51V21L12.03 11.97L21 3H12.03Z" fill="url(#paint2_linear_2689_27616)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_2689_27616" x1="7.7877" y1="25.2043" x2="16.2921" y2="16.7002" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.097" stop-color="#0095D5"/>
|
||||
<stop offset="0.301" stop-color="#238AD9"/>
|
||||
<stop offset="0.621" stop-color="#557BDE"/>
|
||||
<stop offset="0.864" stop-color="#7472E2"/>
|
||||
<stop offset="1" stop-color="#806EE3"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_2689_27616" x1="4.2627" y1="6.6177" x2="9.20189" y2="1.6785" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.118" stop-color="#0095D5"/>
|
||||
<stop offset="0.418" stop-color="#3C83DC"/>
|
||||
<stop offset="0.696" stop-color="#6D74E1"/>
|
||||
<stop offset="0.833" stop-color="#806EE3"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_2689_27616" x1="-0.0306008" y1="19.5492" x2="16.7193" y2="2.79928" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.107" stop-color="#C757BC"/>
|
||||
<stop offset="0.214" stop-color="#D0609A"/>
|
||||
<stop offset="0.425" stop-color="#E1725C"/>
|
||||
<stop offset="0.605" stop-color="#EE7E2F"/>
|
||||
<stop offset="0.743" stop-color="#F58613"/>
|
||||
<stop offset="0.823" stop-color="#F88909"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
14
src/lib/components/marketing/(assets)/icons/lynx.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.87827 5.24328L3.76157 6.77958C3.53153 6.94653 3.37226 7.19742 3.31632 7.48095L3.10937 8.52978C3.0984 8.58537 3.07407 8.6373 3.03858 8.68076L2.07808 10.0075C1.94876 10.166 1.95188 10.5872 2.30609 10.8569C2.44191 10.9816 2.62351 11.2613 2.83008 11.5794C3.26743 12.2529 3.81668 13.0987 4.2803 13.0108C4.93636 12.768 5.73945 12.6903 6.35603 13.0108C7.55462 14.1011 7.26033 15.1064 6.83841 16.5477C6.66863 17.1277 6.47818 17.7782 6.35603 18.5333C6.93172 16.3256 8.22625 13.7616 10.5605 12.8915C10.1399 12.5295 9.28165 12.1932 8.52215 12.1123C8.52215 12.1123 10.8554 10.0075 13.7333 9.04033C11.7243 4.00356 8.40813 1.59656 8.40813 1.59656C8.23915 1.37634 7.8979 1.44858 7.82749 1.71948C7.77092 2.51574 7.67714 3.05719 7.52234 3.56757L6.35603 2.14952C6.2342 1.99476 5.99063 2.08412 5.99185 2.28313C6.18933 3.43983 6.16161 4.0891 5.87827 5.24328ZM6.69926 5.13755L6.70622 5.13708C6.72146 5.13605 6.73646 5.13396 6.75111 5.13088L6.69926 5.13755ZM8.27722 2.54048C9.07652 3.99567 9.4386 4.82238 9.56141 6.36521C8.7112 5.85632 8.34073 5.72682 7.7155 5.73003C8.08024 4.56144 8.19166 3.85776 8.27722 2.54048Z" fill="white"/>
|
||||
<path d="M13.748 13.1738C10.012 13.9851 7.88982 15.2068 6.26672 18.5333C9.18031 13.8944 18.0001 14.7241 18.0001 14.7241C17.8353 13.9663 16.0817 12.5213 14.9284 11.635C14.9284 11.635 15.8588 10.5495 17.9158 10C17.9158 10 13.961 10.2175 11.6588 11.3971C12.4046 11.7707 13.36 12.4011 13.748 13.1738Z" fill="url(#paint0_linear_8754_790)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_8754_790" x1="18" y1="10" x2="6.5" y2="18" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#78E6E5"/>
|
||||
<stop offset="0.100938" stop-color="#78D9EA"/>
|
||||
<stop offset="0.227353" stop-color="#7AC9F0"/>
|
||||
<stop offset="0.369246" stop-color="#85BADB"/>
|
||||
<stop offset="0.475618" stop-color="#B5928C"/>
|
||||
<stop offset="0.622562" stop-color="#E97452"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
3
src/lib/components/marketing/(assets)/icons/net.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.5367 13.7707C2.44246 13.7689 2.35244 13.789 2.27079 13.823L2.27077 13.823L2.26809 13.8241C2.18619 13.8601 2.11066 13.9117 2.04778 13.9776C1.98442 14.0411 1.93372 14.1166 1.90025 14.2008L1.90024 14.2008L1.89982 14.2019C1.86787 14.2841 1.85032 14.3715 1.85012 14.4602M2.5367 13.7707C2.62683 13.7709 2.71694 13.7882 2.80221 13.8257C2.88344 13.8613 2.95839 13.9123 3.02096 13.9775C3.08783 14.041 3.13744 14.1165 3.17282 14.198L3.17349 14.1995L3.17348 14.1995C3.20882 14.2835 3.22627 14.3729 3.22627 14.4633C3.22627 14.5537 3.20882 14.6431 3.17348 14.7271C3.13908 14.8088 3.08878 14.8848 3.02167 14.9483C2.95873 15.0122 2.88363 15.063 2.80079 15.0976L2.74298 14.9591L2.80079 15.0976C2.7175 15.1323 2.62807 15.1501 2.5378 15.1499M2.5367 13.7707C2.53724 13.7707 2.53778 13.7707 2.53832 13.7707L2.53515 13.9207V13.7707C2.53567 13.7707 2.53619 13.7707 2.5367 13.7707ZM2.5378 15.1499C2.44662 15.1515 2.35607 15.1342 2.27193 15.099C2.1879 15.0639 2.11207 15.0118 2.0493 14.9459C1.98586 14.8824 1.93594 14.8076 1.90138 14.7256C1.86625 14.6421 1.84837 14.5522 1.85012 14.4602M2.5378 15.1499C2.53715 15.1499 2.5365 15.1499 2.53585 15.1499L2.53667 14.9999L2.53973 15.1499C2.53908 15.1499 2.53844 15.1499 2.5378 15.1499ZM1.85012 14.4602C1.85013 14.4597 1.85014 14.4591 1.85015 14.4586L2.00011 14.4618H1.85011C1.85011 14.4613 1.85011 14.4607 1.85012 14.4602ZM5.46673 14.9062V9.91575C5.46994 9.80356 5.47033 9.69143 5.46804 9.57937L8.96337 14.9876L9.0077 15.0562H9.08935H10.0849H10.2349V14.9062V8V7.85H10.0849H9.27631H9.12631V8V12.8549C9.12306 13.0013 9.12426 13.1479 9.12979 13.2945L5.68624 7.91909L5.64198 7.85H5.55993H4.5081H4.3581V8V14.9062V15.0562H4.5081H5.31673H5.46673V14.9062ZM15.7176 14.1483L15.7185 13.9974H15.5676H12.86V11.9046H15.2104H15.3604V11.7546V11.0261V10.8761H15.2104H12.86V8.88158H15.3928H15.5428V8.73158V8V7.85H15.3928H11.8816H11.7316V8V14.9062V15.0562H11.8816H15.563H15.7121L15.713 14.9071L15.7176 14.1483ZM16.1862 7.85H16.0362V8V8.73158V8.88158H16.1862H18.0274V14.9062V15.0562H18.1774H18.986H19.136V14.9062V8.88158H21H21.15V8.73158V8V7.85H21H16.1862Z" fill="#512BD4" stroke="#512BD4" stroke-width="0.3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
3
src/lib/components/marketing/(assets)/icons/nextjs.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.3451 2.00538C11.3021 2.00929 11.1652 2.02297 11.042 2.03275C8.20137 2.28882 5.54057 3.82134 3.85533 6.17681C2.91691 7.48649 2.31672 8.9721 2.08993 10.5457C2.00978 11.095 2 11.2572 2 12.002C2 12.7467 2.00978 12.909 2.08993 13.4582C2.63343 17.2133 5.30596 20.3683 8.9306 21.5372C9.57967 21.7464 10.2639 21.8891 11.042 21.9751C11.3451 22.0083 12.6549 22.0083 12.958 21.9751C14.3011 21.8265 15.4389 21.4942 16.5611 20.9215C16.7331 20.8335 16.7664 20.81 16.7429 20.7905C16.7273 20.7788 15.9941 19.7955 15.1144 18.607L13.5152 16.4471L11.5112 13.4817C10.4086 11.8514 9.50147 10.5183 9.49365 10.5183C9.48583 10.5163 9.47801 11.8338 9.4741 13.4426C9.46823 16.2594 9.46628 16.3728 9.43109 16.4392C9.38025 16.535 9.34115 16.5741 9.25904 16.6171C9.19648 16.6484 9.14174 16.6543 8.84653 16.6543H8.50831L8.41838 16.5976C8.35973 16.5604 8.31672 16.5116 8.28739 16.4549L8.24633 16.3669L8.25024 12.4476L8.25611 8.52642L8.31672 8.45018C8.348 8.40913 8.41447 8.35635 8.46139 8.33094C8.54154 8.29185 8.57282 8.28794 8.91105 8.28794C9.30987 8.28794 9.37634 8.30358 9.47996 8.41695C9.50929 8.44823 10.5943 10.0824 11.8925 12.0508C13.1906 14.0193 14.9658 16.707 15.8377 18.0265L17.4213 20.425L17.5015 20.3722C18.2111 19.9109 18.9619 19.2541 19.5562 18.5699C20.8211 17.1175 21.6364 15.3465 21.9101 13.4582C21.9902 12.909 22 12.7467 22 12.002C22 11.2572 21.9902 11.095 21.9101 10.5457C21.3666 6.7906 18.694 3.63564 15.0694 2.4667C14.4301 2.2595 13.7498 2.1168 12.9873 2.03079C12.7996 2.01125 11.5073 1.98974 11.3451 2.00538ZM15.4389 8.05337C15.5327 8.10028 15.609 8.1902 15.6364 8.28403C15.652 8.33485 15.6559 9.42169 15.652 11.871L15.6461 15.3856L15.0264 14.4356L14.4047 13.4856V10.9308C14.4047 9.279 14.4125 8.35049 14.4242 8.30553C14.4555 8.19607 14.5239 8.11006 14.6178 8.05923C14.6979 8.01818 14.7273 8.01427 15.0342 8.01427C15.3236 8.01427 15.3744 8.01818 15.4389 8.05337Z" fill="#C3C3C6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
4
src/lib/components/marketing/(assets)/icons/node.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.2666 3.19203C11.8025 2.93541 11.1975 2.93657 10.733 3.19203C8.40657 4.45431 6.08015 5.71698 3.75333 6.97868C3.30057 7.21287 2.99519 7.69092 3.00006 8.18711V15.8139C2.99679 16.3198 3.31791 16.8025 3.78236 17.0334C4.4507 17.383 5.10002 17.7681 5.78044 18.0944C6.56641 18.4741 7.54974 18.5581 8.34532 18.1621C8.99111 17.8339 9.27794 17.104 9.27714 16.4331C9.28234 13.9161 9.27794 11.399 9.27914 8.88191C9.29449 8.77004 9.20908 8.65048 9.08498 8.65317C8.78768 8.64856 8.48997 8.65048 8.19266 8.6524C8.0803 8.64195 7.97068 8.73369 7.97915 8.84473C7.97515 11.3456 7.97995 13.8472 7.97675 16.3484C7.98322 16.6944 7.7455 17.0269 7.40636 17.1438C6.62309 17.4137 4.38745 15.9865 4.38745 15.9865C4.3054 15.9491 4.2533 15.8617 4.26134 15.7748C4.26134 13.2585 4.26175 10.7421 4.26134 8.22622C4.25007 8.1248 4.31365 8.03344 4.4084 7.99203C6.72714 6.73719 9.04468 5.4792 11.3634 4.22359C11.4439 4.17074 11.5562 4.1709 11.6366 4.22398C13.9553 5.4792 16.2733 6.73603 18.5924 7.99094C18.6875 8.03229 18.7483 8.12518 18.7387 8.22622C18.7383 10.7421 18.7395 13.2585 18.7379 15.7744C18.7447 15.8634 18.698 15.9497 18.6134 15.9888C16.3163 17.2368 13.993 18.4446 11.7167 19.7289C11.6174 19.7849 11.5049 19.8484 11.3937 19.7867C10.795 19.4611 10.2037 19.1229 9.60707 18.7942C9.54222 18.7544 9.45962 18.7374 9.39196 18.7819C9.12442 18.9205 8.87287 19.0327 8.5657 19.1523C8.13424 19.3202 8.2032 19.3889 8.59225 19.6117C9.29001 20 9.98891 20.3867 10.6866 20.7753C11.1459 21.0571 11.7631 21.0772 12.2372 20.8167C14.564 19.556 16.89 18.2938 19.2173 17.0331C19.6805 16.8009 20.0032 16.3201 20 15.8139V8.18711C20.0044 7.70098 19.7107 7.23146 19.2716 6.99381C16.9371 5.72538 14.6015 4.4597 12.2666 3.19203Z" fill="#8CC84B"/>
|
||||
<path d="M15.7774 8.9183C14.8642 8.43794 13.7777 8.41237 12.7629 8.47513C12.0298 8.54635 11.2587 8.74527 10.7245 9.26198C10.1767 9.78144 10.0574 10.6202 10.3176 11.2983C10.5041 11.7775 10.9735 12.0891 11.4589 12.2539C12.0842 12.4709 12.7409 12.538 13.3979 12.6052C13.9971 12.6664 14.5964 12.7276 15.1723 12.9027C15.4076 12.9794 15.6816 13.0966 15.7536 13.3482C15.8201 13.6463 15.7472 13.9927 15.5011 14.1998C14.7193 14.8081 12.5448 14.7149 11.7724 14.2361C11.4601 14.0321 11.3255 13.671 11.2708 13.327C11.2648 13.2197 11.177 13.1214 11.0585 13.1295C10.762 13.126 10.4655 13.1268 10.169 13.1291C10.0655 13.1206 9.95796 13.193 9.95229 13.2968C9.89137 14.8728 11.3636 15.5599 12.7448 15.7112C13.534 15.7851 14.3405 15.7809 15.1176 15.6144C15.7017 15.4836 16.2874 15.2429 16.6895 14.8005C17.1854 14.2628 17.2829 13.4624 17.0605 12.7927C16.8905 12.2931 16.4046 11.9726 15.9079 11.8077C15.2325 11.58 14.4321 11.4576 13.8204 11.4003C12.9312 11.317 11.8746 11.351 11.6229 10.7766C11.5226 10.4758 11.608 10.1023 11.8891 9.91728C12.633 9.42117 14.1469 9.48705 14.9173 9.85766C15.2711 10.0318 15.4761 10.3895 15.5607 10.7506C15.5763 10.8567 15.6489 10.9674 15.7738 10.9627C16.0683 10.9685 16.3628 10.9643 16.6572 10.9647C16.7584 10.9717 16.8691 10.9155 16.8889 10.8137C16.8764 10.059 16.4844 9.2864 15.7774 8.9183Z" fill="#8CC84B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
3
src/lib/components/marketing/(assets)/icons/nuxt.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.2202 19H20.655C20.8912 19 21.1232 18.9353 21.3277 18.8125C21.5322 18.6896 21.702 18.5128 21.82 18.3C21.938 18.0871 22.0001 17.8457 22 17.5999C21.9999 17.3542 21.9376 17.1128 21.8194 16.9L16.8264 7.90008C16.7084 7.68728 16.5386 7.51055 16.3341 7.38768C16.1297 7.26483 15.8977 7.20012 15.6616 7.20012C15.4255 7.20012 15.1936 7.26483 14.9891 7.38768C14.7847 7.51055 14.6149 7.68728 14.4969 7.90008L13.2202 10.2028L10.724 5.69984C10.6059 5.48706 10.4361 5.31036 10.2316 5.18751C10.027 5.06468 9.79504 5 9.55891 5C9.32278 5 9.0908 5.06468 8.88629 5.18751C8.68176 5.31036 8.51191 5.48706 8.3938 5.69984L2.18059 16.9C2.06239 17.1128 2.0001 17.3542 2 17.5999C1.9999 17.8457 2.06198 18.0871 2.18 18.3C2.29803 18.5128 2.46783 18.6896 2.67233 18.8125C2.87684 18.9353 3.10883 19 3.34498 19H8.01196C9.86107 19 11.2247 18.1548 12.163 16.5057L14.4411 12.4L15.6613 10.2028L19.3233 16.8028H14.4411L13.2202 19ZM7.93587 16.8005L4.67891 16.7998L9.56109 8.00034L11.9971 12.4L10.3661 15.3407C9.74296 16.4107 9.03505 16.8005 7.93587 16.8005Z" fill="#00DC82"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
5
src/lib/components/marketing/(assets)/icons/php.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.5811 7H12.1084L11.6768 9.31387H13.0491C13.8017 9.3301 14.3624 9.4997 14.7314 9.82268C15.1077 10.1457 15.2184 10.7596 15.0634 11.6641L14.3219 15.6982H12.7724L13.4808 11.8458C13.5545 11.4419 13.5323 11.1553 13.4144 10.9857C13.2964 10.8161 13.0418 10.7313 12.6507 10.7313L11.4222 10.7191L10.5147 15.6982H8.98735L10.5811 7Z" fill="#8892BF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.58265 9.31391H6.54874C7.41932 9.32191 8.05016 9.59666 8.44129 10.1377C8.83241 10.6787 8.96146 11.4177 8.82865 12.3546C8.77707 12.7828 8.66264 13.2027 8.48556 13.6146C8.31578 14.0264 8.07982 14.3979 7.77724 14.7291C7.40825 15.149 7.01358 15.4155 6.59301 15.5286C6.17245 15.6418 5.73706 15.6982 5.28705 15.6982H3.95895L3.53838 18H2L3.58265 9.31391ZM4.2135 14.3293L4.87534 10.7071H5.0989C5.18013 10.7071 5.26491 10.703 5.35345 10.695C5.94379 10.687 6.43431 10.7475 6.82543 10.8767C7.22386 11.0058 7.35667 11.4945 7.22386 12.3425C7.06161 13.3521 6.7442 13.9416 6.27206 14.1112C5.79991 14.2729 5.20958 14.3494 4.50126 14.3414H4.34631C4.30204 14.3414 4.25777 14.3373 4.2135 14.3293Z" fill="#8892BF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.6696 9.31391H16.7035L15.1208 18H16.6592L17.0798 15.6982H18.4079C18.8579 15.6982 19.2933 15.6418 19.7139 15.5286C20.1344 15.4155 20.5291 15.149 20.8981 14.7291C21.2007 14.3979 21.4366 14.0264 21.6064 13.6146C21.7835 13.2027 21.8979 12.7828 21.9495 12.3546C22.0823 11.4177 21.9532 10.6787 21.5621 10.1377C21.171 9.59666 20.5402 9.32191 19.6696 9.31391ZM17.9962 10.7071L17.3343 14.3293C17.3786 14.3373 17.4229 14.3414 17.4672 14.3414H17.6221C18.3304 14.3494 18.9207 14.2729 19.3929 14.1112C19.865 13.9416 20.1824 13.3521 20.3447 12.3425C20.4775 11.4945 20.3447 11.0058 19.9463 10.8767C19.5551 10.7475 19.0646 10.687 18.4743 10.695C18.3858 10.703 18.301 10.7071 18.2197 10.7071H17.9962Z" fill="#8892BF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
14
src/lib/components/marketing/(assets)/icons/python.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.082 3C8.66956 3 7.52459 4.10863 7.52459 5.47619V7.19047H11.9508V7.66666H5.55737C4.14498 7.66666 3 8.77529 3 10.1429L3 13.8571C3 15.2247 4.14498 16.3333 5.55737 16.3333H7.03278V14.2381C7.03278 12.8705 8.17776 11.7619 9.59016 11.7619H14.3115C15.5066 11.7619 16.4754 10.8238 16.4754 9.66666V5.47619C16.4754 4.10863 15.3304 3 13.918 3H10.082ZM9.4918 6.04762C9.98071 6.04762 10.377 5.66386 10.377 5.19047C10.377 4.71709 9.98071 4.33333 9.4918 4.33333C9.00289 4.33333 8.60655 4.71709 8.60655 5.19047C8.60655 5.66386 9.00289 6.04762 9.4918 6.04762Z" fill="url(#paint0_linear_2689_27561)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9176 20.9999C15.33 20.9999 16.475 19.8913 16.475 18.5237V16.8094H12.0488L12.0488 16.3332L18.4422 16.3332C19.8546 16.3332 20.9996 15.2246 20.9996 13.857V10.1428C20.9996 8.77519 19.8546 7.66657 18.4422 7.66657L16.9668 7.66656V9.7618C16.9668 11.1294 15.8218 12.238 14.4094 12.238L9.6881 12.238C8.493 12.238 7.52417 13.1761 7.52417 14.3332L7.52417 18.5237C7.52417 19.8913 8.66915 20.9999 10.0815 20.9999H13.9176ZM14.5078 17.9523C14.0189 17.9523 13.6225 18.336 13.6225 18.8094C13.6225 19.2828 14.0189 19.6666 14.5078 19.6666C14.9967 19.6666 15.393 19.2828 15.393 18.8094C15.393 18.336 14.9967 17.9523 14.5078 17.9523Z" fill="url(#paint1_linear_2689_27561)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_2689_27561" x1="9.7377" y1="3" x2="9.7377" y2="16.3333" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#327EBD"/>
|
||||
<stop offset="1" stop-color="#1565A7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_2689_27561" x1="14.2619" y1="7.66656" x2="14.2619" y2="20.9999" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFDA4B"/>
|
||||
<stop offset="1" stop-color="#F9C600"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.4822 5.05712C17.9863 5.91947 17.5597 8.46304 17.2202 9.83468C17.6278 9.95124 18.1261 10.1085 18.6255 10.317H15.9759C15.5458 10.2282 15.0946 10.1539 14.6276 10.0952C14.7242 10.2458 14.8191 10.3975 14.9123 10.5501C14.6785 10.6779 14.4777 10.8527 14.3244 11.0606C14.1066 10.6999 13.8792 10.3449 13.6421 9.99644C12.5507 9.91372 11.4525 9.91391 10.361 9.99597C9.74422 10.8948 9.19653 11.8397 8.72265 12.8206C9.19887 13.8035 9.75053 14.7502 10.3703 15.6505C11.4609 15.7208 12.5581 15.7216 13.6484 15.6441C13.7678 15.4657 13.8851 15.2858 14 15.1043V16.4878C13.5299 17.1558 13.0495 17.7593 12.5687 18.2822C12.9101 18.6088 13.4298 19.0964 14 19.4789V20.3481C13.2359 19.9288 12.5312 19.3084 12.0332 18.8307C10.995 19.829 8.99836 21.4282 7.48996 20.5633C5.99158 19.7037 6.42995 17.2381 6.77819 15.8502C5.3905 15.4563 3 14.5323 3 12.8022C3 11.0671 5.39299 10.2179 6.78894 9.82359C6.44199 8.44335 5.9805 5.94196 7.47698 5.08048C8.97981 4.2154 10.9827 5.85358 12.0084 6.83128C13.0371 5.84374 14.9852 4.19852 16.4822 5.05712ZM7.52374 16.0375C7.26755 17.0599 6.75686 19.2601 7.87417 19.9008C8.99671 20.5444 10.8452 18.9098 11.4945 18.2851C10.9689 17.7242 10.4474 17.0836 9.94943 16.3867C9.07714 16.3164 8.26101 16.1997 7.52374 16.0375ZM6.99542 10.5602C5.96524 10.8498 3.76889 11.5087 3.76889 12.8022C3.76889 14.0965 6.00222 14.834 6.98451 15.1136C7.21186 14.3765 7.51155 13.6026 7.87274 12.8208C7.51617 12.0505 7.22071 11.2887 6.99542 10.5602ZM11.4695 7.3771C10.7248 6.66922 8.9841 5.0965 7.86222 5.74227C6.74155 6.38735 7.25475 8.52207 7.53426 9.63529C8.27925 9.46742 9.08965 9.3421 9.93621 9.26407C10.4299 8.57123 10.9466 7.9355 11.4695 7.3771ZM13.0679 9.19515C12.7185 8.73228 12.3633 8.30561 12.0086 7.92354C11.6484 8.31005 11.2901 8.73608 10.9404 9.19468C11.6492 9.16169 12.3591 9.16185 13.0679 9.19515ZM7.74193 10.3724C7.89839 10.8739 8.08997 11.3931 8.3139 11.9213C8.63826 11.2961 8.99197 10.686 9.3738 10.0938C8.80318 10.1647 8.25551 10.2581 7.74193 10.3724ZM7.73134 15.2999C8.24476 15.4111 8.80071 15.4997 9.39021 15.5652C9.00269 14.9673 8.64362 14.3513 8.31478 13.7197C8.08607 14.2592 7.89026 14.7896 7.73134 15.2999ZM10.9469 16.446C11.3019 16.9112 11.6654 17.3438 12.0299 17.7349C12.3821 17.3491 12.7361 16.916 13.0866 16.4423C12.3739 16.4739 11.6597 16.4738 10.9469 16.446ZM16.4757 9.64321C16.7209 8.64918 17.2204 6.36319 16.0982 5.71954C14.9869 5.08218 13.3017 6.65358 12.5474 7.3767C13.0619 7.9279 13.5743 8.56473 14.069 9.2651C14.918 9.34432 15.729 9.47186 16.4757 9.64321ZM12 11.2038C12.8877 11.2038 13.6073 11.9195 13.6073 12.8022C13.6073 13.685 12.8877 14.4007 12 14.4007C11.1123 14.4007 10.3927 13.685 10.3927 12.8022C10.3927 11.9195 11.1123 11.2038 12 11.2038Z" fill="#53C1DE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9 10.817C15.1268 10.817 14.5 11.4326 14.5 12.192V20.442C14.5 21.2014 15.1268 21.817 15.9 21.817H20.1C20.8732 21.817 21.5 21.2014 21.5 20.442V12.192C21.5 11.4326 20.8732 10.817 20.1 10.817H15.9ZM18 20.442C18.3866 20.442 18.7 20.1342 18.7 19.7545C18.7 19.3748 18.3866 19.067 18 19.067C17.6134 19.067 17.3 19.3748 17.3 19.7545C17.3 20.1342 17.6134 20.442 18 20.442Z" fill="#53C1DE"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
4
src/lib/components/marketing/(assets)/icons/react.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.6073 11.9852C13.6073 11.1024 12.8877 10.3868 12 10.3868C11.1123 10.3868 10.3927 11.1024 10.3927 11.9852C10.3927 12.868 11.1123 13.5836 12 13.5836C12.8877 13.5836 13.6073 12.868 13.6073 11.9852Z" fill="#53C1DE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.2202 9.01766C17.5597 7.64602 17.9863 5.10245 16.4822 4.2401C14.9852 3.38151 13.0371 5.02672 12.0084 6.01427C10.9827 5.03657 8.97981 3.39838 7.47698 4.26347C5.9805 5.12494 6.44199 7.62634 6.78894 9.00657C5.39299 9.40087 3 10.2501 3 11.9852C3 13.7153 5.3905 14.6393 6.77819 15.0332C6.42995 16.421 5.99158 18.8867 7.48996 19.7462C8.99836 20.6112 10.995 19.012 12.0332 18.0137C13.0685 19.007 14.998 20.6167 16.4953 19.7547C17.9974 18.89 17.6061 16.3805 17.2592 14.9923C18.6044 14.5975 21 13.6937 21 11.9852C21 10.2668 18.5942 9.41063 17.2202 9.01766ZM17.0497 14.2566C16.8219 13.5394 16.5144 12.7768 16.1383 11.989C16.4973 11.2198 16.7928 10.467 17.0143 9.75439C18.0215 10.0448 20.2311 10.7085 20.2311 11.9852C20.2311 13.2738 18.1108 13.9438 17.0497 14.2566ZM16.11 19.0929C14.9928 19.736 13.3333 18.1967 12.5687 17.4652C13.0759 16.9135 13.5828 16.2721 14.0775 15.56C14.9477 15.4832 15.7698 15.3576 16.5154 15.1863C16.7596 16.1682 17.2321 18.4469 16.11 19.0929ZM7.87417 19.0837C6.75686 18.4431 7.26755 16.2428 7.52374 15.2205C8.26101 15.3827 9.07714 15.4994 9.94943 15.5697C10.4474 16.2666 10.9689 16.9071 11.4945 17.4681C10.8452 18.0928 8.99671 19.7274 7.87417 19.0837ZM3.76889 11.9852C3.76889 10.6917 5.96524 10.0328 6.99542 9.74314C7.22071 10.4717 7.51617 11.2335 7.87274 12.0038C7.51155 12.7856 7.21186 13.5595 6.98451 14.2966C6.00222 14.017 3.76889 13.2795 3.76889 11.9852ZM7.86222 4.92526C8.9841 4.27949 10.7248 5.8522 11.4695 6.56008C10.9466 7.11849 10.4299 7.75421 9.93621 8.44705C9.08965 8.52508 8.27925 8.65041 7.53426 8.81827C7.25475 7.70505 6.74155 5.57033 7.86222 4.92526ZM14.6276 9.27821C15.2019 9.3503 15.7521 9.44615 16.2688 9.56348C16.1137 10.0579 15.9204 10.5749 15.6927 11.1048C15.3626 10.482 15.0083 9.87176 14.6276 9.27821ZM12.0086 7.10653C12.3633 7.48859 12.7185 7.91526 13.0679 8.37813C12.3591 8.34483 11.6492 8.34467 10.9404 8.37766C11.2901 7.91907 11.6484 7.49303 12.0086 7.10653ZM8.3139 11.1043C8.08997 10.5761 7.89839 10.0568 7.74193 9.55539C8.25551 9.44108 8.80318 9.34768 9.3738 9.27678C8.99197 9.86902 8.63826 10.4791 8.3139 11.1043ZM9.39021 14.7481C8.80071 14.6827 8.24476 14.5941 7.73134 14.4829C7.89026 13.9726 8.08607 13.4422 8.31478 12.9027C8.64362 13.5343 9.00269 14.1503 9.39021 14.7481ZM12.0299 16.9178C11.6654 16.5267 11.3019 16.0942 10.9469 15.629C11.6597 15.6568 12.3739 15.6569 13.0866 15.6252C12.7361 16.099 12.3821 16.5321 12.0299 16.9178ZM15.7 12.8752C15.9406 13.4205 16.1434 13.9481 16.3045 14.4498C15.7826 14.5682 15.2191 14.6636 14.6254 14.7344C15.009 14.1297 15.3689 13.5099 15.7 12.8752ZM13.6484 14.8271C12.5581 14.9046 11.4609 14.9038 10.3703 14.8335C9.75053 13.9332 9.19887 12.9864 8.72265 12.0035C9.19653 11.0227 9.74422 10.0778 10.361 9.17895C11.4525 9.0969 12.5507 9.09671 13.6421 9.17943C14.2536 10.0782 14.8005 11.0207 15.2854 11.9927C14.8062 12.9731 14.2557 13.9199 13.6484 14.8271ZM16.0982 4.90252C17.2204 5.54618 16.7209 7.83216 16.4757 8.82619C15.729 8.65484 14.918 8.5273 14.069 8.44808C13.5743 7.74772 13.0619 7.11088 12.5474 6.55968C13.3017 5.83656 14.9869 4.26516 16.0982 4.90252Z" fill="#53C1DE"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
3
src/lib/components/marketing/(assets)/icons/remix.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.8547 2.5C17.628 2.5 20 4.82627 20 8.54224C20 11.3217 18.3308 13.1343 16.0759 13.4364C17.9794 13.8292 19.0921 14.947 19.2972 17.1524L19.3268 17.558L19.3527 17.9371L19.3751 18.2918L19.3907 18.5592L19.4074 18.8747L19.416 19.0548L19.4284 19.3409L19.4383 19.6111L19.4432 19.7664L19.4499 20.0152L19.4557 20.2998L19.4578 20.4372L19.4615 20.8357L19.4627 21.2514L19.4628 21.5H14.5404L14.5406 21.3963L14.5424 21.195L14.5453 20.9988L14.5538 20.5237L14.556 20.3644L14.5577 20.1147L14.5574 19.955L14.556 19.7875L14.554 19.656L14.55 19.472L14.5441 19.2768L14.5363 19.0693L14.5263 18.8482L14.5203 18.7321L14.5103 18.5509L14.4987 18.3604L14.4807 18.0913L14.4653 17.8774C14.4608 17.8115 14.4557 17.7471 14.4499 17.6842L14.4373 17.5604C14.2747 16.0995 13.7088 15.5024 12.7396 15.3033L12.6579 15.2876C12.6028 15.2777 12.5464 15.2691 12.4888 15.2615L12.4015 15.251C12.3868 15.2494 12.3721 15.2478 12.3572 15.2463L12.2671 15.2382L12.1751 15.2316L12.0813 15.2264L11.9866 15.2227L11.8901 15.2202L11.7918 15.219L4 15.2189V11.2613H11.9762C12.1066 11.2613 12.233 11.2587 12.3554 11.2536L12.4764 11.2475L12.5947 11.2397L12.7103 11.2301C12.7294 11.2283 12.7483 11.2265 12.7671 11.2246L12.8787 11.2122C12.9522 11.2033 13.0239 11.1932 13.0938 11.1819L13.1974 11.1639C14.4917 10.9236 15.1388 10.2201 15.1388 8.84717C15.1388 7.30644 14.0846 6.37267 11.9762 6.37267H4V2.5H12.8547ZM9.20477 18.5496C9.85059 18.5496 10.1208 18.9168 10.2171 19.2683L10.2298 19.3188L10.2402 19.3689L10.247 19.4084L10.2499 19.428L10.2547 19.4666L10.2584 19.5044L10.2598 19.5229L10.2618 19.5593L10.2624 19.5771L10.2629 19.6117V21.5H4V18.5496H9.20477Z" fill="#C3C3C6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
120
src/lib/components/marketing/(assets)/icons/ruby.svg
Normal file
@@ -0,0 +1,120 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.9453 14.8806L6.66846 20.9999L19.9751 20.0945L21 6.6395L16.9453 14.8806Z" fill="url(#paint0_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.9968 20.0853L18.8531 12.1694L15.7378 16.2946L19.9968 20.0853Z" fill="url(#paint1_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0125 20.0853L11.6335 19.4258L6.71313 20.9828L20.0125 20.0853Z" fill="url(#paint2_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.72481 20.9846L8.81798 14.1082L4.21191 15.0958L6.72481 20.9846Z" fill="url(#paint3_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.5629 8.85884L15.3527 4.59161L13.9019 9.29522L20.5629 8.85884Z" fill="url(#paint4_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.1265 3.07011L15.0622 4.76826L13.1289 3.04733L18.1265 3.07011Z" fill="url(#paint5_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 17.4024L4.2837 15.0547L3.24529 12.2578L3 17.4024Z" fill="url(#paint6_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.17627 12.1694L4.22104 15.1412L8.76078 14.1199L13.9437 9.28961L15.4064 4.63073L13.1033 3L9.18769 4.46948C7.95404 5.6201 5.56016 7.89675 5.47385 7.93957C5.38845 7.9833 3.89307 10.8175 3.17627 12.1694Z" fill="white"/>
|
||||
<path d="M8.79175 14.091L13.9438 9.2896L13.9461 9.28226L15.7372 16.3173L8.79175 14.091Z" fill="url(#paint7_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.84488 6.8309C9.51858 4.17253 12.9654 2.60193 14.2882 3.94022C15.6101 5.27851 14.2082 8.53087 11.5345 11.1883C8.86083 13.8458 5.45671 15.5029 4.13485 14.1646C2.81208 12.8273 4.17119 9.48835 6.84488 6.8309Z" fill="url(#paint8_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.72485 20.9818L8.80167 14.0835L15.699 16.3055C13.2051 18.6505 10.4315 20.6328 6.72485 20.9818Z" fill="url(#paint9_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9529 9.27603L15.7235 16.3091C17.8067 14.1126 19.6764 11.7513 20.5921 8.83054L13.9529 9.27603Z" fill="url(#paint10_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.574 8.86614C21.2826 6.72159 21.4462 3.64506 18.1046 3.07385L15.3628 4.59253L20.574 8.86614Z" fill="url(#paint11_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 17.3714C3.09812 20.9108 5.64463 20.9635 6.72937 20.9946L4.22374 15.1266L3 17.3714Z" fill="#9E1209"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9626 9.28701C15.5634 10.2736 18.7896 12.2551 18.855 12.2916C18.9566 12.349 20.2459 10.1115 20.5384 8.84698L13.9626 9.28701Z" fill="url(#paint12_radial_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.79883 14.0835L11.5752 19.4549C13.2168 18.5621 14.5024 17.4743 15.6798 16.3091L8.79883 14.0835Z" fill="url(#paint13_radial_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.21271 15.1339L3.81934 19.8312C4.56158 20.8479 5.58272 20.9362 6.65384 20.857C5.87889 18.9229 4.33082 15.0556 4.21271 15.1339Z" fill="url(#paint14_linear_2689_27558)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.3464 4.60429L20.8619 5.38048C20.5676 4.12965 19.6636 3.32248 18.1228 3.07013L15.3464 4.60429Z" fill="url(#paint15_linear_2689_27558)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_2689_27558" x1="18.8145" y1="22.6369" x2="15.0012" y2="15.9231" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FB7655"/>
|
||||
<stop offset="0.41" stop-color="#E42B1E"/>
|
||||
<stop offset="0.99" stop-color="#990000"/>
|
||||
<stop offset="1" stop-color="#990000"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_2689_27558" x1="20.706" y1="16.9894" x2="15.8037" y2="13.7089" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#871101"/>
|
||||
<stop offset="0.99" stop-color="#911209"/>
|
||||
<stop offset="1" stop-color="#911209"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_2689_27558" x1="16.7906" y1="22.8407" x2="11.8885" y2="19.5603" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#871101"/>
|
||||
<stop offset="0.99" stop-color="#911209"/>
|
||||
<stop offset="1" stop-color="#911209"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_2689_27558" x1="6.51552" y1="14.6056" x2="7.2783" y2="19.5492" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.23" stop-color="#E57252"/>
|
||||
<stop offset="0.46" stop-color="#DE3B20"/>
|
||||
<stop offset="0.99" stop-color="#A60003"/>
|
||||
<stop offset="1" stop-color="#A60003"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_2689_27558" x1="16.3641" y1="5.32508" x2="17.2054" y2="8.94037" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.18" stop-color="#E46342"/>
|
||||
<stop offset="0.4" stop-color="#C82410"/>
|
||||
<stop offset="0.99" stop-color="#A80D00"/>
|
||||
<stop offset="1" stop-color="#A80D00"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_2689_27558" x1="13.809" y1="4.05142" x2="17.4191" y2="2.2514" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.54" stop-color="#C81F11"/>
|
||||
<stop offset="0.99" stop-color="#BF0905"/>
|
||||
<stop offset="1" stop-color="#BF0905"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_2689_27558" x1="3.35461" y1="13.3451" x2="3.65305" y2="16.3247" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.31" stop-color="#DE4024"/>
|
||||
<stop offset="0.99" stop-color="#BF190B"/>
|
||||
<stop offset="1" stop-color="#BF190B"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_2689_27558" x1="11.7337" y1="9.98895" x2="12.0148" y2="15.0347" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.23" stop-color="#E4714E"/>
|
||||
<stop offset="0.56" stop-color="#BE1A0D"/>
|
||||
<stop offset="0.99" stop-color="#A80D00"/>
|
||||
<stop offset="1" stop-color="#A80D00"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_2689_27558" x1="1.31436" y1="17.1304" x2="15.3061" y2="2.78299" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#BD0012"/>
|
||||
<stop offset="0.07" stop-color="white"/>
|
||||
<stop offset="0.17" stop-color="white"/>
|
||||
<stop offset="0.27" stop-color="#C82F1C"/>
|
||||
<stop offset="0.33" stop-color="#820C01"/>
|
||||
<stop offset="0.46" stop-color="#A31601"/>
|
||||
<stop offset="0.72" stop-color="#B31301"/>
|
||||
<stop offset="0.99" stop-color="#E82609"/>
|
||||
<stop offset="1" stop-color="#E82609"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_2689_27558" x1="12.0009" y1="18.5815" x2="7.79715" y2="17.5469" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#8C0C01"/>
|
||||
<stop offset="0.54" stop-color="#990C00"/>
|
||||
<stop offset="0.99" stop-color="#A80D0E"/>
|
||||
<stop offset="1" stop-color="#A80D0E"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_2689_27558" x1="19.2191" y1="13.5236" x2="15.4765" y2="10.1786" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7E110B"/>
|
||||
<stop offset="0.99" stop-color="#9E0C00"/>
|
||||
<stop offset="1" stop-color="#9E0C00"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint11_linear_2689_27558" x1="20.5907" y1="7.36723" x2="18.7255" y2="5.3788" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79130D"/>
|
||||
<stop offset="0.99" stop-color="#9E120B"/>
|
||||
<stop offset="1" stop-color="#9E120B"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint12_radial_2689_27558" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(16.0669 10.2325) scale(4.57496 4.58769)">
|
||||
<stop stop-color="#A80D00"/>
|
||||
<stop offset="0.99" stop-color="#7E0E08"/>
|
||||
<stop offset="1" stop-color="#7E0E08"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint13_radial_2689_27558" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(9.73115 16.2782) scale(6.0818 6.09873)">
|
||||
<stop stop-color="#A30C00"/>
|
||||
<stop offset="0.99" stop-color="#800E08"/>
|
||||
<stop offset="1" stop-color="#800E08"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="paint14_linear_2689_27558" x1="5.42282" y1="20.9778" x2="3.89957" y2="15.8242" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#8B2114"/>
|
||||
<stop offset="0.43" stop-color="#9E100A"/>
|
||||
<stop offset="0.99" stop-color="#B3100C"/>
|
||||
<stop offset="1" stop-color="#B3100C"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint15_linear_2689_27558" x1="17.0491" y1="3.89259" x2="20.4497" y2="5.38952" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#B31000"/>
|
||||
<stop offset="0.44" stop-color="#910F08"/>
|
||||
<stop offset="0.99" stop-color="#791C12"/>
|
||||
<stop offset="1" stop-color="#791C12"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
4
src/lib/components/marketing/(assets)/icons/svelte.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.5593 5.64405C17.7119 2.98303 14.0339 2.20337 11.3898 3.88134L6.7288 6.86439C5.45762 7.661 4.57626 8.96609 4.32202 10.4407C4.10168 11.6779 4.28813 12.9491 4.88135 14.0508C4.47457 14.661 4.20338 15.339 4.08474 16.0508C3.81355 17.5593 4.16948 19.1186 5.05084 20.3559C6.91524 23.0169 10.5763 23.7966 13.2203 22.1186L17.8813 19.1525C19.1525 18.3559 20.0339 17.0508 20.2881 15.5763C20.5085 14.339 20.322 13.0678 19.7288 11.9661C20.1356 11.3559 20.4068 10.6779 20.5254 9.96609C20.8135 8.44066 20.4576 6.88134 19.5593 5.64405Z" fill="#FF3E00"/>
|
||||
<path d="M10.9323 20.6102C9.42378 21 7.84751 20.4068 6.96615 19.1356C6.42378 18.3899 6.22039 17.4577 6.37293 16.5424C6.40683 16.3899 6.44073 16.2543 6.47462 16.1017L6.55937 15.8305L6.79666 16C7.35598 16.4068 7.96615 16.7119 8.62717 16.9153L8.79666 16.9661L8.77971 17.1356C8.76276 17.3729 8.83056 17.6271 8.96615 17.8305C9.23734 18.2204 9.71191 18.4068 10.1695 18.2882C10.2712 18.2543 10.3729 18.2204 10.4577 18.1695L15.1017 15.2034C15.339 15.0509 15.4916 14.8305 15.5424 14.5594C15.5933 14.2882 15.5255 14 15.3729 13.7797C15.1017 13.3899 14.6272 13.2204 14.1695 13.339C14.0678 13.3729 13.9662 13.4068 13.8814 13.4577L12.1017 14.5933C11.8136 14.7797 11.4916 14.9153 11.1526 15C9.64412 15.3899 8.06785 14.7966 7.18649 13.5255C6.66107 12.7797 6.44073 11.8475 6.61022 10.9322C6.76276 10.0509 7.30513 9.25427 8.06785 8.77969L12.7289 5.81359C13.017 5.62715 13.339 5.49155 13.678 5.38986C15.1865 5.00003 16.7628 5.59325 17.6441 6.86444C18.1865 7.6102 18.3899 8.5424 18.2373 9.45766C18.2034 9.6102 18.1695 9.74579 18.1187 9.89833L18.0339 10.1695L17.7967 10C17.2373 9.59325 16.6272 9.28816 15.9662 9.08477L15.7967 9.03393L15.8136 8.86444C15.8306 8.62715 15.7628 8.37291 15.6272 8.16952C15.356 7.77969 14.8814 7.6102 14.4238 7.72884C14.3221 7.76274 14.2204 7.79664 14.1356 7.84749L9.49157 10.8136C9.25429 10.9661 9.10174 11.1865 9.0509 11.4577C9.00005 11.7288 9.06785 12.017 9.22039 12.2373C9.49157 12.6271 9.96615 12.7966 10.4238 12.678C10.5255 12.6441 10.6272 12.6102 10.7119 12.5594L12.4916 11.4238C12.7797 11.2373 13.1017 11.1017 13.4407 11C14.9492 10.6102 16.5255 11.2034 17.4068 12.4746C17.9492 13.2204 18.1526 14.1526 18 15.0678C17.8475 15.9492 17.3051 16.7458 16.5424 17.2204L11.8814 20.1865C11.5933 20.3729 11.2712 20.5085 10.9323 20.6102Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
9
src/lib/components/marketing/(assets)/icons/swift.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.5872 18.8938C14.4653 20.1088 11.5479 20.2337 8.61265 18.9866C6.23606 17.9843 4.26411 16.2298 3 14.2251C3.60678 14.7263 4.31466 15.1274 5.07311 15.478C8.10435 16.8864 11.135 16.79 13.2677 15.4816C10.2338 13.1759 7.65188 10.1649 5.73053 7.7091C5.32585 7.30808 5.02246 6.80683 4.71908 6.35574C7.04502 8.46089 10.7364 11.1172 12.0508 11.8694C9.27012 8.96205 6.79228 5.35341 6.89321 5.45346C11.2924 9.86433 15.3883 12.3706 15.3883 12.3706C15.5238 12.4463 15.6284 12.5094 15.7125 12.5657C15.8012 12.3422 15.8789 12.1101 15.9444 11.8694C16.6523 9.31314 15.8434 6.40576 14.0735 4C18.169 6.45601 20.5963 11.0672 19.5847 14.9269C19.5584 15.031 19.5297 15.1337 19.4988 15.2347C21.5211 17.741 21.0005 20.4406 20.7477 19.9394C19.6507 17.8113 17.6197 18.462 16.5872 18.8938Z" fill="url(#paint0_linear_2689_27628)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_2689_27628" x1="12.0066" y1="4" x2="12.0066" y2="20.0008" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F88A36"/>
|
||||
<stop offset="1" stop-color="#FD2020"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
21
src/lib/components/marketing/(assets)/icons/transparency.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 36.25C20 36.25 33.75 29.75 33.75 20V11.125L20 3.75L6.25 11.125V20C6.25 29.75 20 36.25 20 36.25Z" fill="url(#paint0_linear_3129_11894)" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g filter="url(#filter0_b_3129_11894)">
|
||||
<circle cx="28" cy="26" r="8" fill="#FD366E"/>
|
||||
<circle cx="28" cy="26" r="8" fill="white" fill-opacity="0.9"/>
|
||||
<circle cx="28" cy="26" r="8" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<path d="M24.25 27.5L26.75 29.5L31.75 23" stroke="#FD366E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<defs>
|
||||
<filter id="filter0_b_3129_11894" x="15.3999" y="13.3999" width="25.2002" height="25.2002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feGaussianBlur in="BackgroundImageFix" stdDeviation="2"/>
|
||||
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_3129_11894"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_3129_11894" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_3129_11894" x1="20.0018" y1="3.38068" x2="20.0018" y2="36.6193" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FD366E" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#FD366E" stop-opacity="0.4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
15
src/lib/components/marketing/(assets)/icons/vite.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.9471 4.59883L10.4311 17.7947C10.2759 18.0671 9.87719 18.0687 9.71968 17.7976L2.05465 4.6001C1.88306 4.30465 2.14037 3.94678 2.48137 4.00662L10.0054 5.32708C10.0534 5.3355 10.1026 5.33542 10.1505 5.32683L17.5173 4.00851C17.8571 3.94769 18.1156 4.3028 17.9471 4.59883Z" fill="url(#paint0_linear_8495_3619)"/>
|
||||
<path d="M13.6179 2.00383L7.55298 3.06314C7.4533 3.08055 7.37949 3.15585 7.37348 3.24622L7.0004 8.86276C6.99163 8.99505 7.12792 9.09772 7.27277 9.06795L8.96133 8.72058C9.11932 8.68811 9.26207 8.81214 9.2296 8.95376L8.72793 11.1435C8.69417 11.2909 8.8494 11.4169 9.01086 11.3732L10.0538 11.0907C10.2155 11.047 10.3708 11.1734 10.3366 11.3209L9.53938 14.7605C9.4895 14.9756 9.81055 15.0929 9.94444 14.9085L10.0339 14.7853L14.9759 5.9939C15.0587 5.8467 14.916 5.67885 14.7346 5.71005L12.9965 6.00906C12.8332 6.03713 12.6942 5.90155 12.7403 5.7591L13.8747 2.25366C13.9209 2.11098 13.7814 1.97528 13.6179 2.00383Z" fill="url(#paint1_linear_8495_3619)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_8495_3619" x1="1.8675" y1="3.53502" x2="11.0007" y2="16.168" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41D1FF"/>
|
||||
<stop offset="1" stop-color="#BD34FE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_8495_3619" x1="9.23886" y1="2.29143" x2="10.7112" y2="13.6223" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFEA83"/>
|
||||
<stop offset="0.0833333" stop-color="#FFDD35"/>
|
||||
<stop offset="1" stop-color="#FFA800"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
4
src/lib/components/marketing/(assets)/icons/vue.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 4L12.3333 20L21.6667 4H18L12.3333 13.6667L6.66667 4H3Z" fill="#41B883"/>
|
||||
<path d="M6.66663 4L12.3333 13.6667L18 4H14.6666L12.3768 8.00841L9.99996 4H6.66663Z" fill="#35495E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 298 B |
105
src/lib/components/marketing/open-source-alternative.svelte
Normal file
@@ -0,0 +1,105 @@
|
||||
<script lang="ts">
|
||||
import { sleep, unwrite, write } from '$lib/animations';
|
||||
|
||||
import collaboration from './(assets)/icons/collaboration.svg';
|
||||
import customization from './(assets)/icons/customization.svg';
|
||||
import transparency from './(assets)/icons/transparency.svg';
|
||||
import DiscordLink from '../shared/discord-link.svelte';
|
||||
import GithubStats from '../shared/github-stats.svelte';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: 'Community collaboration',
|
||||
copy: "Share knowledge and learn from others' experiences.",
|
||||
icon: collaboration
|
||||
},
|
||||
{
|
||||
title: 'Transparency and security',
|
||||
copy: 'The source code is openly accessible for anyone to inspect.',
|
||||
icon: transparency
|
||||
},
|
||||
{
|
||||
title: 'Customization and flexibility',
|
||||
copy: 'The freedom to customize and adapt products to your needs. ',
|
||||
icon: customization
|
||||
}
|
||||
];
|
||||
|
||||
type Props = {
|
||||
platforms?: Array<string>;
|
||||
} & SvelteHTMLElements['div'];
|
||||
|
||||
const {
|
||||
platforms = ['Auth0', 'Firebase', 'Supabase', 'NHost'],
|
||||
class: className,
|
||||
...rest
|
||||
}: Props = $props();
|
||||
|
||||
let activeIndex = $state<number>(0);
|
||||
let activePlatformText = $state<string>('');
|
||||
|
||||
const rotatePlatforms = async () => {
|
||||
while (true) {
|
||||
await write(platforms[activeIndex], (v) => (activePlatformText = v), 500);
|
||||
|
||||
await sleep(5000);
|
||||
|
||||
await unwrite(platforms[activeIndex], (v) => (activePlatformText = v), 250);
|
||||
|
||||
await sleep(500);
|
||||
|
||||
activeIndex = (activeIndex + 1) % platforms.length;
|
||||
}
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
rotatePlatforms();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class={classNames('light bg-greyscale-50 pt-40 pb-40', className)} {...rest}>
|
||||
<div class="container overflow-x-hidden max-md:px-5!">
|
||||
<div class="mx-auto mb-20 flex max-w-2xl flex-col items-center gap-4 text-center">
|
||||
<h2 class="text-display text-primary font-aeonik-pro">
|
||||
Open source <br class="hidden md:block" />alternative to
|
||||
|
||||
<br class="block md:hidden" />
|
||||
<div
|
||||
class="relative inline-flex bg-[linear-gradient(-146deg,_#FD376F,_#19191D_47%,_#19191D)] bg-clip-text pb-2 text-transparent"
|
||||
>
|
||||
{activePlatformText}
|
||||
<div
|
||||
class="animate-caret-blink -right-2 bottom-0 mt-1 ml-2 block h-full min-h-14 w-px bg-[linear-gradient(-146deg,_#FD376F,_#19191D_47%,_#19191D)]"
|
||||
></div>
|
||||
</div>
|
||||
</h2>
|
||||
<p class="md:text-description text-body text-secondary font-medium">
|
||||
Appwrite is a 100% open source project, giving you the flexibility and support you
|
||||
need to get your project started.
|
||||
</p>
|
||||
<div
|
||||
class="mx-auto mt-2 flex w-full flex-col items-center justify-center gap-2 md:flex-row"
|
||||
>
|
||||
<GithubStats class="w-full! md:w-fit!" />
|
||||
<DiscordLink class="w-full! md:w-fit!" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="divide-smooth grid w-full grid-cols-1 divide-y divide-dashed md:grid-cols-3 md:place-items-center md:divide-y-0"
|
||||
>
|
||||
{#each items as item}
|
||||
<div
|
||||
class="border-smooth py-10 text-center font-medium last-of-type:border-0 md:border-r md:px-10 md:py-0"
|
||||
>
|
||||
<img src={item.icon} alt={item.title} class="mx-auto" />
|
||||
<h3 class="text-sub-body text-primary mt-4 font-medium">{item.title}</h3>
|
||||
<p class="text-sub-body text-secondary mt-2 font-normal">{item.copy}</p>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
158
src/lib/components/marketing/platforms.svelte
Normal file
@@ -0,0 +1,158 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import Node from './(assets)/icons/node.svg';
|
||||
import Javascript from './(assets)/icons/javascript.svg';
|
||||
import Flutter from './(assets)/icons/flutter.svg';
|
||||
import Nextjs from './(assets)/icons/nextjs.svg';
|
||||
import Svelte from './(assets)/icons/svelte.svg';
|
||||
import Remix from './(assets)/icons/remix.svg';
|
||||
import Lynx from './(assets)/icons/lynx.svg';
|
||||
import Astro from './(assets)/icons/astro.svg';
|
||||
import Vue from './(assets)/icons/vue.svg';
|
||||
import Deno from './(assets)/icons/deno.svg';
|
||||
import Angular from './(assets)/icons/angular.svg';
|
||||
import Nuxt from './(assets)/icons/nuxt.svg';
|
||||
import Vite from './(assets)/icons/vite.svg';
|
||||
import ReactNative from './(assets)/icons/react-native.svg';
|
||||
import React from './(assets)/icons/react.svg';
|
||||
import GradientText from '$lib/components/fancy/gradient-text.svelte';
|
||||
import Noise from '$lib/components/fancy/noise.svelte';
|
||||
import { Tooltip } from 'bits-ui';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
|
||||
const platforms = [
|
||||
{
|
||||
name: 'JS',
|
||||
icon: Javascript,
|
||||
primary: '#FFCA28'
|
||||
},
|
||||
{
|
||||
name: 'Flutter',
|
||||
icon: Flutter,
|
||||
primary: '#00569E',
|
||||
secondary: '#47C5FB'
|
||||
},
|
||||
{ name: 'Node.js', icon: Node, primary: '#8CC84B' },
|
||||
{
|
||||
name: 'React Native',
|
||||
icon: ReactNative,
|
||||
primary: '#53C1DE'
|
||||
},
|
||||
{ name: 'Next.js', icon: Nextjs, primary: '#000000' },
|
||||
{ name: 'Astro', icon: Astro, primary: '#ffffff' },
|
||||
{
|
||||
name: 'Vite',
|
||||
icon: Vite,
|
||||
primary: '#BD34FE'
|
||||
},
|
||||
{ name: 'Svelte', icon: Svelte, primary: '#fc5732' },
|
||||
{
|
||||
name: 'Remix',
|
||||
icon: Remix,
|
||||
primary: '#ffffff'
|
||||
},
|
||||
{ name: 'Deno', icon: Deno, primary: '#fff' },
|
||||
{ name: 'Vue', icon: Vue, primary: '#41B883', secondary: '#35495E' },
|
||||
{ name: 'Angular', icon: Angular, primary: '#C3002F' },
|
||||
{
|
||||
name: 'Nuxt',
|
||||
icon: Nuxt,
|
||||
primary: '#00DC82'
|
||||
},
|
||||
{ name: 'React', icon: React, primary: '#53C1DE' },
|
||||
{
|
||||
name: 'Lynx',
|
||||
icon: Lynx,
|
||||
primary: '#78D9EA'
|
||||
}
|
||||
];
|
||||
|
||||
type Props = {
|
||||
headline: string;
|
||||
class?: string;
|
||||
} & SvelteHTMLElements['div'];
|
||||
|
||||
const {
|
||||
headline = 'Supporting the tools you work with',
|
||||
class: className = '',
|
||||
...rest
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class={classNames('border-smooth relative z-10 border-y border-dashed', className)} {...rest}>
|
||||
<div class="container flex flex-col items-center max-md:pt-4 md:flex-row">
|
||||
<GradientText>
|
||||
<span class="flex items-center pr-4 text-sm font-medium md:w-full md:max-w-[175px]"
|
||||
>{headline}</span
|
||||
>
|
||||
</GradientText>
|
||||
<div
|
||||
class={classNames(
|
||||
'flex w-full flex-nowrap overflow-clip md:overflow-visible',
|
||||
'mask-r-from-75% mask-r-to-99% mask-l-from-75% mask-l-to-99% mask-alpha backdrop-blur-3xl md:mask-none'
|
||||
)}
|
||||
>
|
||||
{#each [1, 2] as _, i}
|
||||
<div
|
||||
class={classNames(
|
||||
'divide-smooth animate-scroll-x flex w-max flex-1 grow flex-nowrap divide-dashed md:w-full md:[animation:none] md:divide-x md:[animation-play-state:paused]',
|
||||
{
|
||||
'md:hidden': i === 1
|
||||
}
|
||||
)}
|
||||
>
|
||||
<Tooltip.Provider delayDuration={0} disableCloseOnTriggerClick>
|
||||
{#each platforms as platform, i}
|
||||
<Tooltip.Root>
|
||||
<div
|
||||
class="contents"
|
||||
style="--primary-color:{platform.primary};--secondary-color:{platform.secondary};--animation-delay:{i *
|
||||
25}ms"
|
||||
>
|
||||
<Tooltip.Trigger
|
||||
class={classNames(
|
||||
'border-smooth group animate-fade-in relative mt-4 flex h-16 w-16 items-center justify-center border-dashed md:mt-0 md:w-full lg:border-r',
|
||||
{
|
||||
'lg:border-l': i === 0
|
||||
}
|
||||
)}
|
||||
aria-hidden={i < platforms.length - 1}
|
||||
>
|
||||
<img
|
||||
src={platform.icon}
|
||||
alt={platform.name}
|
||||
class="h-8 w-auto grayscale transition-all duration-500 group-hover:grayscale-0"
|
||||
/>
|
||||
|
||||
<div
|
||||
class={classNames(
|
||||
'absolute inset-0 opacity-0 transition-opacity group-hover:opacity-100',
|
||||
'bg-gradient-to-tl from-transparent to-transparent',
|
||||
'hover:from-(--primary-color,_#fff)/4 hover:to-(--secondary-color,_transparent)/10'
|
||||
)}
|
||||
>
|
||||
<Noise opacity={0.1} />
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content
|
||||
sideOffset={8}
|
||||
side="top"
|
||||
class={classNames(
|
||||
'text-primary bg-greyscale-900 relative hidden rounded-md border-0! px-2.5 py-1 text-sm md:block',
|
||||
'data-[state="closed"]:animate-menu-out data-[state="instant-open"]:animate-menu-in data-[state="delayed-open"]:animate-menu-in'
|
||||
)}
|
||||
>{platform.name}
|
||||
<div
|
||||
class="absolute inset-0 rounded-md bg-gradient-to-tl from-(--primary-color,_#fff)/4 to-(--secondary-color,_transparent)/10"
|
||||
></div>
|
||||
<Tooltip.Arrow class="text-(--primary-color)/4" />
|
||||
</Tooltip.Content>
|
||||
</div>
|
||||
</Tooltip.Root>
|
||||
{/each}
|
||||
</Tooltip.Provider>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
85
src/lib/components/marketing/testimonials.svelte
Normal file
@@ -0,0 +1,85 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
name: 'Ryan O’Conner',
|
||||
copy: `The switch to using Appwrite brought infinite value that I'm still discovering today, but a major impact that it made was the amount of time and stress that it saved me as it simply just works.`,
|
||||
image: '/images/testimonials/ryan-oconner.png',
|
||||
title: 'Founder',
|
||||
company: 'K-Collect'
|
||||
},
|
||||
{
|
||||
name: 'David Forster',
|
||||
copy: `We really loved working with Appwrite for launching our bootstrapped "Open Mind" App. I am still surprised how easy the implementation into Flutter was.`,
|
||||
image: '/images/testimonials/david-forster.png',
|
||||
title: 'Founder',
|
||||
company: 'Open Mind'
|
||||
},
|
||||
{
|
||||
name: 'Marius Bolik',
|
||||
copy: `The integrated user authentication and the ease of creating data structures have undoubtedly saved us several weeks' worth of time.`,
|
||||
image: '/images/testimonials/marius-bolik2.png',
|
||||
title: 'CTO',
|
||||
company: 'mySHOEFITTER'
|
||||
},
|
||||
{
|
||||
name: 'Sergio Ponguta',
|
||||
copy: `Just go for it, don’t think twice. Try Appwrite, and you will love it!`,
|
||||
image: '/images/testimonials/smartbee.png',
|
||||
title: 'Founder',
|
||||
company: 'Smart Bee'
|
||||
},
|
||||
{
|
||||
name: 'Phil McClusky',
|
||||
copy: 'Just like a Swiss Army Knife, you can choose and use the tools that you need with Appwrite.',
|
||||
image: '/images/testimonials/majik.png',
|
||||
title: 'Developer',
|
||||
company: 'Majik Kids'
|
||||
}
|
||||
];
|
||||
|
||||
type Props = {
|
||||
class?: string;
|
||||
};
|
||||
const { class: className }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class={classNames('relative w-full max-w-[100vw] overflow-hidden', className)}>
|
||||
<div class="group light flex w-fit flex-nowrap gap-8 overflow-clip md:overflow-visible">
|
||||
{#each Array.from({ length: 2 }) as _, i}
|
||||
<div
|
||||
class="animate-scroll-x flex items-center gap-8 group-hover:[animation-play-state:paused]"
|
||||
>
|
||||
{#each testimonials as testimonial}
|
||||
<div
|
||||
class="flex h-fit w-[90vw] flex-col justify-center rounded-2xl bg-white p-6 transition-all md:w-lg"
|
||||
aria-hidden={i < testimonials.length - 1}
|
||||
>
|
||||
<p class="text-sub-body text-secondary flex-1 font-medium">
|
||||
{testimonial.copy}
|
||||
</p>
|
||||
|
||||
<div class="mt-4 flex items-center gap-3">
|
||||
<img
|
||||
src={testimonial.image}
|
||||
class="size-12 rounded-full"
|
||||
alt="{testimonial.company} Logo"
|
||||
/>
|
||||
<div>
|
||||
<span class="text-secondary text-sub-body block font-medium">
|
||||
{testimonial.name}
|
||||
</span>
|
||||
{#if testimonial.title}
|
||||
<span class="text-sub-body text-secondary block">
|
||||
{testimonial.title} // {testimonial.company}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,11 +57,20 @@
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col items-center gap-2 md:flex-row">
|
||||
<Button href={cta.url} class="!w-full md:!w-fit">
|
||||
<Button
|
||||
href={cta.url}
|
||||
class="!w-full md:!w-fit"
|
||||
event={`product-hero-${eyebrow.label.toLocaleLowerCase().replace(' ', '_')}-click`}
|
||||
>
|
||||
{cta.label}
|
||||
</Button>
|
||||
{#if secondaryCta}
|
||||
<Button variant="secondary" href={secondaryCta.url} class="!w-full md:!w-fit">
|
||||
<Button
|
||||
variant="secondary"
|
||||
href={secondaryCta.url}
|
||||
class="!w-full md:!w-fit"
|
||||
event={`product-hero-${secondaryCta.label.toLocaleLowerCase().replace(' ', '_')}-click`}
|
||||
>
|
||||
{secondaryCta.label}
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
@@ -29,17 +29,33 @@
|
||||
description: 'Manage your files project, using convenient APIs and utilities.',
|
||||
icon: '/images/icons/illustrated/dark/storage.png',
|
||||
url: '/products/storage'
|
||||
},
|
||||
sites: {
|
||||
title: 'Sites',
|
||||
description: 'The open-source Vercel alternative.',
|
||||
icon: '/images/icons/illustrated/dark/sites.png',
|
||||
url: '/products/sites'
|
||||
},
|
||||
realtime: {
|
||||
title: 'Realtime',
|
||||
description: 'Subscribe and react to any event using the Realtime API.',
|
||||
icon: '/images/icons/illustrated/dark/realtime.png',
|
||||
url: '/docs/realtime'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export let exclude:
|
||||
type Props = {
|
||||
exclude?:
|
||||
| 'messaging'
|
||||
| 'functions'
|
||||
| 'databases'
|
||||
| 'storage'
|
||||
| 'auth'
|
||||
| 'realtime'
|
||||
| undefined = undefined;
|
||||
| 'sites';
|
||||
};
|
||||
|
||||
const { exclude }: Props = $props();
|
||||
|
||||
const products = Object.entries(allProducts)
|
||||
.filter(([key]) => key !== exclude)
|
||||
@@ -47,9 +63,9 @@
|
||||
</script>
|
||||
|
||||
<section class="border-smooth border-t py-20 md:py-40">
|
||||
<div class="container">
|
||||
<div class="container max-md:px-5!">
|
||||
<h4 class="text-label text-primary text-center">Keep exploring our products</h4>
|
||||
<div class="mt-8 grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||
<div class="mt-8 grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-3">
|
||||
{#each products as product}
|
||||
<a
|
||||
class="web-card is-normal"
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
import { fade, scale } from 'svelte/transition';
|
||||
import { createDialog, melt } from '@melt-ui/svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
type Props = {
|
||||
url: string;
|
||||
title?: string;
|
||||
children: Snippet;
|
||||
inlineVideo?: boolean;
|
||||
};
|
||||
|
||||
const {
|
||||
@@ -17,12 +19,23 @@
|
||||
preventScroll: true
|
||||
});
|
||||
|
||||
const { url, title = 'YouTube video player', children }: Props = $props();
|
||||
const { url, title = 'YouTube video player', children, inlineVideo = true }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div use:melt={$trigger} class="contents cursor-pointer">
|
||||
{#if inlineVideo}
|
||||
<div class="contents cursor-pointer" use:melt={$trigger}>
|
||||
{@render children()}
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="contents cursor-pointer"
|
||||
on:click={() => {
|
||||
if (browser && window) window.open(url, '_blank');
|
||||
}}
|
||||
>
|
||||
{@render children()}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $open}
|
||||
<div class="fixed inset-0 z-1000 flex items-center justify-center">
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
<script lang="ts">
|
||||
export let size: number = 16;
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
|
||||
let className: string = '';
|
||||
|
||||
export let paused: boolean = false;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div role="status" class="flex shrink-0 items-center" style="--size:{size}px">
|
||||
<div class={classNames('flex size-5 animate-spin [animation-duration:5s]', className)}>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="text-greyscale-200 dark:text-greyscale-600 size-[var(--size)] animate-spin fill-white"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class={classNames('motion-reduce:[animation:none]', {
|
||||
'animate-spin': !paused
|
||||
})}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
opacity="0.2"
|
||||
d="M24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0C18.6274 0 24 5.37258 24 12ZM2.4 12C2.4 17.3019 6.69807 21.6 12 21.6C17.3019 21.6 21.6 17.3019 21.6 12C21.6 6.69807 17.3019 2.4 12 2.4C6.69807 2.4 2.4 6.69807 2.4 12Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill"
|
||||
d="M5.11708 2.17017C6.66833 1.08398 8.45463 0.380338 10.3299 0.116783C12.2052 -0.146772 14.1163 0.0372409 15.9068 0.653778C17.6974 1.27031 19.3166 2.30187 20.6321 3.6641C21.9476 5.02633 22.922 6.68056 23.4757 8.49154C24.0293 10.3025 24.1465 12.2188 23.8177 14.0838C23.4888 15.9487 22.7233 17.7094 21.5836 19.2218C20.444 20.7342 18.9625 21.9554 17.2605 22.7855C15.5584 23.6157 13.684 24.0312 11.7906 23.9982L11.8325 21.5985C13.3472 21.625 14.8467 21.2925 16.2084 20.6284C17.57 19.9643 18.7552 18.9873 19.6669 17.7774C20.5786 16.5675 21.1911 15.159 21.4542 13.667C21.7172 12.1751 21.6235 10.642 21.1805 9.19323C20.7376 7.74445 19.9581 6.42107 18.9057 5.33128C17.8533 4.2415 16.5579 3.41625 15.1255 2.92302C13.693 2.42979 12.1642 2.28258 10.6639 2.49343C9.1637 2.70427 7.73467 3.26718 6.49367 4.13614L5.11708 2.17017Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
|
||||
5
src/lib/components/ui/badge-transparent.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<div
|
||||
class="flex w-fit items-center gap-x-2 rounded-full border border-[var(--color-smooth)] bg-[var(--color-offset)] px-3 py-1.5"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts" module>
|
||||
import { type VariantProps, cva } from 'cva';
|
||||
|
||||
// TODO: replace _button.scss with Tailwind classes for long-term maintainability
|
||||
const button = cva(['web-button'], {
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -16,12 +19,12 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { type VariantProps, cva } from 'cva';
|
||||
import { type VariantProps } from 'cva';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { Action } from 'svelte/action';
|
||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { trackEvent, type TrackEventArgs } from '$lib/actions/analytics';
|
||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||
|
||||
type ButtonOrAnchorProps =
|
||||
| (HTMLButtonAttributes & { href?: undefined })
|
||||
@@ -30,7 +33,7 @@
|
||||
type Props = {
|
||||
action?: Action;
|
||||
children: Snippet;
|
||||
events?: TrackEventArgs;
|
||||
event?: string | TrackEventArgs;
|
||||
} & VariantProps<typeof button> &
|
||||
ButtonOrAnchorProps;
|
||||
|
||||
@@ -40,7 +43,7 @@
|
||||
action = () => {},
|
||||
children,
|
||||
class: classes,
|
||||
events,
|
||||
event,
|
||||
...rest
|
||||
}: Props = $props();
|
||||
|
||||
@@ -48,11 +51,11 @@
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a use:action {href} class={buttonClasses} {...rest as HTMLAnchorAttributes}>
|
||||
<a use:action {href} class={buttonClasses} onclick={() => event && trackEvent(event)} {...rest}>
|
||||
{@render children()}
|
||||
</a>
|
||||
{:else}
|
||||
<button use:action class={buttonClasses} {...rest as HTMLButtonAttributes}>
|
||||
<button use:action class={buttonClasses} onclick={() => event && trackEvent(event)} {...rest}>
|
||||
{@render children()}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -2,3 +2,4 @@ export { default as Button, type Variant } from './button.svelte';
|
||||
export { default as InlineTag } from './inline-tag.svelte';
|
||||
export { default as Icon, type IconType } from './icon';
|
||||
export { default as Select } from './select.svelte';
|
||||
export { default as BadgeTransparent } from './badge-transparent.svelte';
|
||||
|
||||
@@ -116,7 +116,11 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="web-mobile-header-end">
|
||||
<Button href={getAppwriteDashboardUrl()} class="hidden md:flex">
|
||||
<Button
|
||||
href={getAppwriteDashboardUrl()}
|
||||
class="hidden md:flex"
|
||||
event="docs-go_to_console-click"
|
||||
>
|
||||
<span class="text-sub-body font-medium">Go to Console</span>
|
||||
</Button>
|
||||
<Button variant="text" aria-label="open navigation" onclick={toggleSidenav}>
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
</div>
|
||||
<div class="web-mobile-header-end">
|
||||
{#if !$isMobileNavOpen}
|
||||
<Button href={getAppwriteDashboardUrl()}>
|
||||
<Button href={getAppwriteDashboardUrl()} event="main-start_building_btn-click">
|
||||
<span class="text">Start building</span>
|
||||
</Button>
|
||||
{/if}
|
||||
@@ -227,11 +227,6 @@
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="web-u-inline-width-100-percent-mobile"
|
||||
onclick={() =>
|
||||
trackEvent({
|
||||
plausible: { name: 'Star on GitHub in header' },
|
||||
posthog: { name: 'github-stars_nav_click' }
|
||||
})}
|
||||
>
|
||||
<Icon name="star" aria-hidden="true" />
|
||||
<span class="text">Star on GitHub</span>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
import { SOCIAL_STATS } from '$lib/constants';
|
||||
import { layoutState, toggleSidenav } from './Docs.svelte';
|
||||
import SidebarNavButton from './SidebarNavButton.svelte';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
interface Props {
|
||||
expandable?: boolean;
|
||||
@@ -63,7 +64,14 @@
|
||||
<div class="web-side-nav-scroll">
|
||||
{#if parent}
|
||||
<section class="web-side-nav-wrapper-parent">
|
||||
<a href={parent.href} aria-label="go back">
|
||||
<a
|
||||
href={parent.href}
|
||||
aria-label="go back"
|
||||
onclick={() =>
|
||||
trackEvent(
|
||||
`docs-sidebar-${parent.label.toLowerCase().replace(' ', '_')}-click`
|
||||
)}
|
||||
>
|
||||
<span class="icon-cheveron-left" aria-hidden="true"></span>
|
||||
</a>
|
||||
<span class="web-side-nav-wrapper-parent-title text-micro uppercase"
|
||||
|
||||
@@ -21,7 +21,7 @@ export const createCountdown = (date: Date) => {
|
||||
const totalMinutes = Math.floor(totalSeconds / 60);
|
||||
minutes.set(totalMinutes % 60);
|
||||
hours.set(Math.floor(totalMinutes / 60));
|
||||
days.set(Math.ceil(get(hours) / 24));
|
||||
days.set(Math.floor(get(hours) / 24));
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Language } from './code';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
const allVersions = [
|
||||
'1.7.x',
|
||||
'1.6.x',
|
||||
'1.5.x',
|
||||
'1.4.x',
|
||||
@@ -30,7 +31,9 @@ export const Service = {
|
||||
Locale: 'locale',
|
||||
Storage: 'storage',
|
||||
Teams: 'teams',
|
||||
Users: 'users'
|
||||
Users: 'users',
|
||||
Sites: 'sites',
|
||||
Tokens: 'tokens'
|
||||
} as const;
|
||||
|
||||
export type ServiceType = typeof Service;
|
||||
@@ -142,7 +145,9 @@ export const serviceMap: Record<ServiceValue, string> = {
|
||||
[Service.Locale]: 'Locale',
|
||||
[Service.Storage]: 'Storage',
|
||||
[Service.Teams]: 'Teams',
|
||||
[Service.Users]: 'Users'
|
||||
[Service.Users]: 'Users',
|
||||
[Service.Sites]: 'Sites',
|
||||
[Service.Tokens]: 'Tokens'
|
||||
};
|
||||
|
||||
export const preferredVersion = writable<Version | null>(
|
||||
|
||||
@@ -112,6 +112,11 @@ function getExamples(version: string) {
|
||||
query: '?raw',
|
||||
import: 'default'
|
||||
});
|
||||
case '1.7.x':
|
||||
return import.meta.glob('$appwrite/docs/examples/1.7.x/**/*.md', {
|
||||
query: '?raw',
|
||||
import: 'default'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,11 @@
|
||||
Join our Technology Partners program to integrate your solutions with
|
||||
Appwrite’s API, enhancing functionality and expanding your reach.
|
||||
</p>
|
||||
<Button href="/integrations/technology-partner" class="mt-4 self-center">
|
||||
<Button
|
||||
href="/integrations/technology-partner"
|
||||
class="mt-4 self-center"
|
||||
event="integrations-technology_partner-click"
|
||||
>
|
||||
<span class="text">Get Started</span>
|
||||
</Button>
|
||||
</section>
|
||||
|
||||
19
src/partials/cli-sites.md
Normal file
@@ -0,0 +1,19 @@
|
||||
You can create sites using the CLI without needing to access the Console.
|
||||
|
||||
{% partial file="cli-disclaimer.md" /%}
|
||||
|
||||
To deploy your site with the Appwrite CLI, use the `appwrite init sites` command to create a starter site and paste your code into the generated file and folder.
|
||||
|
||||
```sh
|
||||
appwrite init sites
|
||||
```
|
||||
|
||||
To deploy the generated code, add any dependencies and push the site using the following command:
|
||||
|
||||
```sh
|
||||
appwrite push sites
|
||||
```
|
||||
|
||||
{% arrow_link href="/docs/tooling/command-line/sites#commands" %}
|
||||
Learn more about the CLI sites commands
|
||||
{% /arrow_link %}
|
||||
10
src/partials/sites-env-vars.md
Normal file
@@ -0,0 +1,10 @@
|
||||
| Variable | Description | Available at Build and/or Run Time |
|
||||
| ------------------------------- | ------------------------------------------------------- | ---------------------------------- |
|
||||
| `APPWRITE_SITE_API_ENDPOINT` | The API endpoint of the running site | Both |
|
||||
| `APPWRITE_SITE_NAME` | The name of the running site. | Both |
|
||||
| `APPWRITE_SITE_DEPLOYMENT` | The deployment ID of the running sites. | Both |
|
||||
| `APPWRITE_SITE_PROJECT_ID` | The project ID of the running site. | Both |
|
||||
| `APPWRITE_SITE_RUNTIME_NAME` | The runtime name of the running site. | Both |
|
||||
| `APPWRITE_SITE_RUNTIME_VERSION` | The runtime version of the running site. | Both |
|
||||
| `APPWRITE_SITE_CPUS` | The CPU (runtime) specification of the running site. | Both |
|
||||
| `APPWRITE_SITE_MEMORY` | The memory (runtime) specification of the running site. | Both |
|
||||
@@ -9,6 +9,10 @@
|
||||
}
|
||||
|
||||
const { children }: Props = $props();
|
||||
const showLockUp = $derived(
|
||||
page.route.id?.includes('/init/tickets') &&
|
||||
!page.route.id?.includes('/init/tickets/[username]')
|
||||
);
|
||||
</script>
|
||||
|
||||
<Main>
|
||||
@@ -16,7 +20,7 @@
|
||||
class="flex min-h-screen flex-col bg-[url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDI1MCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHk9IjI1MSIgd2lkdGg9IjQiIGhlaWdodD0iNCIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC4yNCIvPgo8cmVjdCB4PSIxMjAiIHk9IjQ5NiIgd2lkdGg9IjQiIGhlaWdodD0iNCIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC4yNCIvPgo8L3N2Zz4K)] bg-[size:calc(100vw_/_11)] bg-[position:center_top]"
|
||||
>
|
||||
{@render children()}
|
||||
{#if page.url.pathname.includes('/init/tickets') && !isStarted}
|
||||
{#if showLockUp}
|
||||
<div class="hidden overflow-y-hidden md:block">
|
||||
<Lockup class="-mb-[16rem] w-full lg:-mb-[24rem]" />
|
||||
</div>
|
||||
|
||||
BIN
src/routes/(init)/init/(assets)/eventBuildingWithFlutter.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
src/routes/(init)/init/(assets)/eventClosingParty.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
src/routes/(init)/init/(assets)/eventFutureOfAppwrite.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
src/routes/(init)/init/(assets)/eventIndustryPanel.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
src/routes/(init)/init/(assets)/eventLiveDemo.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
src/routes/(init)/init/(assets)/init-giveaway.png
Normal file
|
After Width: | Height: | Size: 484 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 32 KiB |
BIN
src/routes/(init)/init/(assets)/posterDeploy.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
src/routes/(init)/init/(assets)/posterFutureOfAppwrite.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
@@ -10,14 +10,14 @@
|
||||
class="mx-auto flex w-full items-center gap-4 bg-[url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIyIiBoZWlnaHQ9IjY4IiB2aWV3Qm94PSIwIDAgMTIyIDY4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cmVjdCB5PSIyIiB3aWR0aD0iMiIgaGVpZ2h0PSIyIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjI0Ii8+CjxyZWN0IHg9IjYwIiB5PSIzMiIgd2lkdGg9IjIiIGhlaWdodD0iMiIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC4yNCIvPgo8L3N2Zz4K)] py-4 md:h-[76px]"
|
||||
>
|
||||
<div class="md:basis-1/3">
|
||||
<Badge class="ml-0">Init is coming <span class="text-accent">/</span> {initDates}</Badge>
|
||||
<Badge class="ml-0">Init is here <span class="text-accent">/</span> {initDates}</Badge>
|
||||
</div>
|
||||
<a href="/init" class="md:basis-1/3">
|
||||
<img class="mx-auto mt-2 hidden max-w-[200px] md:block" src={Lockup} alt="Appwrite" />
|
||||
</a>
|
||||
<div class="mr-0 ml-auto justify-self-end text-right">
|
||||
<a href="/init" class="text-primary group mr-0 ml-auto flex items-center gap-2 text-right"
|
||||
>Register now <Icon
|
||||
>Go to Init <Icon
|
||||
class="transition group-hover:-translate-x-0.5"
|
||||
name="arrow-right"
|
||||
/></a
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" module>
|
||||
export type DayProps = {
|
||||
illustration: string;
|
||||
illustration: string | object;
|
||||
release: Date;
|
||||
title: string;
|
||||
description: string;
|
||||
@@ -40,7 +40,7 @@
|
||||
content = [],
|
||||
announcementVideo = undefined,
|
||||
links = [],
|
||||
title,
|
||||
title: featureTitle,
|
||||
description,
|
||||
url,
|
||||
index
|
||||
@@ -80,7 +80,7 @@
|
||||
class="border-offset relative z-10 col-span-5 flex h-full flex-col justify-center gap-4 border-x-2 border-none px-4 py-8 md:border-dashed md:p-8"
|
||||
>
|
||||
<h2 class="text-display font-aeonik-pro text-primary">
|
||||
{title}<span class="text-accent">_</span>
|
||||
{featureTitle}<span class="text-accent">_</span>
|
||||
</h2>
|
||||
<p class="text-secondary text-body max-w-sm font-medium">
|
||||
{description}
|
||||
@@ -116,7 +116,7 @@
|
||||
'after:border-offset after:-mt-px after:block after:h-0.5 after:w-full after:border-t-2 after:border-dashed'
|
||||
)}
|
||||
>
|
||||
{#each content as { type, title, url, label }}
|
||||
{#each content as { type, title: contentTitle, url, label }}
|
||||
<a href={url} class="group block cursor-pointer">
|
||||
<div
|
||||
class={classNames(
|
||||
@@ -129,7 +129,9 @@
|
||||
<span class="bg-smooth w-fit rounded-[4px] px-2 py-0.5"
|
||||
>{type}</span
|
||||
>
|
||||
<span class="font-aeonik-pro text-label">{title}</span>
|
||||
<span class="font-aeonik-pro text-label"
|
||||
>{contentTitle}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
{label ?? 'Read article'}
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
import embla from 'embla-carousel-svelte';
|
||||
import type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from 'embla-carousel';
|
||||
import { Button, Icon } from '$lib/components/ui';
|
||||
import EventFutureOfAppwrite from '../(assets)/eventFutureOfAppwrite.png';
|
||||
import EventLiveDemo from '../(assets)/eventLiveDemo.png';
|
||||
import EventBuildingWithFlutter from '../(assets)/eventBuildingWithFlutter.png';
|
||||
import EventClosingParty from '../(assets)/eventClosingParty.png';
|
||||
import EventIndustryPanel from '../(assets)/eventIndustryPanel.png';
|
||||
|
||||
let emblaApi: EmblaCarouselType;
|
||||
|
||||
@@ -40,6 +45,29 @@
|
||||
.on('select', togglePrevNextBtnsState)
|
||||
.on('reInit', togglePrevNextBtnsState);
|
||||
};
|
||||
|
||||
const events = [
|
||||
{
|
||||
poster: EventFutureOfAppwrite,
|
||||
title: 'The future of Appwrite'
|
||||
},
|
||||
{
|
||||
poster: EventLiveDemo,
|
||||
title: 'Live demo'
|
||||
},
|
||||
{
|
||||
poster: EventBuildingWithFlutter,
|
||||
title: 'Building with Flutter'
|
||||
},
|
||||
{
|
||||
poster: EventIndustryPanel,
|
||||
title: 'Industry panel'
|
||||
},
|
||||
{
|
||||
poster: EventClosingParty,
|
||||
title: 'Closing party'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<div class="border-offset relative min-h-[45vh] border-y-2 border-dashed bg-black/14 py-24">
|
||||
@@ -70,10 +98,13 @@
|
||||
on:emblaInit={onEmblaInit}
|
||||
>
|
||||
<div class="embla__container flex">
|
||||
{#each Array.from({ length: 8 }) as _}
|
||||
{#each events as _}
|
||||
<div
|
||||
class="embla__slide bg-card/90 mr-4 h-[180px] min-w-0 [flex:0_0_33%] rounded-lg"
|
||||
></div>
|
||||
class="embla__slide bg-card/90 mr-4 min-w-0 [flex:0_0_33%] items-center rounded-lg p-4"
|
||||
>
|
||||
<img src={_.poster} class="m-auto rounded-t" />
|
||||
<h3 class="mt-0.5 text-base font-medium">{_.title}</h3>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
<script lang="ts">
|
||||
import TicketCard from '../tickets/(components)/ticket-card.svelte';
|
||||
import Avatar from '../(assets)/avatar.png';
|
||||
import InitGiveaway from '../(assets)/init-giveaway.png';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { Button } from '$lib/components/ui';
|
||||
import { Media } from '$lib/UI';
|
||||
</script>
|
||||
|
||||
<div class="container grid min-h-[65vh] w-full grid-cols-1 place-items-center py-20 md:grid-cols-2">
|
||||
<div
|
||||
class="container grid min-h-[65vh] w-full grid-cols-1 place-items-center py-5 md:grid-cols-2 md:py-20"
|
||||
>
|
||||
<div class="flex flex-col gap-12">
|
||||
<Media
|
||||
src={InitGiveaway}
|
||||
alt="Init giveaway"
|
||||
class="web-media md:max-h-[304px] md:max-w-[467px]"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<h2 class="text-title text-primary font-aeonik-pro mb-4">
|
||||
Get a ticket and enter<br /> our Init giveaway
|
||||
Get a ticket and<br />enter our giveaway
|
||||
</h2>
|
||||
<p class="text-secondary text-body mb-8">
|
||||
Create, customize and share your ticket to get the chance to win exclusive Init swag.
|
||||
<p class="text-secondary text-body mb-6">
|
||||
Create, customize and share your ticket to get the chance to win exclusive Init
|
||||
swag.
|
||||
</p>
|
||||
<Button href="/init/tickets/customize" variant="secondary">Claim your ticket</Button>
|
||||
</div>
|
||||
<div class="relative flex w-full items-center">
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative me-8 hidden w-full items-center gap-4 md:me-0 md:flex md:scale-[1.073] md:gap-0"
|
||||
>
|
||||
<div style:transform="rotate(4deg)" class="absolute right-40 z-0">
|
||||
<TicketCard
|
||||
$id="1"
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Follow on Product Hunt
|
||||
Support on Product Hunt
|
||||
</Button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
<div class="group mt-2 w-fit min-w-[190px]">
|
||||
{#if type === 'video' || type === 'announcement'}
|
||||
<VideoDialog {url}>
|
||||
<VideoDialog {url} inlineVideo={false}>
|
||||
<div
|
||||
class="relative flex aspect-video w-full max-w-[190px] cursor-pointer flex-col items-center rounded-md outline-2 outline-offset-3 outline-[var(--color-offset)] outline-dashed"
|
||||
>
|
||||
<img
|
||||
src={Poster}
|
||||
src={poster}
|
||||
alt={title}
|
||||
class="absolute inset-0 object-cover transition-opacity group-hover:opacity-75"
|
||||
/>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script lang="ts" module>
|
||||
const base = new Date('2025-05-19T13:00:00.000Z');
|
||||
const base = new Date('2025-05-19T07:00:00.000Z');
|
||||
const otherFeaturesBase = new Date('2025-05-19T13:00:00.000Z');
|
||||
|
||||
export const isStarted = new Date() >= base;
|
||||
export const initDates = `${format(base, 'MMM d')} - ${format(addDays(base, 4), 'd')}`;
|
||||
export const initDates = `${format(base, 'MMM d')} - ${format(addDays(otherFeaturesBase, 4), 'd')}`;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -10,6 +11,8 @@
|
||||
|
||||
import CountdownGrid from './(components)/countdown-grid.svelte';
|
||||
import Poster from './(assets)/poster.png';
|
||||
import PosterFutureAppwrite from './(assets)/posterFutureOfAppwrite.png';
|
||||
import PosterDeploy from './(assets)/posterDeploy.png';
|
||||
import Sites from './(assets)/illustrations/sites.svg';
|
||||
import Flutter from './(assets)/illustrations/flutter.svg';
|
||||
import Formats from './(assets)/illustrations/formats.svg';
|
||||
@@ -20,6 +23,7 @@
|
||||
import Hero from './(components)/hero.svelte';
|
||||
import Giveaway from './(components)/giveaway.svelte';
|
||||
import EventCarousel from './(components)/event-carousel.svelte';
|
||||
import { FooterNav, MainFooter } from '$lib/components';
|
||||
|
||||
const title = 'Init - Appwrite';
|
||||
const description = 'The start of something new.';
|
||||
@@ -31,27 +35,32 @@
|
||||
|
||||
let days: Array<Omit<DayProps, 'index'>> = [
|
||||
{
|
||||
title: 'Feature',
|
||||
title: 'Sites',
|
||||
release: base,
|
||||
illustration: Sites,
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sed lacus lectus. Nunc gravida arcu posuere odio sagittis, ac congue lacus placerat.',
|
||||
url: '/',
|
||||
'Introducing the open-source Vercel alternative. A new Appwrite product that lets you deploy and host your websites and web apps right inside Appwrite.',
|
||||
url: 'https://www.youtube-nocookie.com/embed/0cERQxFjTW4',
|
||||
content: [
|
||||
{ title: 'Serverless functions 101: best practices', url: '/', type: 'Blog' },
|
||||
{
|
||||
title: 'Local serverless function development with the new Appwrite CLI',
|
||||
url: '/',
|
||||
title: 'Announcing Appwrite Sites',
|
||||
url: '/blog/post/announcing-appwrite-sites',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Local development',
|
||||
url: '/',
|
||||
type: 'Docs'
|
||||
title: 'How to host SSR web apps with Appwrite Sites',
|
||||
url: '/blog/post/host-ssr-web-apps-sites',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Get started with Appwrite Sites',
|
||||
url: '/docs/products/sites',
|
||||
type: 'Docs',
|
||||
label: 'Visit docs'
|
||||
}
|
||||
],
|
||||
announcementVideo: {
|
||||
url: 'https://www.youtube.com/watch?v=31udvDQ5I4Y',
|
||||
url: 'https://www.youtube-nocookie.com/embed/0cERQxFjTW4',
|
||||
title: 'Announcement Video',
|
||||
poster: Poster
|
||||
},
|
||||
@@ -59,93 +68,113 @@
|
||||
{
|
||||
title: 'Product demo',
|
||||
type: 'video',
|
||||
poster: '',
|
||||
url: 'https://www.youtube-nocookie.com/embed/31udvDQ5I4Y'
|
||||
poster: PosterDeploy,
|
||||
url: 'https://youtu.be/VtDe6hDw91k'
|
||||
},
|
||||
{ title: 'Discord Stage', type: 'discord', poster: '', url: 'https://discord.com' }
|
||||
{
|
||||
title: 'YouTube Live',
|
||||
type: 'video',
|
||||
poster: PosterFutureAppwrite,
|
||||
url: 'https://www.youtube.com/watch?v=1g8tuogsp7A'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Feature',
|
||||
release: addDays(base, 1),
|
||||
title: 'Flutter Web',
|
||||
release: addDays(otherFeaturesBase, 1),
|
||||
illustration: Flutter,
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sed lacus lectus. Nunc gravida arcu posuere odio sagittis, ac congue lacus placerat.',
|
||||
url: '/',
|
||||
'Appwrite and Flutter have always worked well together, and now, you can deploy your Flutter web apps directly from Appwrite Sites.',
|
||||
url: '/blog/post/hosting-flutter-web',
|
||||
content: [
|
||||
{ title: 'Serverless functions 101: best practices', url: '/', type: 'Blog' },
|
||||
{
|
||||
title: 'Local serverless function development with the new Appwrite CLI',
|
||||
url: '/',
|
||||
title: 'How to set up the Flutter starter template on Appwrite Sites',
|
||||
url: '/blog/post/flutter-starter-sites',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Local development',
|
||||
url: '/',
|
||||
type: 'Docs'
|
||||
title: 'Building with Appwrite Sites template',
|
||||
url: '/blog/post/building-with-sites-templates',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Hosting for Flutter Web',
|
||||
url: '/docs/products/sites/quick-start/flutter',
|
||||
type: 'Docs',
|
||||
label: 'Visit docs'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Key',
|
||||
release: addDays(base, 2),
|
||||
title: 'Dev Keys',
|
||||
release: addDays(otherFeaturesBase, 2),
|
||||
illustration: DevKeys,
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sed lacus lectus. Nunc gravida arcu posuere odio sagittis, ac congue lacus placerat.',
|
||||
url: '/',
|
||||
'Introducing Dev Keys. A new Appwrite feature that lets you bypass rate limits *during local development*. No more slowdowns. No more artificial blockers. Just fast, uninterrupted building.',
|
||||
url: '/blog/post/announcing-dev-keys',
|
||||
content: [
|
||||
{ title: 'Serverless functions 101: best practices', url: '/', type: 'Blog' },
|
||||
{
|
||||
title: 'Local serverless function development with the new Appwrite CLI',
|
||||
url: '/',
|
||||
title: 'Improve your Appwrite developer experience with Dev Keys',
|
||||
url: '/blog/post/improve-devex-dev-keys',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Local development',
|
||||
url: '/',
|
||||
type: 'Docs'
|
||||
title: 'Dev Keys',
|
||||
url: '/docs/advanced/platform/dev-keys',
|
||||
type: 'Docs',
|
||||
label: 'Visit docs'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Feature',
|
||||
release: addDays(base, 3),
|
||||
title: 'Image formats',
|
||||
release: addDays(otherFeaturesBase, 3),
|
||||
illustration: Formats,
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sed lacus lectus. Nunc gravida arcu posuere odio sagittis, ac congue lacus placerat.',
|
||||
url: '/',
|
||||
'We have added support for two new image formats in Appwrite Storage: HEIC and AVIF. This will give you more tools to manage, manipulate, and serve images the way you need.',
|
||||
url: '/blog/post/announcing-new-image-formats',
|
||||
content: [
|
||||
{ title: 'Serverless functions 101: best practices', url: '/', type: 'Blog' },
|
||||
{
|
||||
title: 'Local serverless function development with the new Appwrite CLI',
|
||||
url: '/',
|
||||
title: 'How to use AVIF in Storage',
|
||||
url: '/blog/pos/avif-in-storage',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Local development',
|
||||
url: '/',
|
||||
type: 'Docs'
|
||||
title: 'Improve your Appwrite developer experience with dev keys',
|
||||
url: '/blog/post/developer-experience-dev-keys',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'New image formats',
|
||||
url: '/docs/products/storage/images',
|
||||
type: 'Docs',
|
||||
label: 'Visit docs'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Feature',
|
||||
release: addDays(base, 4),
|
||||
title: 'File Tokens',
|
||||
release: addDays(otherFeaturesBase, 4),
|
||||
illustration: Tokens,
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sed lacus lectus. Nunc gravida arcu posuere odio sagittis, ac congue lacus placerat.',
|
||||
url: '/',
|
||||
'Introducing File Tokens. This feature lets you share files easily and securely, without modifying permissions or changing project access. Just generate a token and share the link.',
|
||||
url: 'https://youtu.be/_XU1dftsQag',
|
||||
content: [
|
||||
{ title: 'Serverless functions 101: best practices', url: '/', type: 'Blog' },
|
||||
{
|
||||
title: 'Local serverless function development with the new Appwrite CLI',
|
||||
url: '/',
|
||||
title: 'Serverless functions 101: best practices',
|
||||
url: '/blog/post/announcing-file-tokens',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'Local development',
|
||||
url: '/',
|
||||
type: 'Docs'
|
||||
title: 'file tokens',
|
||||
url: '/blog/post',
|
||||
type: 'Blog'
|
||||
},
|
||||
{
|
||||
title: 'File Tokens',
|
||||
url: '/docs/',
|
||||
type: 'Docs',
|
||||
label: 'Visit docs'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -181,6 +210,45 @@
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<EventCarousel />
|
||||
<Giveaway />
|
||||
<!-- <EventCarousel />-->
|
||||
{/if}
|
||||
|
||||
<Giveaway />
|
||||
|
||||
<div class="footer-section extended-borders-footer container">
|
||||
<FooterNav />
|
||||
|
||||
<MainFooter />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.extended-borders-footer {
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
.extended-borders-footer::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-top: 2px dashed var(--color-offset);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
height: 0;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
inset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
& :global(.web-footer-nav) {
|
||||
border-block-start: none;
|
||||
margin-block-start: unset;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
border-block-start: solid 0.0625rem hsl(var(--web-color-smooth));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
import { stickerPack } from '../customize/+page.svelte';
|
||||
import { initDates } from '../../+page.svelte';
|
||||
import { enhance } from '$app/forms';
|
||||
import InitGiveaway from '$routes/(init)/init/(assets)/init-giveaway.png';
|
||||
import { Media } from '$lib/UI';
|
||||
import { FooterNav, MainFooter } from '$lib/components';
|
||||
|
||||
const { data } = $props();
|
||||
|
||||
@@ -70,15 +73,17 @@
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="border-offset size-full border-dashed">
|
||||
<div class="outer-container border-offset border-b-2 border-dashed">
|
||||
<div class="container">
|
||||
<div class="border-offset grid min-h-[80vh] grid-cols-1 md:grid-cols-12">
|
||||
<div
|
||||
class="border-offset grid min-h-[80vh] grid-cols-1 border-b-2 border-dashed md:grid-cols-12"
|
||||
class="border-offset divide-offset grid place-items-center border-r-2 border-l-2 border-dashed md:col-span-6 md:border-r-0"
|
||||
>
|
||||
<div
|
||||
class="border-offset divide-offset grid place-items-center divide-y-2 divide-dashed border-r-2 border-l-2 border-dashed md:col-span-6 md:border-r-0"
|
||||
>
|
||||
<div class="row-span-2 hidden h-full w-full px-8 md:block"></div>
|
||||
<div class="row-span-8 flex h-full w-full items-center px-4 py-6 md:px-12">
|
||||
class="extended-borders-top row-span-2 hidden h-full w-full px-8 md:block"
|
||||
></div>
|
||||
<div class="flex h-full w-full items-center px-4 py-6 md:px-12">
|
||||
<div class="flex flex-1 flex-col gap-2">
|
||||
<a href="/init" class="text-primary group mb-2 flex items-center gap-2">
|
||||
<Icon
|
||||
@@ -99,8 +104,8 @@
|
||||
</h2>
|
||||
|
||||
<p class="text-body text-secondary mt-2 font-medium">
|
||||
Thank you for registering for Init. Share your ticket on social media to
|
||||
enter the raffle to win limited edition swag.
|
||||
Thank you for registering for Init. Share your ticket on social
|
||||
media to enter the raffle to win limited edition swag.
|
||||
</p>
|
||||
<div class="mt-8 flex items-center gap-4">
|
||||
{#if data.isCurrentUsersTicket}
|
||||
@@ -140,7 +145,7 @@
|
||||
<Spinner />
|
||||
{:else}
|
||||
<Icon name="github" class="text-primary" />
|
||||
{/if}Claim your TIcket</Button
|
||||
{/if}Claim your Ticket</Button
|
||||
>
|
||||
</form>
|
||||
|
||||
@@ -151,8 +156,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-span-2 h-full w-full px-8"></div>
|
||||
<div class="extended-borders-bottom row-span-2 h-full w-full px-8"></div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="border-offset flex flex-col items-center justify-center border-x-2 border-dashed bg-black/24 px-4 py-8 md:col-span-6"
|
||||
>
|
||||
@@ -175,3 +181,87 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container mt-[44px] flex flex-col md:mt-[87px]">
|
||||
<div class="mb-[87px] flex flex-col-reverse gap-4 md:flex-row md:justify-between">
|
||||
<div>
|
||||
<h2 class="text-title text-primary font-aeonik-pro md:mb-4">
|
||||
Get your ticket and<br />enter our giveaway
|
||||
</h2>
|
||||
<p class="text-secondary text-body mb-10 md:mb-6">
|
||||
Create, customize and share your ticket to<br />get the chance to win exclusive
|
||||
Init swag.
|
||||
</p>
|
||||
<Button href="/init/tickets/customize" variant="secondary">Claim your ticket</Button
|
||||
>
|
||||
</div>
|
||||
|
||||
<Media
|
||||
src={InitGiveaway}
|
||||
alt="Init giveaway"
|
||||
class="web-media mb-12 md:mb-0 md:max-h-[370px] md:max-w-[568px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="footer-section extended-borders-footer">
|
||||
<FooterNav />
|
||||
|
||||
<MainFooter />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.extended-borders-top,
|
||||
.extended-borders-bottom,
|
||||
.extended-borders-footer {
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.extended-borders-top::after,
|
||||
.extended-borders-bottom::before,
|
||||
.extended-borders-footer::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-top: 2px dashed var(--color-offset);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.extended-borders-top::after {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: -100%;
|
||||
}
|
||||
|
||||
.extended-borders-bottom::before {
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: -100%;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
right: -100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.extended-borders-footer::before {
|
||||
left: -100%;
|
||||
right: -100%;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
& :global(.web-footer-nav) {
|
||||
border-block-start: none;
|
||||
margin-block-start: unset;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
border-block-start: solid 0.0625rem hsl(var(--web-color-smooth));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import { inView, animate } from 'motion';
|
||||
import NumberFlow from '@number-flow/svelte';
|
||||
import { inView } from 'motion-legacy';
|
||||
import { onDestroy } from 'svelte';
|
||||
import KCollectTestimonialImage from '../../../products/sites/kcollect-ryan-testimonial.png';
|
||||
|
||||
const animationDuration = 3;
|
||||
|
||||
let stats = $state([
|
||||
let stats = [
|
||||
{
|
||||
number: 0,
|
||||
suffix: '+',
|
||||
@@ -30,26 +32,63 @@
|
||||
description: 'projects',
|
||||
top: 46.75
|
||||
}
|
||||
]);
|
||||
];
|
||||
|
||||
let alternateStats = [
|
||||
{
|
||||
number: 0,
|
||||
suffix: 'K+',
|
||||
description: 'Github stars',
|
||||
top: 93.75
|
||||
},
|
||||
{
|
||||
number: 0,
|
||||
suffix: '+',
|
||||
description: 'PoP locations',
|
||||
top: 78.25
|
||||
},
|
||||
{
|
||||
number: 0,
|
||||
suffix: 'K+',
|
||||
description: 'developers',
|
||||
top: 62.5
|
||||
},
|
||||
{
|
||||
number: 0,
|
||||
suffix: 'B+',
|
||||
description: 'monthly database operations',
|
||||
top: 46.75
|
||||
}
|
||||
];
|
||||
|
||||
const numbers = [12, 1000, 50, 300];
|
||||
const alternateNumbers = [50, 300, 300, 200];
|
||||
|
||||
let shouldAnimate: boolean = false;
|
||||
let animate: boolean = false;
|
||||
|
||||
let timeoutIds: Array<NodeJS.Timeout> = [];
|
||||
const updateNumbers = () => {
|
||||
correctStats.forEach((stat, index) => {
|
||||
const timeoutId = setTimeout(
|
||||
() => {
|
||||
correctStats[index] = { ...stat, number: correctNumbers[index] };
|
||||
},
|
||||
((index * animationDuration) / correctNumbers.length) * 500
|
||||
);
|
||||
|
||||
timeoutIds.push(timeoutId);
|
||||
});
|
||||
};
|
||||
|
||||
const useInView = (node: HTMLElement) => {
|
||||
shouldAnimate = true;
|
||||
inView(node, () => {
|
||||
if (!shouldAnimate) return;
|
||||
stats.forEach((stat, index) => {
|
||||
animate(0, numbers[index], {
|
||||
ease: 'circOut',
|
||||
duration: 0.75,
|
||||
onUpdate: (latest) => (stat.number = +latest.toFixed())
|
||||
});
|
||||
});
|
||||
});
|
||||
inView(
|
||||
node,
|
||||
() => {
|
||||
animate = true;
|
||||
updateNumbers();
|
||||
},
|
||||
{ amount: 0.5 }
|
||||
);
|
||||
};
|
||||
|
||||
const clearAllTimeouts = () => {
|
||||
@@ -63,10 +102,42 @@
|
||||
onDestroy(() => {
|
||||
clearAllTimeouts();
|
||||
});
|
||||
|
||||
export let theme: 'light' | 'dark' = 'dark';
|
||||
export let alternateInfo: boolean = false;
|
||||
|
||||
const correctStats = alternateInfo ? alternateStats : stats;
|
||||
const correctNumbers = alternateInfo ? alternateNumbers : numbers;
|
||||
const testimonial = {
|
||||
name: 'Ryan O’Conner',
|
||||
copy: `The switch to using Appwrite brought infinite value that I'm still discovering today, but a major impact that it made was the amount of time and stress that it saved me as it simply just works.`,
|
||||
image: KCollectTestimonialImage,
|
||||
title: 'Founder',
|
||||
company: 'K-Collect'
|
||||
};
|
||||
|
||||
const getCorrectText = () => {
|
||||
if (!alternateInfo) {
|
||||
return {
|
||||
partOne: 'Appwrite has supported our recent growth in every step of the way,',
|
||||
partTwo: 'without any failures or outages.'
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
partOne: 'The switch to using Appwrite brought',
|
||||
partTwo: "infinite value that I'm still discovering today."
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const text = getCorrectText();
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="border-smooth relative flex min-h-[750px] flex-col gap-4 border-y bg-black/8 py-20"
|
||||
class={classNames(
|
||||
'relative flex min-h-[70vh] flex-col gap-4',
|
||||
theme === 'dark' ? 'border-smooth border-y bg-black/8 py-20' : ''
|
||||
)}
|
||||
use:useInView
|
||||
>
|
||||
<div class="relative z-10 container w-fit md:w-full">
|
||||
@@ -77,23 +148,39 @@
|
||||
>
|
||||
</h2>
|
||||
<p class="text-secondary border-accent mt-5 border-l-2 pr-28 pl-2 font-medium">
|
||||
<span class="text-accent">"</span>Appwrite has supported our recent growth in every
|
||||
step of the way,
|
||||
<span class="text-primary">without any failures or outages</span><span
|
||||
class="text-accent">"</span
|
||||
>
|
||||
<span class="text-accent">“</span>{text.partOne}
|
||||
<span class="text-primary">{text.partTwo}</span><span class="text-accent">”</span>
|
||||
</p>
|
||||
|
||||
{#if alternateInfo}
|
||||
<div class="mt-4 flex items-center gap-3">
|
||||
<img
|
||||
src={testimonial.image}
|
||||
class="size-6 rounded-full"
|
||||
alt="{testimonial.company} Logo"
|
||||
/>
|
||||
<div class="flex gap-1">
|
||||
<span class="text-primary text-sub-body block font-medium">
|
||||
{testimonial.name},
|
||||
</span>
|
||||
<span class="text-sub-body text-secondary block"
|
||||
>{testimonial.title} at {testimonial.company}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-12 block space-y-8 md:hidden">
|
||||
{#each stats as stat, i}
|
||||
{#each correctStats as stat, i}
|
||||
<div class="h-full overflow-auto pl-6">
|
||||
<div class={classNames('relative')} style:top={`${(4 - i) * 18}%`}>
|
||||
<span
|
||||
<NumberFlow
|
||||
class="text-description text-primary border-accent relative -left-px z-10 border-l pl-4 font-medium"
|
||||
>{stat.number}{stat.suffix}</span
|
||||
>
|
||||
value={stat.number}
|
||||
suffix={stat.suffix}
|
||||
/>
|
||||
<span class="text-body text-secondary block pl-4">{stat.description}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -101,87 +188,65 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="swipe absolute inset-0 hidden md:block"
|
||||
class="swipe mask absolute inset-0 hidden md:block"
|
||||
style:--animation-duration={`${animationDuration}s`}
|
||||
style:--mask-height="50px"
|
||||
>
|
||||
<div class="relative container h-full">
|
||||
<div class="absolute inset-0 z-100 grid grid-cols-4">
|
||||
{#each stats as stat, i}
|
||||
{#each correctStats as stat, i}
|
||||
<div
|
||||
class="border-smooth h-full overflow-auto border-l border-dashed [mask-image:_linear-gradient(to_bottom,_transparent,_black_var(--mask-height),_black_calc(100%_-_var(--mask-height)),_black)]"
|
||||
class="mask border-smooth h-full overflow-auto border-l"
|
||||
style:--mask-direction="bottom"
|
||||
style:--mask-height={`${(4 - i) * 25}%`}
|
||||
>
|
||||
<div class={classNames('relative')} style:top={`${(4 - i) * 18}%`}>
|
||||
<span
|
||||
<NumberFlow
|
||||
class="text-description text-primary border-accent relative -left-px z-10 border-l pl-4 font-medium"
|
||||
>{stat.number}{stat.suffix}</span
|
||||
>
|
||||
value={stat.number}
|
||||
suffix={stat.suffix}
|
||||
/>
|
||||
<span class="text-body text-secondary block pl-4"
|
||||
>{stat.description}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="absolute inset-0">
|
||||
{#each stats as _, i}
|
||||
<!-- <div class="pointer-events-none absolute inset-0 z-50">
|
||||
{#each correctStats as stat, i}
|
||||
<div
|
||||
class="dot border-accent absolute top-0 left-0 z-10 h-2 w-2 rounded-full border bg-white"
|
||||
style:offset-distance={`${i * (100 / stats.length) + 12.5}%`}
|
||||
class="border-accent absolute top-[var(--top)] left-[calc(var(--left)_+_1px)] h-2 w-2 -translate-1/2 rounded-full border bg-white"
|
||||
style:--top={`${stat.top}%`}
|
||||
style:--left="{i * 25}%"
|
||||
></div>
|
||||
{/each}
|
||||
</div> -->
|
||||
<svg
|
||||
class="absolute inset-x-0 bottom-0 h-auto"
|
||||
fill="none"
|
||||
viewBox="0 0 1728 563"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="none"
|
||||
>
|
||||
<path d="M0 563.5L1728 1V563.5H0Z" fill="url(#b)" stroke="url(#a)" />
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="b"
|
||||
x1="-467"
|
||||
x2="1787"
|
||||
y1="753"
|
||||
y2="24.5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#FD366E" stop-opacity=".16" offset="0" />
|
||||
<stop stop-color="#FD366E" stop-opacity="0" offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="a"
|
||||
x1="-94"
|
||||
x2="1730.1"
|
||||
y1="578"
|
||||
y2="7.8097"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#FD366E" offset="0" />
|
||||
<stop stop-color="#FD366E" stop-opacity=".48" offset=".21402" />
|
||||
<stop stop-color="#FD366E" stop-opacity=".2" offset=".7712" />
|
||||
<stop stop-color="#FD366E" stop-opacity="0" offset="1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="from-accent/15 absolute inset-0 bg-gradient-to-tr to-transparent [clip-path:polygon(0_100%,_100%_25%,_100%_100%,_0_100%)]"
|
||||
></div>
|
||||
<div
|
||||
class="from-accent absolute inset-0 bg-gradient-to-r to-transparent [clip-path:polygon(0_100%,_100%_25%,_100%_25.1%,_0_100.1%)]"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--path-width: 1200px;
|
||||
--path-height: 358px;
|
||||
}
|
||||
.dot {
|
||||
offset-path: path('M var(--path-width) var(--path-height) L 0 749.5');
|
||||
}
|
||||
.swipe {
|
||||
animation: wipe-in var(--animation-duration) ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes mask-wipe {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wipe-in {
|
||||
0% {
|
||||
clip-path: polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%);
|
||||
|
||||