Skip to content

Commit

Permalink
feat(www): New landing page (#10)
Browse files Browse the repository at this point in the history
## Changelog
- [x] New hero section
- [x] Highlight Nav and example
- [x] Waiting list form
  • Loading branch information
alifarooq9 authored Apr 9, 2024
2 parents 4985bf7 + 7d96252 commit 064092f
Show file tree
Hide file tree
Showing 20 changed files with 791 additions and 36 deletions.
9 changes: 8 additions & 1 deletion apps/www/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ await import("./src/env.js");

/** @type {import("next").NextConfig} */
const config = {
transpilePackages: ["@rapidlaunch/ui"],
images: {
remotePatterns: [
{
protocol: "https",
hostname: "utfs.io",
},
],
},
};

export default config;
4 changes: 4 additions & 0 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
"@hookform/resolvers": "^3.3.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"@t3-oss/env-nextjs": "^0.9.2",
"@tanstack/react-query": "^5.24.1",
"@vercel/analytics": "^1.2.2",
Expand All @@ -29,6 +32,7 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.50.1",
"react-wrap-balancer": "^1.1.0",
"sharp": "^0.33.3",
"sonner": "^1.4.2",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
Expand Down
4 changes: 2 additions & 2 deletions apps/www/prettier.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
const config = {
plugins: ["prettier-plugin-tailwindcss"],
tabWidth: 4,
plugins: ["prettier-plugin-tailwindcss"],
tabWidth: 4,
};

export default config;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { useMutation } from "@tanstack/react-query";
import { joinEarlyAccessAction } from "@/server/actions";
import { joinEarlyAccessAction } from "@/server/actions/early-access";
import { Icons } from "@/components/icons";
import { toast } from "sonner";

Expand Down Expand Up @@ -62,7 +62,7 @@ export function EarlyAccessForm() {
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="w-full max-w-sm space-y-2"
className="w-full space-y-2"
>
<FormField
control={form.control}
Expand All @@ -72,7 +72,7 @@ export function EarlyAccessForm() {
<FormControl>
<Input
placeholder="Name"
className="bg-background"
className="h-12 bg-background"
{...field}
/>
</FormControl>
Expand All @@ -88,7 +88,7 @@ export function EarlyAccessForm() {
<FormControl>
<Input
placeholder="Email"
className="bg-background"
className="h-12 bg-background"
{...field}
/>
</FormControl>
Expand All @@ -100,7 +100,8 @@ export function EarlyAccessForm() {
<Button
disabled={isPending}
type="submit"
className="w-full gap-2"
className="h-12 w-full gap-2"
size="lg"
>
{isPending ? (
<Icons.loader className="h-4 w-4" />
Expand Down
88 changes: 88 additions & 0 deletions apps/www/src/app/(app)/_components/highlight-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"use client";

import { cn } from "@/lib/utils";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import type { TabsProps } from "@radix-ui/react-tabs";
import { SaasStarterkitHighlight } from "@/app/(app)/_components/saas-startkit-highlight";
import React from "react";

const highlights = [
{
id: "saas-starterkit",
title: "SaaS Starterkit",
description:
"Auth, Dashboard, Landing Pages, billing and more — everything you need to launch your MVP faster.",
badge: "Almost Ready",
},
{
id: "blocks",
title: "Blocks",
description:
"Auth forms, modals, hero sections, pricing tables, and more — all customizable and open source.",
disabled: true,
badge: "Soon",
},
{
id: "guides",
title: "Guides",
description:
"Authenticating users, setting up billing, and more — all the guides you need to launch your app.",
disabled: true,
badge: "Soon",
},
];

type HighlightNavProps = TabsProps;

export function HighlightTabs({ className, ...props }: HighlightNavProps) {
const [selectedHighlight, setSelectedHighlight] = React.useState(
highlights[0]?.id,
);

const activeHighlight = highlights.find(
(highlight) => highlight.id === selectedHighlight,
);

return (
<Tabs
className={cn("space-y-10", className)}
value={selectedHighlight}
onValueChange={(value) => setSelectedHighlight(value)}
{...props}
>
<div className="flex flex-col items-center gap-4">
<TabsList className="grid h-auto grid-cols-3 items-start bg-transparent p-0">
{highlights.map((highlight) => (
<TabsTrigger
value={highlight.id}
key={highlight.id}
disabled={highlight.disabled}
className="group flex flex-col items-center justify-start gap-2 whitespace-normal rounded-none border-t py-6 text-start data-[state=active]:border-primary data-[state=active]:shadow-none sm:items-start"
>
<div className="flex flex-col items-center gap-2 sm:flex-row">
<h2 className="text-center font-medium">
{highlight.title}
</h2>
{highlight?.badge && (
<span className="block rounded-sm bg-secondary px-2 py-0.5 text-center text-xs font-medium text-primary">
{highlight.badge}
</span>
)}
</div>
<p className="hidden font-normal text-muted-foreground transition-all sm:block">
{highlight.description}
</p>
</TabsTrigger>
))}
</TabsList>

<p className="block w-full text-center text-sm font-normal text-muted-foreground transition-all sm:hidden">
{activeHighlight?.description}
</p>
</div>
<TabsContent value="saas-starterkit">
<SaasStarterkitHighlight />
</TabsContent>
</Tabs>
);
}
2 changes: 2 additions & 0 deletions apps/www/src/app/(app)/_components/main-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export function MainNav() {
"text-foreground":
pathname === item.href,
},
item.disabled &&
"pointer-events-none opacity-60",
)}
>
{item.label}
Expand Down
1 change: 1 addition & 0 deletions apps/www/src/app/(app)/_components/mobile-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function MobileNav() {
className="flex sm:hidden"
>
<Icons.hamburger className="h-4 w-4" />
<span className="sr-only">menu</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="pr-0">
Expand Down
110 changes: 110 additions & 0 deletions apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { badgeVariants } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { siteUrls } from "@/config/urls";
import Image from "next/image";
import Link from "next/link";
import { ArrowRightIcon } from "lucide-react";
import { buttonVariants } from "@/components/ui/button";

const saasStarterkitHighlights = [
{
id: "user-dashboard",
title: "User Dashboard",
imageLight:
"https://utfs.io/f/43bbc3c8-cf3c-4fae-a0eb-9183f1779489-294m81.png",
imageDark:
"https://utfs.io/f/fddea366-51c6-45f4-bd54-84d273ad9fb9-1ly324.png",
},
{
id: "auth",
title: "Authentication",
imageLight:
"https://utfs.io/f/805616c1-22b8-4508-9890-9ba9e2867a41-p24dnn.png",
imageDark:
"https://utfs.io/f/9074c0de-d9ea-4c0b-9d49-55dca1253a3f-6ig3yq.png",
},
{
id: "user-settings",
title: "User Settings",
imageLight:
"https://utfs.io/f/da560e34-84ca-4283-8060-65d727def753-eqmy3s.png",
imageDark:
"https://utfs.io/f/e365451e-1a36-43a7-8d1c-7315e5aae430-63u1th.png",
},
{
id: "Users-management",
title: "Users Management",
imageLight:
"https://utfs.io/f/72a2c035-69e0-46ca-84a8-446e4dabf77c-3koi6e.png",
imageDark:
"https://utfs.io/f/89099112-4273-4375-9e44-1b3394600e21-c6ikq1.png",
},
];

export function SaasStarterkitHighlight() {
return (
<div className="space-y-4">
<p className="gap-2 text-center text-sm sm:text-left">
For more information, Visit the{" "}
<Link
href={siteUrls.saasStarterkit}
className={badgeVariants({
variant: "secondary",
className: "ml-1 mt-1 gap-0.5 sm:mt-0",
})}
>
<span>SaaS Starterkit</span>
<ArrowRightIcon className="h-3 w-3" />
</Link>
</p>
<Tabs defaultValue="user-dashboard" className="h-auto">
<TabsList className="h-auto flex-wrap items-center justify-center gap-2 bg-transparent p-0 sm:justify-start">
{saasStarterkitHighlights.map((tab) => (
<TabsTrigger
key={tab.id}
value={tab.id}
className="data-[state=active]:bg-secondary"
>
{tab.title}
</TabsTrigger>
))}

<Link
href={siteUrls.saasStarterkit}
className={buttonVariants({
variant: "ghost",
size: "sm",
className: "gap-1",
})}
>
<span>View all</span>
<ArrowRightIcon className="h-4 w-4" />
</Link>
</TabsList>
{saasStarterkitHighlights.map((tab) => (
<TabsContent
className="relative aspect-video rounded-md bg-muted"
key={tab.id}
value={tab.id}
>
<Image
src={tab.imageLight}
alt={tab.title}
fill
className="block rounded-md border border-border dark:hidden"
priority
/>

<Image
src={tab.imageDark}
alt={tab.title}
fill
className="hidden rounded-md border border-border dark:block"
priority
/>
</TabsContent>
))}
</Tabs>
</div>
);
}
2 changes: 1 addition & 1 deletion apps/www/src/app/(app)/_components/side-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { MobileNav } from "@/app/(app)/_components/mobile-nav";

export function SiteHeader() {
return (
<header className="sticky top-0 w-full border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<header className="sticky top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-14 max-w-screen-2xl items-center justify-between">
<div className="flex items-center gap-5">
<MobileNav />
Expand Down
Loading

0 comments on commit 064092f

Please sign in to comment.