Skip to content

Commit 66c2a67

Browse files
authored
Merge pull request #128 from saasfly/update-ui-2.0
ui 2.0
2 parents c170222 + 9f76e71 commit 66c2a67

27 files changed

Lines changed: 1226 additions & 245 deletions

apps/nextjs/next.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const config = {
2626
// serverActions: true,
2727
},
2828
images: {
29-
domains: ["images.unsplash.com", "avatars.githubusercontent.com"],
29+
domains: ["images.unsplash.com", "avatars.githubusercontent.com", "www.twillot.com", "cdnv2.ruguoapp.com"],
3030
},
3131
/** We already do linting and typechecking as separate tasks in CI */
3232
eslint: { ignoreDuringBuilds: true },

apps/nextjs/src/app/[lang]/(docs)/layout.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export default async function DocsLayout({
1919
children,
2020
params: { lang },
2121
}: DocsLayoutProps) {
22-
// const dashboardConfig = await getDashboardConfig({ params: { lang } });
2322
const dict = await getDictionary(lang);
2423
const user = await getCurrentUser();
2524

apps/nextjs/src/app/[lang]/(marketing)/page.tsx

Lines changed: 124 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,61 @@
11
import Link from "next/link";
2+
import Image from "next/image";
3+
import { getDictionary } from "~/lib/get-dictionary";
4+
5+
import { CodeCopy } from "~/components/code-copy";
6+
import { Comments } from "~/components/comments";
7+
import { FeaturesGrid } from "~/components/features-grid";
8+
import { RightsideMarketing } from "~/components/rightside-marketing";
29

10+
import { AnimatedTooltip } from "@saasfly/ui/animated-tooltip";
11+
import { BackgroundLines } from "@saasfly/ui/background-lines";
12+
import { Button } from "@saasfly/ui/button";
13+
import { ColourfulText } from "@saasfly/ui/colorful-text";
314
import * as Icons from "@saasfly/ui/icons";
415

5-
import { XBlogArticle } from "~/components/blog-card";
6-
import { Comments } from "~/components/comments";
7-
import { DocumentGuide } from "~/components/document-guide";
8-
import { FeaturesCard } from "~/components/features-card";
9-
import { Meteorss } from "~/components/meteors-card";
10-
import { Questions } from "~/components/questions";
11-
import ShimmerButton from "~/components/shimmer-button";
12-
import { TypewriterEffectSmooths } from "~/components/typewriterEffectSmooth";
13-
import { WobbleCardShow } from "~/components/wobble";
14-
import { WordReveal } from "~/components/word-reveal";
1516
import type { Locale } from "~/config/i18n-config";
16-
import { getDictionary } from "~/lib/get-dictionary";
17-
import type { Meteor } from "~/types/meteors";
17+
import {VideoScroll} from "~/components/video-scroll";
1818

19-
const meteors_data: Meteor = {
20-
name: "Join our Discord",
21-
description:
22-
"Join our Discord server to chat with other developers and get help.",
23-
button_content: "Chat with us",
24-
url: "https://discord.gg/8SwSX43wnD",
25-
};
19+
const people = [
20+
{
21+
id: 1,
22+
name: "tianzx",
23+
designation: "CEO at Nextify",
24+
image: "https://avatars.githubusercontent.com/u/10096899",
25+
link: "https://x.com/nextify2024",
26+
},
27+
{
28+
id: 2,
29+
name: "jackc3",
30+
designation: "Co-founder at Nextify",
31+
image: "https://avatars.githubusercontent.com/u/10334353",
32+
link: "https://x.com/BingxunYao",
33+
},
34+
{
35+
id: 3,
36+
name: "imesong",
37+
designation: "Contributor",
38+
image: "https://avatars.githubusercontent.com/u/3849293",
39+
},
40+
{
41+
id: 4,
42+
name: "ziveen",
43+
designation: "Contributor",
44+
image: "https://avatars.githubusercontent.com/u/22560152",
45+
},
46+
{
47+
id: 5,
48+
name: "Zenuncl",
49+
designation: "Independent Software Developer",
50+
image: "https://avatars.githubusercontent.com/u/3316062",
51+
},
52+
{
53+
id: 6,
54+
name: "Innei",
55+
designation: "Indie Developer",
56+
image: "https://avatars.githubusercontent.com/u/41265413",
57+
},
58+
];
2659

2760
export default async function IndexPage({
2861
params: { lang },
@@ -35,108 +68,107 @@ export default async function IndexPage({
3568

3669
return (
3770
<>
38-
<section className="w-full px-8 sm:px-48 md:px-48 xl:h-[100vh] xl:px-48">
39-
<div className="grid grid-cols-1 gap-10 pb-10 md:pb-40 xl:grid-cols-2">
40-
<div className="flex flex-col items-start">
41-
<div className="flex flex-col pt-4 md:pt-28 lg:pt-28 xl:pt-28">
42-
<Link href="https://document.saasfly.io" target="_blank">
43-
<DocumentGuide>
44-
{dict.marketing.introducing || "Introducing Saasfly"}
45-
</DocumentGuide>
46-
</Link>
47-
48-
<div className="mt-6">
49-
<h1 className="relative mb-6 max-w-4xl text-left text-4xl font-bold dark:text-zinc-100 sm:text-7xl md:text-7xl xl:text-7xl">
50-
{dict.marketing.title ||
51-
"Saasfly: A new SaaS player? Make things easier."}
52-
</h1>
53-
</div>
71+
<section className="container">
72+
<div className="grid grid-cols-1 gap-10 xl:grid-cols-2">
73+
<div className="flex flex-col items-start h-full">
74+
<BackgroundLines className="h-full">
75+
<div className="flex flex-col pt-4 md:pt-36 lg:pt-36 xl:pt-36">
76+
<div className="mt-20">
77+
<div
78+
className="mb-6 max-w-4xl text-left text-4xl font-semibold dark:text-zinc-100 md:text-5xl xl:text-5xl md:leading-[4rem] xl:leading-[4rem]">
79+
{dict.marketing.title || "Ship your apps to the world easier with "}
80+
<ColourfulText text="Saasfly"/>
81+
</div>
82+
</div>
5483

55-
<div>
56-
<span className="text-zinc-500 sm:text-xl">
57-
{dict.marketing.sub_title ||
58-
"Your complete All-in-One solution for building SaaS services."}
84+
<div className="mt-4">
85+
<span className="text-neutral-500 dark:text-neutral-400 sm:text-lg">
86+
{dict.marketing.sub_title || "Your complete All-in-One solution for building SaaS services."}
5987
</span>
60-
<TypewriterEffectSmooths />
61-
</div>
88+
</div>
6289

63-
<div className="mb-4 mt-6 flex w-full flex-col justify-center space-y-4 sm:flex-row sm:justify-start sm:space-x-8 sm:space-y-0">
64-
<Link href={`${lang}/login`}>
65-
<ShimmerButton className="mx-auto flex justify-center">
66-
<span className="z-10 w-48 whitespace-pre bg-gradient-to-b from-black from-30% to-gray-300/80 bg-clip-text text-center text-sm font-semibold leading-none tracking-tight text-white dark:from-white dark:to-slate-900/10 dark:text-transparent">
90+
<div
91+
className="mb-4 mt-6 flex w-full flex-col justify-center space-y-4 sm:flex-row sm:justify-start sm:space-x-8 sm:space-y-0 z-10">
92+
<Link href="https://github.com/saasfly/saasfly" target="_blank">
93+
<Button
94+
className="bg-blue-600 hover:bg-blue-500 text-white rounded-full text-lg px-6 h-12 font-medium">
6795
{dict.marketing.get_started}
68-
</span>
69-
</ShimmerButton>
70-
</Link>
71-
72-
<Link href="https://github.com/saasfly/saasfly" target="_blank">
73-
<div className="flex h-full items-center justify-center">
74-
<Icons.GitHub className="mr-2 h-6 w-6" />
75-
<span className="text-base font-semibold">
76-
{dict.marketing.view_on_github || "View on GitHub"}
77-
</span>
96+
<Icons.ArrowRight className="h-5 w-5"/>
97+
</Button>
98+
</Link>
99+
100+
<CodeCopy/>
101+
</div>
102+
103+
<div className="flex xl:flex-row flex-col items-center justify-start mt-4 w-full">
104+
<div className="flex">
105+
<AnimatedTooltip items={people}/>
106+
</div>
107+
<div className="flex flex-col items-center justify-start ml-8">
108+
<div className="w-[340px]">
109+
<text className="font-semibold">9 </text>
110+
<text
111+
className="text-neutral-500 dark:text-neutral-400">{dict.marketing.contributors.contributors_desc}</text>
112+
</div>
113+
<div className="w-[340px]">
114+
<text
115+
className="text-neutral-500 dark:text-neutral-400">{dict.marketing.contributors.developers_first}</text>
116+
<ColourfulText text="2000"/>
117+
<text
118+
className="text-neutral-500 dark:text-neutral-400">{dict.marketing.contributors.developers_second}</text>
119+
</div>
78120
</div>
79-
</Link>
121+
</div>
80122
</div>
81-
</div>
123+
</BackgroundLines>
82124
</div>
83125

84-
<div className="hidden h-full w-full xl:block">
85-
<div className="flex flex-col pt-28">
86-
<Meteorss meteor={meteors_data} />
87-
<div className="mt-4 flex w-full justify-between">
88-
<XBlogArticle />
89-
<div className="ml-4">
90-
<FeaturesCard />
91-
</div>
92-
</div>
126+
<div className="hidden h-full w-full xl:block bg-background">
127+
<div className="flex flex-col pt-44">
128+
<RightsideMarketing dict={dict.marketing.right_side}/>
93129
</div>
94130
</div>
95131
</div>
96132
</section>
97133

98-
<section className="hidden h-[100vh] w-full xl:block">
99-
<div className="flex h-full w-full justify-between px-[220px]">
100-
<div className="flex w-[60%] flex-col pr-4 pt-40">
101-
<WobbleCardShow />
102-
</div>
103-
<div className="h-full w-[40%]">
104-
<div className="flex flex-col pl-[120px]">
105-
<WordReveal />
106-
</div>
107-
</div>
108-
</div>
134+
<section className="container mt-8 md:mt-[-180px] xl:mt-[-180px]">
135+
<FeaturesGrid dict={dict.marketing.features_grid}/>
109136
</section>
110137

111-
<section className="hidden h-[100vh] w-full xl:block">
112-
<div className="flex h-full w-full justify-between px-[220px]">
113-
<div className="flex w-[60%] flex-col pr-4 pt-40">
114-
<div className="px-[120px]">
115-
<Questions />
116-
</div>
138+
<section className="container pt-24">
139+
<div className="flex flex-col justify-center items-center pt-10">
140+
<div className="text-lg text-neutral-500 dark:text-neutral-400">{dict.marketing.sponsor.title}</div>
141+
<div className="mt-4 flex items-center gap-4">
142+
<Link href="https://www.twillot.com/" target="_blank">
143+
<Image src="https://www.twillot.com/logo-128.png" width="48" height="48" alt="twillot"/>
144+
</Link>
145+
<Link href="https://opencollective.com/saasfly" target="_blank">
146+
<div className="flex items-center gap-2 px-4 py-2 rounded-xl border-2 border-dashed border-neutral-300 dark:border-neutral-700 hover:bg-accent dark:hover:bg-neutral-800/30">
147+
<Icons.Heart className="w-5 h-5 fill-pink-600 text-pink-600 dark:fill-pink-700 dark:text-pink-700"/>
148+
<span className="text-sm font-medium text-neutral-500 dark:text-neutral-200">{dict.marketing.sponsor.donate || ''}</span>
149+
</div>
150+
</Link>
117151
</div>
118152
</div>
119153
</section>
120154

121-
<section className="w-full px-8 xl:hidden">
122-
<Questions />
155+
<section className="container pt-8">
156+
<VideoScroll dict={dict.marketing.video}/>
123157
</section>
124158

125-
<section className="w-full px-8 pt-10 sm:px-0 sm:pt-0 md:px-0 md:pt-0 xl:px-0 xl:pt-0">
159+
<section className="w-full px-8 pt-10 sm:px-0 sm:pt-24 md:px-0 md:pt-24 xl:px-0 xl:pt-24">
126160
<div className="flex h-full w-full flex-col items-center pb-[100px] pt-10">
127161
<div>
128162
<h1 className="mb-6 text-center text-3xl font-bold dark:text-zinc-100 md:text-5xl">
129-
What People Are Saying
163+
{dict.marketing.people_comment.title}
130164
</h1>
131165
</div>
132-
<div className="mb-6 text-xl dark:text-zinc-100 md:text-xl">
133-
Don’t just take our word for it. Here’s what{" "}
134-
<span className="font-bold">real people</span> are saying about
135-
Saasfly.
166+
<div className="mb-6 text-lg text-neutral-500 dark:text-neutral-400">
167+
{dict.marketing.people_comment.desc}
136168
</div>
137169

138170
<div className="w-full overflow-x-hidden">
139-
<Comments />
171+
<Comments/>
140172
</div>
141173
</div>
142174
</section>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"use client"
2+
3+
import { useState } from "react"
4+
import * as Icons from "@saasfly/ui/icons";
5+
6+
export function CodeCopy() {
7+
const [copied, setCopied] = useState(false)
8+
const command = "bun create saasfly"
9+
10+
const copyToClipboard = async () => {
11+
try {
12+
await navigator.clipboard.writeText(command)
13+
setCopied(true)
14+
setTimeout(() => setCopied(false), 2000)
15+
} catch (err) {
16+
console.error("Failed to copy text: ", err)
17+
}
18+
}
19+
20+
return (
21+
<div className="rounded-full h-12 px-3 flex items-center justify-between max-w-xl bg-neutral-200 dark:bg-neutral-700/40">
22+
<div className="flex items-center space-x-2 font-mono text-neutral-700 dark:text-neutral-300">
23+
<span>$</span>
24+
<span>{command}</span>
25+
</div>
26+
<button
27+
onClick={copyToClipboard}
28+
className="p-1.5 hover:bg-gray-200 dark:hover:bg-neutral-800 rounded-md transition-colors ml-2"
29+
aria-label="Copy to clipboard"
30+
>
31+
{copied ? <Icons.Check className="w-4 h-4 text-neutral-700 dark:text-neutral-300" /> : <Icons.Copy className={`w-4 h-4 text-neutral-700 dark:text-neutral-300`} />}
32+
</button>
33+
</div>
34+
)
35+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Card } from "@saasfly/ui/card"
2+
import * as Icons from "@saasfly/ui/icons";
3+
4+
export function FeaturesGrid({ dict } : { dict: Record<string, string> | undefined }) {
5+
return (
6+
<div className="flex gap-4 flex-col sm:flex-row md:flex-row xl:flex-row">
7+
<Card className="p-3 w-full rounded-3xl dark:border-neutral-800 dark:bg-neutral-900/40">
8+
<div className="flex flex-col gap-2">
9+
<div className="flex items-center gap-2">
10+
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center">
11+
<Icons.Blocks className="w-6 h-6 text-purple-500" />
12+
</div>
13+
<h2 className="text-lg font-semibold">{dict?.monorepo_title}</h2>
14+
</div>
15+
<p className="leading-relaxed text-neutral-500 dark:text-neutral-400 font-medium">
16+
{dict?.monorepo_desc}
17+
</p>
18+
</div>
19+
</Card>
20+
21+
<Card className="p-3 w-full rounded-3xl dark:border-neutral-800 dark:bg-neutral-900/40">
22+
<div className="flex flex-col gap-2">
23+
<div className="flex items-center gap-2">
24+
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center">
25+
<Icons.Languages className="w-6 h-6 text-purple-500" />
26+
</div>
27+
<h2 className="text-lg font-semibold">{dict?.i18n_title}</h2>
28+
</div>
29+
<p className="leading-relaxed text-neutral-500 dark:text-neutral-400 font-medium">
30+
{dict?.i18n_desc}
31+
</p>
32+
</div>
33+
</Card>
34+
35+
<Card className="p-3 w-full rounded-3xl dark:border-neutral-800 dark:bg-neutral-900/40">
36+
<div className="flex flex-col gap-2">
37+
<div className="flex items-center gap-2">
38+
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center">
39+
<Icons.Billing className="w-6 h-6 text-purple-500" />
40+
</div>
41+
<h2 className="text-lg font-semibold">{dict?.payments_title}</h2>
42+
</div>
43+
<p className="leading-relaxed text-neutral-500 dark:text-neutral-400 font-medium">
44+
{dict?.payments_desc}
45+
</p>
46+
</div>
47+
</Card>
48+
49+
<Card className="p-3 w-full rounded-3xl dark:border-neutral-800 dark:bg-neutral-900/40">
50+
<div className="flex flex-col gap-2">
51+
<div className="flex items-center gap-2">
52+
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center">
53+
<Icons.ShieldCheck className="w-6 h-6 text-purple-500" />
54+
</div>
55+
<h2 className="text-lg font-semibold">{dict?.nextauth_title}</h2>
56+
</div>
57+
<p className="leading-relaxed text-neutral-500 dark:text-neutral-400 font-medium">
58+
{dict?.nextauth_desc}
59+
</p>
60+
</div>
61+
</Card>
62+
</div>
63+
)
64+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use client";
2+
3+
import Link from "next/link";
4+
import * as Icons from "@saasfly/ui/icons";
5+
6+
export function GitHubStar() {
7+
return (
8+
<Link href="https://github.com/saasfly/saasfly" target="_blank" rel="Saasfly GitHub">
9+
<div className="inline-flex items-center gap-1.5 px-3 h-9 border border-input hover:bg-accent hover:text-accent-foreground rounded-full text-sm font-medium">
10+
<Icons.GitHub className="w-4 h-4"/>
11+
<span>2.2K</span>
12+
</div>
13+
</Link>
14+
)
15+
}

0 commit comments

Comments
 (0)