Skip to content

Commit a212e85

Browse files
authored
various changes to add terms and security info (#225)
* add terms and security to footer * add security card * add demo card
1 parent eab0007 commit a212e85

File tree

11 files changed

+220
-71
lines changed

11 files changed

+220
-71
lines changed

packages/web/src/app/[domain]/onboard/components/connectCodeHost.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { CodeHostIconButton } from "../../components/codeHostIconButton";
1717
import useCaptureEvent from "@/hooks/useCaptureEvent";
1818
import { useSession } from "next-auth/react";
1919
import posthog from "posthog-js";
20+
import SecurityCard from "@/app/components/securityCard";
2021

2122
interface ConnectCodeHostProps {
2223
nextStep: OnboardingSteps;
@@ -48,7 +49,10 @@ export const ConnectCodeHost = ({ nextStep }: ConnectCodeHostProps) => {
4849

4950
if (!selectedCodeHost) {
5051
return (
51-
<CodeHostSelection onSelect={setSelectedCodeHost} />
52+
<>
53+
<CodeHostSelection onSelect={setSelectedCodeHost} />
54+
<SecurityCard />
55+
</>
5256
)
5357
}
5458

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"use client"
2+
3+
import { ExternalLink } from "lucide-react"
4+
import Link from "next/link"
5+
6+
import { Button } from "@/components/ui/button"
7+
import { Card, CardContent } from "@/components/ui/card"
8+
import useCaptureEvent from "@/hooks/useCaptureEvent"
9+
10+
export default function DemoCard() {
11+
const captureEvent = useCaptureEvent();
12+
13+
return (
14+
<Card className="mb-6 w-full border bg-card text-card-foreground">
15+
<CardContent className="p-4">
16+
<div className="flex flex-col space-y-4">
17+
<div className="flex items-center justify-between">
18+
<div className="space-y-1">
19+
<h3 className="text-sm font-medium">New to Sourcebot?</h3>
20+
<p className="text-xs text-muted-foreground">Try our public demo before creating an account</p>
21+
</div>
22+
23+
<Button asChild variant="outline" size="sm" className="h-8 text-xs">
24+
<Link
25+
href="https://sourcebot.dev/search"
26+
target="_blank"
27+
className="flex items-center gap-1.5"
28+
onClick={() => captureEvent('wa_demo_card_click', {})}
29+
>
30+
Try demo
31+
<ExternalLink className="h-3.5 w-3.5" />
32+
</Link>
33+
</Button>
34+
</div>
35+
</div>
36+
</CardContent>
37+
</Card>
38+
)
39+
}

packages/web/src/app/[domain]/onboard/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { InviteTeam } from "./components/inviteTeam";
77
import { CompleteOnboarding } from "./components/completeOnboarding";
88
import { Checkout } from "./components/checkout";
99
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
10+
import SecurityCard from "@/app/components/securityCard";
11+
1012
interface OnboardProps {
1113
params: {
1214
domain: string

packages/web/src/app/[domain]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { UpgradeToast } from "./components/upgradeToast";
55
import Link from "next/link";
66
import { getOrgFromDomain } from "@/data/org";
77
import { PageNotFound } from "./components/pageNotFound";
8-
import { Footer } from "./components/footer";
8+
import { Footer } from "@/app/components/footer";
99
import { SourcebotLogo } from "../components/sourcebotLogo";
1010
import { RepositorySnapshot } from "./components/repositorySnapshot";
1111
import { KeyboardShortcutHint } from "./components/keyboardShortcutHint";

packages/web/src/app/[domain]/repos/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default async function ReposPage({ params: { domain } }: { params: { doma
1313
<Header>
1414
<h1 className="text-3xl">Repositories</h1>
1515
</Header>
16-
<div className="h-screen flex flex-col items-center">
16+
<div className="flex flex-col items-center">
1717
<div className="w-full">
1818
<RepositoryTable />
1919
</div>

packages/web/src/app/[domain]/components/footer.tsx renamed to packages/web/src/app/components/footer.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ export function Footer() {
66
<footer className="w-full mt-auto py-4 flex flex-row justify-center items-center gap-4">
77
<Link href="https://sourcebot.dev" className="text-gray-400 text-sm hover:underline">About</Link>
88
<Separator orientation="vertical" className="h-4" />
9-
<Link href="https://github.com/sourcebot-dev/sourcebot/issues/new" className="text-gray-400 text-sm hover:underline">Support</Link>
9+
<Link href="https://sourcebot.dev/terms" className="text-gray-400 text-sm hover:underline">Terms</Link>
10+
<Separator orientation="vertical" className="h-4" />
11+
<Link href="https://sourcebot.dev/security" className="text-gray-400 text-sm hover:underline">Security</Link>
1012
<Separator orientation="vertical" className="h-4" />
1113
<Link href="mailto:team@sourcebot.dev" className="text-gray-400 text-sm hover:underline">Contact Us</Link>
1214
</footer>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"use client"
2+
3+
import Link from "next/link"
4+
import { Shield, Lock, CheckCircle, ExternalLink, Mail } from "lucide-react"
5+
import useCaptureEvent from "@/hooks/useCaptureEvent"
6+
7+
export default function SecurityCard() {
8+
const captureEvent = useCaptureEvent();
9+
10+
return (
11+
<div className="mt-12 max-w-md mx-auto text-center">
12+
<div className="bg-backgroundSecondary border border-[#1E2A3A] rounded-lg p-6 shadow-lg">
13+
<div className="flex justify-center mb-4">
14+
<Shield className="h-10 w-10 text-[#9D5CFF]" />
15+
</div>
16+
<h3 className="text-xl font-semibold mb-3">Multi-Layered Security</h3>
17+
<p className="text-[#A1A1AA] mb-6">
18+
We take the security and privacy of your data seriously. All code and secret tokens you provide are protected
19+
using multiple layers of security.
20+
</p>
21+
22+
<div className="space-y-4 mb-5">
23+
<div className="flex items-start">
24+
<CheckCircle className="h-5 w-5 text-[#9D5CFF] mr-3 mt-0.5 flex-shrink-0" />
25+
<span className="text-sm text-foregroundSecondary text-left">
26+
All data is stored on Google Cloud Platform in the United States (us-west-1)
27+
</span>
28+
</div>
29+
30+
<div className="flex items-start">
31+
<CheckCircle className="h-5 w-5 text-[#9D5CFF] mr-3 mt-0.5 flex-shrink-0" />
32+
<span className="text-sm text-foregroundSecondary text-left">
33+
All data is encrypted in transit using TLS 1.2+, and at rest using AES-256
34+
</span>
35+
</div>
36+
37+
<div className="flex items-start">
38+
<CheckCircle className="h-5 w-5 text-[#9D5CFF] mr-3 mt-0.5 flex-shrink-0" />
39+
<div className="text-sm text-foregroundSecondary text-left">
40+
<div className="flex items-center">
41+
<span>Sourcebot is open-source and trusted by thousands of developers</span>
42+
<Link
43+
href="https://github.com/sourcebot-dev/sourcebot"
44+
target="_blank"
45+
className="inline-flex items-center ml-2 text-[#9D5CFF] hover:text-[#B47EFF] transition-colors"
46+
>
47+
<svg
48+
className="h-4 w-4 mr-0.5"
49+
fill="currentColor"
50+
viewBox="0 0 24 24"
51+
xmlns="http://www.w3.org/2000/svg"
52+
>
53+
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
54+
</svg>
55+
<ExternalLink className="h-3 w-3" />
56+
</Link>
57+
</div>
58+
</div>
59+
</div>
60+
</div>
61+
62+
<div className="text-sm text-[#A1A1AA] mb-5">
63+
Have questions?
64+
<Link
65+
href="mailto:team@sourcebot.dev"
66+
className="inline-flex items-center ml-2 text-[#9D5CFF] hover:text-[#B47EFF] transition-colors"
67+
>
68+
<Mail className="h-3.5 w-3.5 mr-1" />
69+
<span>Get in touch</span>
70+
</Link>
71+
</div>
72+
73+
<Link
74+
href="https://sourcebot.dev/security"
75+
target="_blank"
76+
className="inline-flex items-center justify-center px-5 py-2.5 rounded-md bg-backgroundSecondary border border-[#1E2A3A] text-foreground hover:bg-backgroundSecondary/80 transition-colors"
77+
onClick={() => captureEvent('wa_security_page_click', {})}
78+
>
79+
<Lock className="h-4 w-4 mr-2" />
80+
<span>Learn about our security measures</span>
81+
</Link>
82+
</div>
83+
</div>
84+
)
85+
}
86+

packages/web/src/app/login/components/loginForm.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { CredentialsForm } from "./credentialsForm";
1212
import { SourcebotLogo } from "@/app/components/sourcebotLogo";
1313
import { TextSeparator } from "@/app/components/textSeparator";
1414
import useCaptureEvent from "@/hooks/useCaptureEvent";
15-
15+
import DemoCard from "@/app/[domain]/onboard/components/demoCard";
1616
interface LoginFormProps {
1717
callbackUrl?: string;
1818
error?: string;
@@ -52,6 +52,9 @@ export const LoginForm = ({ callbackUrl, error, enabledMethods }: LoginFormProps
5252
/>
5353
<h2 className="text-lg font-bold text-center">Sign in to your account</h2>
5454
</div>
55+
<div className="w-full sm:w-[500px] max-w-[500px]">
56+
<DemoCard />
57+
</div>
5558
<Card className="flex flex-col items-center border p-6 sm:p-12 rounded-lg gap-4 sm:gap-6 w-full sm:w-[500px] max-w-[500px] bg-background">
5659
{error && (
5760
<div className="text-sm text-destructive text-center text-wrap border p-2 rounded-md border-destructive">

packages/web/src/app/login/page.tsx

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { auth } from "@/auth";
22
import { LoginForm } from "./components/loginForm";
33
import { redirect } from "next/navigation";
44
import { getProviders } from "@/auth";
5+
import { Footer } from "@/app/components/footer";
6+
57
interface LoginProps {
68
searchParams: {
79
callbackUrl?: string;
@@ -18,26 +20,29 @@ export default async function Login({ searchParams }: LoginProps) {
1820
const providers = getProviders();
1921
const providerMap = providers
2022
.map((provider) => {
21-
if (typeof provider === "function") {
22-
const providerData = provider()
23-
return { id: providerData.id, name: providerData.name }
24-
} else {
25-
return { id: provider.id, name: provider.name }
26-
}
27-
});
23+
if (typeof provider === "function") {
24+
const providerData = provider()
25+
return { id: providerData.id, name: providerData.name }
26+
} else {
27+
return { id: provider.id, name: provider.name }
28+
}
29+
});
2830

2931
return (
30-
<div className="flex flex-col items-center p-4 sm:p-12 min-h-screen w-full bg-backgroundSecondary">
31-
<LoginForm
32-
callbackUrl={searchParams.callbackUrl}
33-
error={searchParams.error}
34-
enabledMethods={{
35-
github: providerMap.some(provider => provider.id === "github"),
36-
google: providerMap.some(provider => provider.id === "google"),
37-
magicLink: providerMap.some(provider => provider.id === "nodemailer"),
38-
credentials: providerMap.some(provider => provider.id === "credentials"),
39-
}}
40-
/>
32+
<div className="flex flex-col min-h-screen">
33+
<div className="flex-1 flex flex-col items-center p-4 sm:p-12 w-full bg-backgroundSecondary">
34+
<LoginForm
35+
callbackUrl={searchParams.callbackUrl}
36+
error={searchParams.error}
37+
enabledMethods={{
38+
github: providerMap.some(provider => provider.id === "github"),
39+
google: providerMap.some(provider => provider.id === "google"),
40+
magicLink: providerMap.some(provider => provider.id === "nodemailer"),
41+
credentials: providerMap.some(provider => provider.id === "credentials"),
42+
}}
43+
/>
44+
</div>
45+
<Footer />
4146
</div>
4247
)
4348
}

packages/web/src/app/login/verify/page.tsx

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useCallback, useState, Suspense } from "react"
1212
import VerificationFailed from "./verificationFailed"
1313
import { SourcebotLogo } from "@/app/components/sourcebotLogo"
1414
import useCaptureEvent from "@/hooks/useCaptureEvent"
15+
import { Footer } from "@/app/components/footer"
1516

1617
function VerifyPageContent() {
1718
const [value, setValue] = useState("")
@@ -41,58 +42,61 @@ function VerifyPageContent() {
4142
}
4243

4344
return (
44-
<div className="flex flex-col items-center p-4 sm:p-12 min-h-screen w-full bg-backgroundSecondary">
45-
<div className="w-full max-w-md">
46-
<div className="flex justify-center mb-6">
47-
<SourcebotLogo className="h-16" size="large" />
48-
</div>
49-
<Card className="w-full shadow-lg border-muted/40">
50-
<CardHeader className="space-y-1">
51-
<CardTitle className="text-2xl font-bold text-center">Verify your email</CardTitle>
52-
<CardDescription className="text-center">
53-
Enter the 6-digit code we sent to <span className="font-semibold text-primary">{email}</span>
54-
</CardDescription>
55-
</CardHeader>
45+
<div className="flex flex-col min-h-screen">
46+
<div className="flex-1 flex flex-col items-center p-4 sm:p-12 w-full bg-backgroundSecondary">
47+
<div className="w-full max-w-md">
48+
<div className="flex justify-center mb-6">
49+
<SourcebotLogo className="h-16" size="large" />
50+
</div>
51+
<Card className="w-full shadow-lg border-muted/40">
52+
<CardHeader className="space-y-1">
53+
<CardTitle className="text-2xl font-bold text-center">Verify your email</CardTitle>
54+
<CardDescription className="text-center">
55+
Enter the 6-digit code we sent to <span className="font-semibold text-primary">{email}</span>
56+
</CardDescription>
57+
</CardHeader>
5658

57-
<CardContent>
58-
<form onSubmit={(e) => {
59-
e.preventDefault()
60-
handleSubmit()
61-
}} className="space-y-6">
62-
<div className="flex justify-center py-4">
63-
<InputOTP maxLength={6} value={value} onChange={setValue} onKeyDown={handleKeyDown} className="gap-2">
64-
<InputOTPGroup>
65-
<InputOTPSlot index={0} className="rounded-md border-input" />
66-
<InputOTPSlot index={1} className="rounded-md border-input" />
67-
<InputOTPSlot index={2} className="rounded-md border-input" />
68-
</InputOTPGroup>
69-
<InputOTPSeparator />
70-
<InputOTPGroup>
71-
<InputOTPSlot index={3} className="rounded-md border-input" />
72-
<InputOTPSlot index={4} className="rounded-md border-input" />
73-
<InputOTPSlot index={5} className="rounded-md border-input" />
74-
</InputOTPGroup>
75-
</InputOTP>
76-
</div>
77-
</form>
78-
</CardContent>
59+
<CardContent>
60+
<form onSubmit={(e) => {
61+
e.preventDefault()
62+
handleSubmit()
63+
}} className="space-y-6">
64+
<div className="flex justify-center py-4">
65+
<InputOTP maxLength={6} value={value} onChange={setValue} onKeyDown={handleKeyDown} className="gap-2">
66+
<InputOTPGroup>
67+
<InputOTPSlot index={0} className="rounded-md border-input" />
68+
<InputOTPSlot index={1} className="rounded-md border-input" />
69+
<InputOTPSlot index={2} className="rounded-md border-input" />
70+
</InputOTPGroup>
71+
<InputOTPSeparator />
72+
<InputOTPGroup>
73+
<InputOTPSlot index={3} className="rounded-md border-input" />
74+
<InputOTPSlot index={4} className="rounded-md border-input" />
75+
<InputOTPSlot index={5} className="rounded-md border-input" />
76+
</InputOTPGroup>
77+
</InputOTP>
78+
</div>
79+
</form>
80+
</CardContent>
7981

80-
<CardFooter className="flex flex-col space-y-4 pt-0">
81-
<Button variant="ghost" className="w-full text-sm" size="sm" onClick={() => window.history.back()}>
82-
<ArrowLeft className="mr-2 h-4 w-4" />
83-
Back to login
84-
</Button>
85-
</CardFooter>
86-
</Card>
87-
<div className="mt-8 text-center text-sm text-muted-foreground">
88-
<p>
89-
Having trouble?{" "}
90-
<a href="mailto:team@sourcebot.dev" className="text-primary hover:underline">
91-
Contact support
92-
</a>
93-
</p>
82+
<CardFooter className="flex flex-col space-y-4 pt-0">
83+
<Button variant="ghost" className="w-full text-sm" size="sm" onClick={() => window.history.back()}>
84+
<ArrowLeft className="mr-2 h-4 w-4" />
85+
Back to login
86+
</Button>
87+
</CardFooter>
88+
</Card>
89+
<div className="mt-8 text-center text-sm text-muted-foreground">
90+
<p>
91+
Having trouble?{" "}
92+
<a href="mailto:team@sourcebot.dev" className="text-primary hover:underline">
93+
Contact support
94+
</a>
95+
</p>
96+
</div>
9497
</div>
9598
</div>
99+
<Footer />
96100
</div>
97101
)
98102
}

0 commit comments

Comments
 (0)