Added custome field env for client side, and auto click next for feature section
This commit is contained in:
parent
3df00ef534
commit
083d10c927
@ -403,6 +403,11 @@ const config = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Put your custom environment here
|
||||||
|
customFields: {
|
||||||
|
apiKeyBrevo: process.env.API_KEY_BREVO,
|
||||||
|
},
|
||||||
|
|
||||||
themes: ['@docusaurus/theme-live-codeblock', '@docusaurus/theme-mermaid'],
|
themes: ['@docusaurus/theme-live-codeblock', '@docusaurus/theme-mermaid'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,17 +39,17 @@
|
|||||||
"prism-react-renderer": "^1.3.5",
|
"prism-react-renderer": "^1.3.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-hook-form": "^7.47.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.11.0",
|
||||||
"react-tweet": "^3.2.0",
|
"react-tweet": "^3.2.0",
|
||||||
"redocusaurus": "^2.0.0",
|
"redocusaurus": "^2.0.0",
|
||||||
"sass": "^1.69.3",
|
"sass": "^1.69.3",
|
||||||
"tailwind-merge": "^2.1.0",
|
"tailwind-merge": "^2.1.0",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3"
|
||||||
"react-hook-form": "^7.47.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "^3.0.0",
|
"@docusaurus/module-type-aliases": "^3.0.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.4.5",
|
||||||
"tailwindcss-animate": "^1.0.7"
|
"tailwindcss-animate": "^1.0.7"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
|
||||||
import { AiOutlineGithub, AiOutlineTwitter } from 'react-icons/ai'
|
import { AiOutlineGithub, AiOutlineTwitter } from 'react-icons/ai'
|
||||||
import { BiLogoDiscordAlt, BiLogoLinkedin } from 'react-icons/bi'
|
import { BiLogoDiscordAlt, BiLogoLinkedin } from 'react-icons/bi'
|
||||||
import { useForm } from 'react-hook-form'
|
import { useForm } from 'react-hook-form'
|
||||||
@ -106,12 +107,16 @@ const menus = [
|
|||||||
const getCurrentYear = new Date().getFullYear()
|
const getCurrentYear = new Date().getFullYear()
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
const { register, handleSubmit } = useForm({
|
const { register, handleSubmit, reset } = useForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
email: '',
|
email: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
siteConfig: { customFields },
|
||||||
|
} = useDocusaurusContext()
|
||||||
|
|
||||||
const onSubmit = (data) => {
|
const onSubmit = (data) => {
|
||||||
const { email } = data
|
const { email } = data
|
||||||
const options = {
|
const options = {
|
||||||
@ -119,7 +124,7 @@ export default function Footer() {
|
|||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json',
|
'accept': 'application/json',
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'api-key': process.env.API_KEY_BREVO,
|
'api-key': customFields.apiKeyBrevo,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
updateEnabled: false,
|
updateEnabled: false,
|
||||||
@ -131,6 +136,11 @@ export default function Footer() {
|
|||||||
if (email) {
|
if (email) {
|
||||||
fetch('https://api.brevo.com/v3/contacts', options)
|
fetch('https://api.brevo.com/v3/contacts', options)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
|
.then((response) => {
|
||||||
|
if (response.id) {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch((err) => console.error(err))
|
.catch((err) => console.error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import DownloadApp from '@site/src/containers/DownloadApp'
|
import DownloadApp from '@site/src/containers/DownloadApp'
|
||||||
import { Tweet } from 'react-tweet'
|
import { Tweet } from 'react-tweet'
|
||||||
import { useForm } from 'react-hook-form'
|
import { useForm } from 'react-hook-form'
|
||||||
@ -21,7 +21,13 @@ import Dropdown from '@site/src/containers/Elements/dropdown'
|
|||||||
|
|
||||||
import useIsBrowser from '@docusaurus/useIsBrowser'
|
import useIsBrowser from '@docusaurus/useIsBrowser'
|
||||||
|
|
||||||
const tabel = {
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
|
||||||
|
|
||||||
|
import Svg from '@site/static/img/homepage/features01dark.svg'
|
||||||
|
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
const table = {
|
||||||
labels: [
|
labels: [
|
||||||
'Ownership',
|
'Ownership',
|
||||||
'Openness',
|
'Openness',
|
||||||
@ -57,6 +63,26 @@ const tabel = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
title: 'Run local AI or connect to remote APIs',
|
||||||
|
description:
|
||||||
|
'Choose between running AI models locally for privacy, like Llama or Mistral, or connect to remote APIs, like ChatGPT or Claude.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Browse and download models',
|
||||||
|
description: `With Jan's Hub, instantly download popular AI models or import your own to expand your toolkit without hassle.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Use Jan in your natural workflows',
|
||||||
|
description: `Jan works with your workflow, ready to assist at a moment's notice without interrupting your work.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Customize and add features with Extensions',
|
||||||
|
description: `Tailor Jan exactly to your needs with Extensions, making your experience truly your own.`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const isBrowser = useIsBrowser()
|
const isBrowser = useIsBrowser()
|
||||||
const { stargazers } = useAppStars()
|
const { stargazers } = useAppStars()
|
||||||
@ -71,12 +97,16 @@ export default function Home() {
|
|||||||
const userAgent = isBrowser && navigator.userAgent
|
const userAgent = isBrowser && navigator.userAgent
|
||||||
const isBrowserChrome = isBrowser && userAgent.includes('Chrome')
|
const isBrowserChrome = isBrowser && userAgent.includes('Chrome')
|
||||||
|
|
||||||
const { register, handleSubmit } = useForm({
|
const { register, handleSubmit, reset } = useForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
email: '',
|
email: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
siteConfig: { customFields },
|
||||||
|
} = useDocusaurusContext()
|
||||||
|
|
||||||
const onSubmit = (data) => {
|
const onSubmit = (data) => {
|
||||||
const { email } = data
|
const { email } = data
|
||||||
const options = {
|
const options = {
|
||||||
@ -84,7 +114,7 @@ export default function Home() {
|
|||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json',
|
'accept': 'application/json',
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'api-key': process.env.API_KEY_BREVO,
|
'api-key': customFields.apiKeyBrevo,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
updateEnabled: false,
|
updateEnabled: false,
|
||||||
@ -96,10 +126,30 @@ export default function Home() {
|
|||||||
if (email) {
|
if (email) {
|
||||||
fetch('https://api.brevo.com/v3/contacts', options)
|
fetch('https://api.brevo.com/v3/contacts', options)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
|
.then((response) => {
|
||||||
|
if (response.id) {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch((err) => console.error(err))
|
.catch((err) => console.error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [activeFeature, setActiveFeature] = useState(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeFeature < 3) {
|
||||||
|
setTimeout(() => {
|
||||||
|
setActiveFeature(activeFeature + 1)
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
if (activeFeature === 3) {
|
||||||
|
setTimeout(() => {
|
||||||
|
setActiveFeature(0)
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
}, [activeFeature])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Banner />
|
<Banner />
|
||||||
@ -243,14 +293,14 @@ export default function Home() {
|
|||||||
|
|
||||||
{/* Feature */}
|
{/* Feature */}
|
||||||
<div className="w-full xl:w-10/12 mx-auto relative py-8">
|
<div className="w-full xl:w-10/12 mx-auto relative py-8">
|
||||||
<div className="flex p-4 lg:justify-between flex-col lg:flex-row items-end">
|
<div className="flex p-4 lg:px-0 lg:justify-between flex-col lg:flex-row items-end">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<h1 className="text-5xl lg:text-7xl !font-normal leading-tight lg:leading-tight mt-2 font-serif">
|
<h1 className="text-5xl lg:text-7xl !font-normal leading-tight lg:leading-tight mt-2 font-serif">
|
||||||
Jan redefines <br className="hidden lg:block" /> how we use
|
Jan redefines <br className="hidden lg:block" /> how we use
|
||||||
computers
|
computers
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-10 w-full lg:w-1/2 mr-auto text-right">
|
<div className="mt-10 w-full lg:w-1/2 mr-auto lg:text-right">
|
||||||
<a
|
<a
|
||||||
className="mt-6 text-blue-600 dark:text-blue-400 cursor-pointer"
|
className="mt-6 text-blue-600 dark:text-blue-400 cursor-pointer"
|
||||||
href="https://jan.ai/features/"
|
href="https://jan.ai/features/"
|
||||||
@ -260,6 +310,47 @@ export default function Home() {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-8 mt-10">
|
||||||
|
<div className="w-full lg:w-2/5 px-4 lg:p-0">
|
||||||
|
{features.map((feature, i) => {
|
||||||
|
const isActive = activeFeature === i
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="mb-4 dark:bg-[#1F1F1F] bg-[#F5F5F5] p-6 rounded-xl cursor-pointer"
|
||||||
|
onClick={() => setActiveFeature(i)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={twMerge(
|
||||||
|
'flex items-center gap-4',
|
||||||
|
isActive && 'items-start'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<h1 className="dark:text-[#4C4C4C] text-[#C4C4C4]">
|
||||||
|
0{i + 1}
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
<h6 className="text-xl">{feature.title}</h6>
|
||||||
|
<p
|
||||||
|
className={twMerge(
|
||||||
|
'mt-1 leading-relaxed text-black/60 dark:text-white/60 hidden',
|
||||||
|
isActive && 'block'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{feature.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative w-full -right-[10%] rounded-l-3xl overflow-hidden">
|
||||||
|
<Svg />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Philosophy */}
|
{/* Philosophy */}
|
||||||
@ -471,7 +562,7 @@ export default function Home() {
|
|||||||
<div className="mt-20 flex dark:bg-[#181818] bg-[#FAFAFA] border border-gray-300 dark:border-gray-600 rounded-t-2xl border-b-0">
|
<div className="mt-20 flex dark:bg-[#181818] bg-[#FAFAFA] border border-gray-300 dark:border-gray-600 rounded-t-2xl border-b-0">
|
||||||
<div className="w-56 lg:w-80 border-r border-gray-300 dark:border-gray-600">
|
<div className="w-56 lg:w-80 border-r border-gray-300 dark:border-gray-600">
|
||||||
<div className="p-7"></div>
|
<div className="p-7"></div>
|
||||||
{tabel.labels.map((label, i) => {
|
{table.labels.map((label, i) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="border-t border-gray-300 dark:border-gray-600 p-4 font-bold text-left"
|
className="border-t border-gray-300 dark:border-gray-600 p-4 font-bold text-left"
|
||||||
@ -486,7 +577,7 @@ export default function Home() {
|
|||||||
|
|
||||||
<div className="w-full lg:w-1/2 border-r border-gray-300 dark:border-gray-600 hidden md:block">
|
<div className="w-full lg:w-1/2 border-r border-gray-300 dark:border-gray-600 hidden md:block">
|
||||||
<h6 className="p-4 mb-0">Status Quo</h6>
|
<h6 className="p-4 mb-0">Status Quo</h6>
|
||||||
{tabel.statusQuo.map((label, i) => {
|
{table.statusQuo.map((label, i) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="border-t border-gray-300 dark:border-gray-600 p-4"
|
className="border-t border-gray-300 dark:border-gray-600 p-4"
|
||||||
@ -510,7 +601,7 @@ export default function Home() {
|
|||||||
/>
|
/>
|
||||||
<h6 className="mb-0">Jan</h6>
|
<h6 className="mb-0">Jan</h6>
|
||||||
</div>
|
</div>
|
||||||
{tabel.jan.map((label, i) => {
|
{table.jan.map((label, i) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="border-t border-gray-300 dark:border-gray-600 p-4"
|
className="border-t border-gray-300 dark:border-gray-600 p-4"
|
||||||
|
|||||||
3
docs/static/img/homepage/features01dark.svg
vendored
Normal file
3
docs/static/img/homepage/features01dark.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 1.9 MiB |
@ -5166,10 +5166,10 @@ dot-prop@^6.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-obj "^2.0.0"
|
is-obj "^2.0.0"
|
||||||
|
|
||||||
dotenv@^16.3.1:
|
dotenv@^16.4.5:
|
||||||
version "16.3.1"
|
version "16.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
|
||||||
integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
|
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
|
||||||
|
|
||||||
duplexer@^0.1.2:
|
duplexer@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user