bradduy commited on
Commit
eb0c817
·
1 Parent(s): ae01397
src/app/(auth)/layout.tsx ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ClerkProvider } from '@clerk/nextjs';
2
+ import { setRequestLocale } from 'next-intl/server';
3
+ export default async function AuthLayout(props: {
4
+ children: React.ReactNode;
5
+ params: Promise<{ locale: string }>;
6
+ }) {
7
+ const { locale } = await props.params;
8
+ setRequestLocale(locale);
9
+ let signInUrl = '/sign-in';
10
+ let signUpUrl = '/sign-up';
11
+ let dashboardUrl = '/dashboard';
12
+ let afterSignOutUrl = '/';
13
+ signInUrl = `/${signInUrl}`;
14
+ signUpUrl = `/${signUpUrl}`;
15
+ dashboardUrl = `/`;
16
+ afterSignOutUrl = `/${afterSignOutUrl}`;
17
+ return (
18
+ <ClerkProvider
19
+ localization={{
20
+ signIn: {
21
+ start: {
22
+ title: 'Sign In',
23
+ },
24
+ },
25
+ signUp: {
26
+ start: {
27
+ title: 'Sign Up',
28
+ },
29
+ },
30
+ }}
31
+ signInUrl={signInUrl}
32
+ signUpUrl={signUpUrl}
33
+ signInFallbackRedirectUrl={dashboardUrl}
34
+ signUpFallbackRedirectUrl={dashboardUrl}
35
+ afterSignOutUrl={afterSignOutUrl}
36
+ >
37
+ <div className="mx-auto flex w-full items-center justify-center pt-32">
38
+ {props.children}
39
+ </div>
40
+ </ClerkProvider>
41
+ );
42
+ }
src/app/(auth)/sign-in/page.tsx ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { SignIn } from '@clerk/nextjs';
2
+ type ISignInPageProps = {
3
+ params: Promise<{ locale: string }>;
4
+ };
5
+ export default async function SignInPage(_props: ISignInPageProps) {
6
+ return (
7
+ <SignIn
8
+ path="/sign-in"
9
+ signUpUrl="/sign-up"
10
+ />
11
+ );
12
+ };
src/components/atoms/Card/index.tsx ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { cn } from '@/utils/Helpers';
2
+ import * as React from 'react';
3
+
4
+ const Card = ({ ref, className, ...props }: React.HTMLAttributes<HTMLDivElement> & { ref?: React.RefObject<HTMLDivElement> }) => (
5
+ <div ref={ref} className={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)} {...props} />
6
+ );
7
+ Card.displayName = 'Card';
8
+
9
+ const CardHeader = ({ ref, className, ...props }: React.HTMLAttributes<HTMLDivElement> & { ref: React.RefObject<HTMLDivElement> }) => (
10
+ <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
11
+ );
12
+ CardHeader.displayName = 'CardHeader';
13
+
14
+ const CardTitle = ({ ref, className, ...props }: React.HTMLAttributes<HTMLHeadingElement> & { ref: React.RefObject<HTMLParagraphElement> }) => (
15
+ // eslint-disable-next-line jsx-a11y/heading-has-content
16
+ <h3 ref={ref} className={cn('text-2xl font-semibold leading-none tracking-tight', className)} {...props} />
17
+ );
18
+ CardTitle.displayName = 'CardTitle';
19
+
20
+ const CardDescription = ({ ref, className, ...props }: React.HTMLAttributes<HTMLParagraphElement> & { ref: React.RefObject<HTMLParagraphElement> }) => (
21
+ <p ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
22
+ );
23
+ CardDescription.displayName = 'CardDescription';
24
+
25
+ const CardContent = ({ ref, className, ...props }: React.HTMLAttributes<HTMLDivElement> & { ref?: React.RefObject<HTMLDivElement> }) => <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />;
26
+ CardContent.displayName = 'CardContent';
27
+
28
+ const CardFooter = ({ ref, className, ...props }: React.HTMLAttributes<HTMLDivElement> & { ref: React.RefObject<HTMLDivElement> }) => (
29
+ <div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
30
+ );
31
+ CardFooter.displayName = 'CardFooter';
32
+
33
+ export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
src/components/homepage/AnnouncementBanner.tsx ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Badge, Button } from '@/components/atoms';
2
+ import { ChevronDown, Download } from 'lucide-react';
3
+ import Image from 'next/image';
4
+
5
+ export function AnnouncementBanner() {
6
+ return (
7
+ <>
8
+ <div className="container flex flex-col items-center gap-4 text-center">
9
+ <Badge className="rounded-lg" variant="secondary">
10
+ NEW
11
+ {' '}
12
+ <span className="mx-1">+</span>
13
+ {' '}
14
+ v0.5.14 is now live on GitHub. Check it out!
15
+ </Badge>
16
+
17
+ <span className="text-4xl">❝</span>
18
+
19
+ <h1 className="font-heading text-3xl sm:text-5xl md:text-6xl lg:text-7xl">
20
+ Chat with AI
21
+ <br />
22
+ without privacy concerns
23
+ </h1>
24
+
25
+ <p className="max-w-2xl leading-normal text-muted-foreground sm:text-xl sm:leading-8">
26
+ Jan is an open source ChatGPT-alternative that runs 100% offline.
27
+ </p>
28
+
29
+ <div className="space-y-4">
30
+ <Button className="h-11 px-8" size="lg">
31
+ <Download className="mr-2 size-4" />
32
+ Download for Windows
33
+ <ChevronDown className="ml-2 size-4" />
34
+ </Button>
35
+ <p className="text-xs text-muted-foreground">
36
+ <span className="font-semibold text-yellow-500">2.5M+</span>
37
+ {' '}
38
+ downloads | Free & Open Source
39
+ </p>
40
+ </div>
41
+ </div>
42
+
43
+ <div className="container">
44
+ <div className="relative mx-auto aspect-video max-w-5xl overflow-hidden rounded-xl border bg-background shadow-xl">
45
+ <Image
46
+ src="https://sjc.microlink.io/-ax0tIqUfnMYpO1Y6sFNuRcGN_Oe6cQwpzrnQR5q5pzkpfA29UGKZ228lDnpeQCpNANORBcNBmQgFoOtLn18vw.jpeg"
47
+ alt="Jan AI Interface"
48
+ fill
49
+ className="object-cover"
50
+ priority
51
+ />
52
+ </div>
53
+ </div>
54
+ </>
55
+ );
56
+ }
src/components/homepage/CustomizationSection.tsx ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Badge, Card } from '@/components/atoms';
2
+ import Image from 'next/image';
3
+
4
+ export function CustomizationSection() {
5
+ return (
6
+ <section className="container space-y-16 py-24">
7
+ <div className="space-y-4 text-center">
8
+ <h2 className="font-heading text-4xl md:text-5xl lg:text-6xl">Highly Customizable</h2>
9
+ <p className="text-xl text-muted-foreground">Customize Jan to match your needs and preferences.</p>
10
+ </div>
11
+
12
+ <div className="grid gap-8 md:grid-cols-2">
13
+ {/* Assistants & Memory Card */}
14
+ <Card className="space-y-4 p-6">
15
+ <div className="space-y-2">
16
+ <div className="flex items-center gap-2">
17
+ <h3 className="text-2xl font-semibold">Assistants & Memory</h3>
18
+ <Badge variant="secondary" className="bg-blue-100 text-blue-700 hover:bg-blue-100">
19
+ Coming Soon
20
+ </Badge>
21
+ </div>
22
+ <p className="text-muted-foreground">
23
+ Create personalized AI assistants that remember your conversations and execute specific tasks across your
24
+ systems.
25
+ </p>
26
+ </div>
27
+
28
+ <Image
29
+ src="https://jan.ai/assets/images/homepage/assistant-light.png"
30
+ alt="App Screenshot Feature"
31
+ width={800}
32
+ height={800}
33
+ className="object-contain"
34
+ />
35
+ </Card>
36
+
37
+ {/* Extensions Card */}
38
+ <Card className="space-y-4 p-6">
39
+ <div className="space-y-2">
40
+ <h3 className="text-2xl font-semibold">Extensions</h3>
41
+ <p className="text-muted-foreground">
42
+ Customize Jan with Extensions, that range from Cloud AI connectors, tools, data connectors.
43
+ </p>
44
+ </div>
45
+
46
+ <Image
47
+ src="https://jan.ai/assets/images/homepage/extension-light.png"
48
+ alt="App Screenshot Feature"
49
+ width={800}
50
+ height={800}
51
+ className="object-contain"
52
+ />
53
+ </Card>
54
+ </div>
55
+ </section>
56
+ );
57
+ }
src/components/homepage/FeatureSection.tsx ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Badge } from '@/components/atoms';
2
+ import { Cloud, FileText, Grid, MessageCircle, Server } from 'lucide-react';
3
+ import Image from 'next/image';
4
+
5
+ const features = [
6
+ {
7
+ number: '01',
8
+ title: 'Chat with AI',
9
+ description: 'Ask your questions, brainstorm, and learn from the AI running on your device to be more productive.',
10
+ icon: MessageCircle,
11
+ },
12
+ {
13
+ number: '02',
14
+ title: 'Model Hub',
15
+ description: 'Access and manage various AI models directly from your device.',
16
+ icon: Grid,
17
+ },
18
+ {
19
+ number: '03',
20
+ title: 'Connect to Cloud AIs',
21
+ description: 'Seamlessly integrate with cloud-based AI services when needed.',
22
+ icon: Cloud,
23
+ },
24
+ {
25
+ number: '04',
26
+ title: 'Local API Server',
27
+ description: 'Run your own API server locally for complete control and privacy.',
28
+ icon: Server,
29
+ },
30
+ {
31
+ number: '05',
32
+ title: 'Chat with your files',
33
+ description: 'Interact with your documents and files using natural language.',
34
+ icon: FileText,
35
+ experimental: true,
36
+ },
37
+ ];
38
+
39
+ export function FeaturesSection() {
40
+ return (
41
+ <section className="container space-y-16 py-24">
42
+ <h2 className="font-heading text-4xl md:text-5xl lg:text-6xl">Features</h2>
43
+
44
+ <div className="grid items-start gap-8 lg:grid-cols-2">
45
+ <div className="space-y-8">
46
+ {features.map(feature => (
47
+ <div key={feature.number} className="flex items-center gap-4">
48
+ <div className="font-heading text-3xl text-muted-foreground/50">{feature.number}</div>
49
+ <div className="space-y-2">
50
+ <div className="flex items-center gap-2">
51
+ <h3 className="text-xl font-semibold">{feature.title}</h3>
52
+ {feature.experimental && (
53
+ <Badge variant="secondary" className="text-xs">
54
+ Experimental
55
+ </Badge>
56
+ )}
57
+ </div>
58
+ <p className="text-muted-foreground">{feature.description}</p>
59
+ </div>
60
+ </div>
61
+ ))}
62
+ </div>
63
+
64
+ <Image
65
+ src="https://jan.ai/assets/images/homepage/features01.png"
66
+ alt="App Screenshot Feature"
67
+ width={800}
68
+ height={800}
69
+ />
70
+ </div>
71
+ </section>
72
+ );
73
+ }