Finalize responsive new web
127
docs/src/components/Elements/downloadLink.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const systemsTemplate = [
|
||||||
|
{
|
||||||
|
name: "Download for Mac (M1/M2)",
|
||||||
|
logo: require("@site/static/img/apple-logo-white.png").default,
|
||||||
|
fileFormat: "{appname}-mac-arm64-{tag}.dmg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Download for Mac (Intel)",
|
||||||
|
logo: require("@site/static/img/apple-logo-white.png").default,
|
||||||
|
fileFormat: "{appname}-mac-x64-{tag}.dmg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Download for Windows",
|
||||||
|
logo: require("@site/static/img/windows-logo-white.png").default,
|
||||||
|
fileFormat: "{appname}-win-x64-{tag}.exe",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Download for Linux",
|
||||||
|
logo: require("@site/static/img/linux-logo-white.png").default,
|
||||||
|
fileFormat: "{appname}-linux-amd64-{tag}.deb",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function classNames(...classes) {
|
||||||
|
return classes.filter(Boolean).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DownloadLink() {
|
||||||
|
const [systems, setSystems] = useState(systemsTemplate);
|
||||||
|
const [defaultSystem, setDefaultSystem] = useState(systems[0]);
|
||||||
|
|
||||||
|
const getLatestReleaseInfo = async (repoOwner, repoName) => {
|
||||||
|
const url = `https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`;
|
||||||
|
try {
|
||||||
|
const response = await axios.get(url);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const extractAppName = (fileName) => {
|
||||||
|
// Extract appname using a regex that matches the provided file formats
|
||||||
|
const regex = /^(.*?)-(?:mac|win|linux)-(?:arm64|x64|amd64)-.*$/;
|
||||||
|
const match = fileName.match(regex);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeDefaultSystem = async (systems) => {
|
||||||
|
const userAgent = navigator.userAgent;
|
||||||
|
|
||||||
|
const arc = await navigator?.userAgentData?.getHighEntropyValues([
|
||||||
|
"architecture",
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (userAgent.includes("Windows")) {
|
||||||
|
// windows user
|
||||||
|
setDefaultSystem(systems[2]);
|
||||||
|
} else if (userAgent.includes("Linux")) {
|
||||||
|
// linux user
|
||||||
|
setDefaultSystem(systems[3]);
|
||||||
|
} else if (
|
||||||
|
userAgent.includes("Mac OS") &&
|
||||||
|
arc &&
|
||||||
|
arc.architecture === "arm"
|
||||||
|
) {
|
||||||
|
setDefaultSystem(systems[0]);
|
||||||
|
} else {
|
||||||
|
setDefaultSystem(systems[1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateDownloadLinks = async () => {
|
||||||
|
try {
|
||||||
|
const releaseInfo = await getLatestReleaseInfo("janhq", "jan");
|
||||||
|
|
||||||
|
// Extract appname from the first asset name
|
||||||
|
const firstAssetName = releaseInfo.assets[0].name;
|
||||||
|
const appname = extractAppName(firstAssetName);
|
||||||
|
|
||||||
|
if (!appname) {
|
||||||
|
console.error(
|
||||||
|
"Failed to extract appname from file name:",
|
||||||
|
firstAssetName
|
||||||
|
);
|
||||||
|
changeDefaultSystem(systems);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove 'v' at the start of the tag_name
|
||||||
|
const tag = releaseInfo.tag_name.startsWith("v")
|
||||||
|
? releaseInfo.tag_name.substring(1)
|
||||||
|
: releaseInfo.tag_name;
|
||||||
|
|
||||||
|
const updatedSystems = systems.map((system) => {
|
||||||
|
const downloadUrl = system.fileFormat
|
||||||
|
.replace("{appname}", appname)
|
||||||
|
.replace("{tag}", tag);
|
||||||
|
return {
|
||||||
|
...system,
|
||||||
|
href: `https://github.com/janhq/jan/releases/download/${releaseInfo.tag_name}/${downloadUrl}`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setSystems(updatedSystems);
|
||||||
|
changeDefaultSystem(updatedSystems);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to update download links:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateDownloadLinks();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-2">
|
||||||
|
<a href={defaultSystem.href}>
|
||||||
|
<span className="text-blue-600 font-bold">Download Jan</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -76,6 +76,7 @@ export default function Dropdown() {
|
|||||||
setDefaultSystem(systems[1]);
|
setDefaultSystem(systems[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const updateDownloadLinks = async () => {
|
const updateDownloadLinks = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -5,38 +5,12 @@ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|||||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||||
import Layout from "@theme/Layout";
|
import Layout from "@theme/Layout";
|
||||||
import AnnoncementBanner from "@site/src/components/Announcement";
|
import AnnoncementBanner from "@site/src/components/Announcement";
|
||||||
import {
|
|
||||||
CloudArrowUpIcon,
|
import { AiOutlineGithub } from "react-icons/ai";
|
||||||
CursorArrowRaysIcon,
|
|
||||||
ShieldCheckIcon,
|
|
||||||
CpuChipIcon,
|
|
||||||
ClipboardDocumentIcon,
|
|
||||||
CubeTransparentIcon,
|
|
||||||
ComputerDesktopIcon,
|
|
||||||
FolderPlusIcon,
|
|
||||||
} from "@heroicons/react/24/outline";
|
|
||||||
import { AiOutlineGithub, AiOutlineTwitter } from "react-icons/ai";
|
|
||||||
|
|
||||||
import ThemedImage from "@theme/ThemedImage";
|
import ThemedImage from "@theme/ThemedImage";
|
||||||
|
|
||||||
const features = [
|
import DownloadLink from "@site/src/components/Elements/downloadLink";
|
||||||
{
|
|
||||||
name: "Personal AI that runs on your computer",
|
|
||||||
desc: "Jan runs directly on your local machine, offering privacy, convenience and customizability.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Extendable via App and Plugin framework",
|
|
||||||
desc: "Jan has a versatile app and plugin framework, allowing you to customize it to your needs.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Private and offline, your data never leaves your machine",
|
|
||||||
desc: "Your conversations and data are with an AI that runs on your computer, where only you have access.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "No subscription fees, the AI runs on your computer",
|
|
||||||
desc: "Say goodbye to monthly subscriptions or usage-based APIs. Jan runs 100% free on your own hardware.",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const { siteConfig } = useDocusaurusContext();
|
const { siteConfig } = useDocusaurusContext();
|
||||||
@ -45,19 +19,18 @@ export default function Home() {
|
|||||||
<AnnoncementBanner />
|
<AnnoncementBanner />
|
||||||
<Layout
|
<Layout
|
||||||
title={`${siteConfig.tagline}`}
|
title={`${siteConfig.tagline}`}
|
||||||
description="Jan runs Large Language Models locally on Windows, Mac and Linux.
|
description="Jan runs Large Language Models locally on Windows, Mac and Linux. Available on Desktop and Cloud-Native."
|
||||||
Available on Desktop and Cloud-Native."
|
|
||||||
>
|
>
|
||||||
<main className="bg-gray-50 dark:bg-gray-950/95 relative">
|
<main className="bg-gray-50 dark:bg-gray-950/95 relative">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{/* <ThemedImage
|
<ThemedImage
|
||||||
alt="App screenshot"
|
alt="App screenshot"
|
||||||
sources={{
|
sources={{
|
||||||
light: useBaseUrl("/img/bg-hero-light.svg"),
|
light: useBaseUrl("/img/bg-hero-light.svg"),
|
||||||
dark: useBaseUrl("/img/bg-hero-dark.svg"),
|
dark: useBaseUrl("/img/bg-hero-dark.svg"),
|
||||||
}}
|
}}
|
||||||
className="absolute w-full h-full opacity-10 dark:opacity-20 top-0 object-cover blur-3xl"
|
className="absolute w-full h-full opacity-10 dark:opacity-20 top-0 object-cover blur-3xl"
|
||||||
/> */}
|
/>
|
||||||
<div className="container py-16">
|
<div className="container py-16">
|
||||||
<div className="grid grid-cols-1 items-center gap-4">
|
<div className="grid grid-cols-1 items-center gap-4">
|
||||||
<div className="relative z-10 text-center ">
|
<div className="relative z-10 text-center ">
|
||||||
@ -72,7 +45,6 @@ export default function Home() {
|
|||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
<h1 className="bg-gradient-to-r dark:from-white from-black to-gray-500 dark:to-gray-400 bg-clip-text text-4xl lg:text-6xl font-bold leading-tight text-transparent dark:text-transparent lg:leading-tight">
|
<h1 className="bg-gradient-to-r dark:from-white from-black to-gray-500 dark:to-gray-400 bg-clip-text text-4xl lg:text-6xl font-bold leading-tight text-transparent dark:text-transparent lg:leading-tight">
|
||||||
Own your AI
|
Own your AI
|
||||||
</h1>
|
</h1>
|
||||||
@ -108,7 +80,6 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center relative ">
|
<div className="text-center relative ">
|
||||||
{/* <div className="el-blur-hero absolute -left-40 w-full top-1/2 -translate-y-1/2" /> */}
|
|
||||||
<div className="p-3 border dark:border-gray-500 border-gray-400 inline-block rounded-lg">
|
<div className="p-3 border dark:border-gray-500 border-gray-400 inline-block rounded-lg">
|
||||||
<ThemedImage
|
<ThemedImage
|
||||||
alt="App screenshot"
|
alt="App screenshot"
|
||||||
@ -124,36 +95,142 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="container mt-10 mb-20 text-center">
|
<div className="container mt-10 mb-20 text-center">
|
||||||
<h2>AI that you control</h2>
|
<h2>AI that you control</h2>
|
||||||
<p className="text-base mt-2 w-full lg:w-2/5 mx-auto leading-relaxed">
|
<p className="text-base mt-2 w-full lg:w-2/5 mx-auto leading-relaxed">
|
||||||
Private. Local. Infinitely Customizable.
|
Private. Local. Infinitely Customizable.
|
||||||
</p>
|
</p>
|
||||||
<div className="grid text-left lg:grid-cols-2 mt-16 gap-16">
|
<div className="grid text-left lg:grid-cols-2 mt-16 gap-4">
|
||||||
{features.map((feat, i) => {
|
<div className="card relative min-h-[380px] lg:min-h-[460px]">
|
||||||
return (
|
<img
|
||||||
<div
|
src="/img/card-element.png"
|
||||||
className="flex gap-x-4 p-8 rounded-3xl border bg-gray-100 border-gray-100 dark:border-[#202231] dark:bg-[#111217]"
|
alt="Element"
|
||||||
key={i}
|
className="absolute w-full bottom-0 left-0"
|
||||||
>
|
/>
|
||||||
<div>
|
<div class="p-8 relative z-40">
|
||||||
<h5>{feat.name}</h5>
|
<h5>Personal AI that runs on your computer</h5>
|
||||||
<p className="mt-2">{feat.desc}</p>
|
<p className="mt-2">
|
||||||
</div>
|
Jan runs directly on your local machine, offering privacy,
|
||||||
</div>
|
convenience and customizability.
|
||||||
);
|
</p>
|
||||||
})}
|
<ThemedImage
|
||||||
</div>
|
alt="Group Chat"
|
||||||
</div> */}
|
sources={{
|
||||||
<div class="container">
|
light: useBaseUrl("/img/group-chat-light.png"),
|
||||||
<div class="flex">
|
dark: useBaseUrl("/img/group-chat-dark.png"),
|
||||||
<div>
|
}}
|
||||||
<h1 className="text-7xl">Your AI, forever.</h1>
|
className="mt-10"
|
||||||
<p>Apps come and go, but your AI and data should last. </p>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card relative min-h-[380px] lg:min-h-[460px]">
|
||||||
|
<div className="p-8">
|
||||||
|
<h5>Extendable via App and Plugin framework</h5>
|
||||||
|
<p className="mt-2">
|
||||||
|
Jan has a versatile app and plugin framework, allowing you
|
||||||
|
to customize it to your needs.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ThemedImage
|
||||||
|
alt="Framework"
|
||||||
|
sources={{
|
||||||
|
light: useBaseUrl("/img/card-framework-light.png"),
|
||||||
|
dark: useBaseUrl("/img/card-framework-dark.png"),
|
||||||
|
}}
|
||||||
|
className="w-11/12 ml-auto mt-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="card relative min-h-[380px] lg:min-h-[460px]">
|
||||||
|
<div className="p-8">
|
||||||
|
<h5>
|
||||||
|
Private and offline, your data never leaves your machine
|
||||||
|
</h5>
|
||||||
|
<p className="mt-2">
|
||||||
|
Your conversations and data are with an AI that runs on your
|
||||||
|
computer, where only you have access.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ThemedImage
|
||||||
|
alt="Group Chat"
|
||||||
|
sources={{
|
||||||
|
light: useBaseUrl("/img/card-nitro-light.png"),
|
||||||
|
dark: useBaseUrl("/img/card-nitro-dark.png"),
|
||||||
|
}}
|
||||||
|
className="w-3/4 mx-auto mt-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="card relative min-h-[380px] lg:min-h-[460px]">
|
||||||
|
<div className="p-8">
|
||||||
|
<h5>No subscription fees, the AI runs on your computer</h5>
|
||||||
|
<p className="mt-2">
|
||||||
|
Say goodbye to monthly subscriptions or usage-based APIs.
|
||||||
|
Jan runs 100% free on your own hardware.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ThemedImage
|
||||||
|
alt="Group Chat"
|
||||||
|
sources={{
|
||||||
|
light: useBaseUrl("/img/card-free-light.png"),
|
||||||
|
dark: useBaseUrl("/img/card-free-dark.png"),
|
||||||
|
}}
|
||||||
|
className="w-full mt-auto mx-auto"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container py-20 text-center">
|
|
||||||
|
<div class="container lg:px-20 py-20 text-center lg:text-left">
|
||||||
|
<div class="flex flex-col lg:flex-row space-y-20 lg:space-y-0">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-7xl">Your AI, forever.</h1>
|
||||||
|
<p className="text-2xl mt-2">
|
||||||
|
Apps come and go, but your AI and data should last.{" "}
|
||||||
|
</p>
|
||||||
|
<div class="w-full lg:w-3/4 mt-8">
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-10 lg:gap-24">
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src="/img/ic-park-solid-unlock.svg"
|
||||||
|
alt="Icon - Lock"
|
||||||
|
className="w-8 mb-4 mx-auto lg:mx-0"
|
||||||
|
/>
|
||||||
|
<p>
|
||||||
|
Jan uses open, standard and non-proprietary files stored
|
||||||
|
locally on your device.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src="img/ic-baseline-control-camera.svg"
|
||||||
|
alt="Icon - Camera"
|
||||||
|
className="w-8 mb-4 mx-auto lg:mx-0"
|
||||||
|
/>
|
||||||
|
<p>
|
||||||
|
You have total control over your AI, which means you can
|
||||||
|
use Jan offline and switch to another app easily if you
|
||||||
|
want.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full lg:w-80 text-center">
|
||||||
|
<ThemedImage
|
||||||
|
alt="App screenshot"
|
||||||
|
sources={{
|
||||||
|
light: useBaseUrl("/img/jan-icon-light.png"),
|
||||||
|
dark: useBaseUrl("/img/jan-icon-dark.png"),
|
||||||
|
}}
|
||||||
|
className="w-40 lg:w-full mx-auto"
|
||||||
|
/>
|
||||||
|
<p className="mt-1 font-bold">100% free on your own hardware</p>
|
||||||
|
<DownloadLink />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container pb-20 pt-10 text-center">
|
||||||
<h2>
|
<h2>
|
||||||
We are open-source. <br /> Join Jan community.
|
We are open-source. <br /> Join Jan community.
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
0px 1px 2px 0px #525154 inset;
|
0px 1px 2px 0px #525154 inset;
|
||||||
}
|
}
|
||||||
.card {
|
.card {
|
||||||
@apply p-8 rounded-3xl border bg-gray-100 border-gray-100 dark:border-[#202231] dark:bg-[#111217];
|
@apply rounded-3xl border bg-gray-100 border-gray-100 dark:border-[#202231] dark:bg-[#111217];
|
||||||
|
|
||||||
&-link {
|
&-link {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
BIN
docs/static/img/card-element.png
vendored
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/static/img/card-framework-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
docs/static/img/card-framework-light.png
vendored
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
docs/static/img/card-free-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
docs/static/img/card-free-light.png
vendored
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
docs/static/img/card-nitro-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
docs/static/img/card-nitro-light.png
vendored
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
docs/static/img/group-chat-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
docs/static/img/group-chat-light.png
vendored
Normal file
|
After Width: | Height: | Size: 139 KiB |
4
docs/static/img/ic-baseline-control-camera.svg
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="36" height="37" viewBox="0 0 36 37" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M23.31 8.41986L20.655 11.0599L18 8.41986L15.345 11.0599L12.69 8.41986L18 3.10986L23.31 8.41986ZM27.69 23.4199L25.05 20.7649L27.69 18.1099L25.05 15.4549L27.69 12.7999L33 18.1099L27.69 23.4199ZM12.69 27.7999L15.345 25.1599L18 27.7999L20.655 25.1599L23.31 27.7999L18 33.1099L12.69 27.7999ZM8.31 12.7999L10.95 15.4549L8.31 18.1099L10.95 20.7649L8.31 23.4199L3 18.1099L8.31 12.7999Z" fill="#3B82F6"/>
|
||||||
|
<path d="M18 22.6099C20.4853 22.6099 22.5 20.5951 22.5 18.1099C22.5 15.6246 20.4853 13.6099 18 13.6099C15.5147 13.6099 13.5 15.6246 13.5 18.1099C13.5 20.5951 15.5147 22.6099 18 22.6099Z" fill="#3B82F6"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 712 B |
10
docs/static/img/ic-park-solid-unlock.svg
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<svg width="36" height="37" viewBox="0 0 36 37" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="mask0_206_5233" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="3" y="1" width="30" height="34">
|
||||||
|
<path d="M29.25 16.6458H6.75C5.92157 16.6458 5.25 17.3173 5.25 18.1458V31.6458C5.25 32.4742 5.92157 33.1458 6.75 33.1458H29.25C30.0784 33.1458 30.75 32.4742 30.75 31.6458V18.1458C30.75 17.3173 30.0784 16.6458 29.25 16.6458Z" fill="white" stroke="white" stroke-width="3" stroke-linejoin="round"/>
|
||||||
|
<path d="M10.5 16.6097V10.6135C10.4963 6.76224 13.4423 3.53499 17.3145 3.14799C21.1868 2.76099 24.7253 5.34024 25.5 9.11424" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M18 22.6099V27.1099" stroke="black" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0_206_5233)">
|
||||||
|
<path d="M0 0.109863H36V36.1099H0V0.109863Z" fill="#3B82F6"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 940 B |
BIN
docs/static/img/jan-icon-dark.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
docs/static/img/jan-icon-light.png
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |