From 9db3bf3e020eeb8fdca7648238fde75c6f2a65d4 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Sun, 7 Apr 2024 16:09:36 +0500 Subject: [PATCH 1/5] feat(www): New landing page --- apps/www/next.config.js | 9 +- apps/www/package.json | 4 + apps/www/prettier.config.js | 4 +- .../app/(app)/_components/highlight-tabs.tsx | 68 +++++ .../_components/saas-startkit-highlight.tsx | 112 +++++++ .../src/app/(app)/_components/side-header.tsx | 2 +- apps/www/src/app/(app)/page.tsx | 66 ++++- apps/www/src/app/layout.tsx | 6 +- apps/www/src/components/ui/scroll-area.tsx | 48 +++ apps/www/src/components/ui/tabs.tsx | 55 ++++ apps/www/src/config/urls.ts | 2 +- apps/www/src/lib/fonts.ts | 8 +- apps/www/src/server/actions/github.ts | 20 ++ apps/www/tailwind.config.ts | 6 + pnpm-lock.yaml | 276 ++++++++++++++++++ 15 files changed, 664 insertions(+), 22 deletions(-) create mode 100644 apps/www/src/app/(app)/_components/highlight-tabs.tsx create mode 100644 apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx create mode 100644 apps/www/src/components/ui/scroll-area.tsx create mode 100644 apps/www/src/components/ui/tabs.tsx create mode 100644 apps/www/src/server/actions/github.ts diff --git a/apps/www/next.config.js b/apps/www/next.config.js index ad7a15a..caa757d 100644 --- a/apps/www/next.config.js +++ b/apps/www/next.config.js @@ -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; diff --git a/apps/www/package.json b/apps/www/package.json index 0d989ad..09d7617 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -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", @@ -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", diff --git a/apps/www/prettier.config.js b/apps/www/prettier.config.js index aa5080b..1c9fe51 100644 --- a/apps/www/prettier.config.js +++ b/apps/www/prettier.config.js @@ -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; diff --git a/apps/www/src/app/(app)/_components/highlight-tabs.tsx b/apps/www/src/app/(app)/_components/highlight-tabs.tsx new file mode 100644 index 0000000..533370a --- /dev/null +++ b/apps/www/src/app/(app)/_components/highlight-tabs.tsx @@ -0,0 +1,68 @@ +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"; + +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: "Coming 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: "Coming Soon", + }, +]; + +type HighlightNavProps = TabsProps; + +export function HighlightTabs({ className, ...props }: HighlightNavProps) { + return ( + + + {highlights.map((highlight) => ( + +
+

{highlight.title}

+ {highlight?.badge && ( + + {highlight.badge} + + )} +
+

+ {highlight.description} +

+
+ ))} +
+ + + +
+ ); +} diff --git a/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx b/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx new file mode 100644 index 0000000..157f33b --- /dev/null +++ b/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx @@ -0,0 +1,112 @@ +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 ( +
+
+

+ For more information, Visit the{" "} + + SaaS Starterkit + + +

+
+ + + {saasStarterkitHighlights.map((tab) => ( + + {tab.title} + + ))} + + + View all + + + + {saasStarterkitHighlights.map((tab) => ( + + {tab.title} + + {tab.title} + + ))} + +
+ ); +} diff --git a/apps/www/src/app/(app)/_components/side-header.tsx b/apps/www/src/app/(app)/_components/side-header.tsx index 254278e..2a4438e 100644 --- a/apps/www/src/app/(app)/_components/side-header.tsx +++ b/apps/www/src/app/(app)/_components/side-header.tsx @@ -9,7 +9,7 @@ import { MobileNav } from "@/app/(app)/_components/mobile-nav"; export function SiteHeader() { return ( -
+
diff --git a/apps/www/src/app/(app)/page.tsx b/apps/www/src/app/(app)/page.tsx index efdccc8..eb9f332 100644 --- a/apps/www/src/app/(app)/page.tsx +++ b/apps/www/src/app/(app)/page.tsx @@ -1,30 +1,68 @@ -import { Badge } from "@/components/ui/badge"; import Balance from "react-wrap-balancer"; -import { EarlyAccessForm } from "@/components/early-access-form"; +import { ExternalLinkIcon } from "lucide-react"; +import Link from "next/link"; +import { siteUrls } from "@/config/urls"; +import { buttonVariants } from "@/components/ui/button"; +import { Icons } from "@/components/icons"; +import { HighlightTabs } from "@/app/(app)/_components/highlight-tabs"; +import { getRepoStars } from "@/server/actions/github"; + +export default async function HomePage() { + const repoStars = await getRepoStars(); -export default function HomePage() { return ( -
- - 🎉{" "} -

Open Source SaaS Starterkits and components

-
+
+ + 🎉 + + RapidLaunch is in development. Follow our progress on 𝕏 + (formally Twitter) + + + - Launch 🚀 in days with beautiful SaaS starterkits and components + Rapidly launch your MVP with Beautiful Starterkits, Blocks, and + more. Elevate your development game with Rapidlaunch! Launch your apps - faster with our SaaS starterkits, components, building blocks. - Customizable. Open Source + faster with our SaaS starterkits, components, building guides, + and more. Customizable. Open Source. +
+ + Get Early Access + + + + Github - + + {repoStars} + + +
- -
+ +
); } diff --git a/apps/www/src/app/layout.tsx b/apps/www/src/app/layout.tsx index c596150..bd73aff 100644 --- a/apps/www/src/app/layout.tsx +++ b/apps/www/src/app/layout.tsx @@ -5,7 +5,7 @@ import "@/styles/globals.css"; import type { Metadata } from "next"; import { siteConfig } from "@/config/site"; import { Analytics } from "@vercel/analytics/react"; -import { fontSans } from "@/lib/fonts"; +import { fontSans, fontHeading } from "@/lib/fonts"; const TITLE = "Rapidlaunch | Open Source Nextjs SaaS Starterkits and Components"; @@ -49,7 +49,9 @@ export default function RootLayout({ }) { return ( - + {children} diff --git a/apps/www/src/components/ui/scroll-area.tsx b/apps/www/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..0b4a48d --- /dev/null +++ b/apps/www/src/components/ui/scroll-area.tsx @@ -0,0 +1,48 @@ +"use client" + +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/apps/www/src/components/ui/tabs.tsx b/apps/www/src/components/ui/tabs.tsx new file mode 100644 index 0000000..e395ffb --- /dev/null +++ b/apps/www/src/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +"use client"; + +import React from "react"; +import * as TabsPrimitive from "@radix-ui/react-tabs"; + +import { cn } from "@/lib/utils"; + +const Tabs = TabsPrimitive.Root; + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsList.displayName = TabsPrimitive.List.displayName; + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; + +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/apps/www/src/config/urls.ts b/apps/www/src/config/urls.ts index 034d16e..51e2277 100644 --- a/apps/www/src/config/urls.ts +++ b/apps/www/src/config/urls.ts @@ -1,6 +1,6 @@ export const siteUrls = { home: "/", - starterkits: "/starterkits", + saasStarterkit: "/saas-starterkit", components: "/components", blog: "/blog", docs: "/docs", diff --git a/apps/www/src/lib/fonts.ts b/apps/www/src/lib/fonts.ts index 17b7a46..ff01282 100644 --- a/apps/www/src/lib/fonts.ts +++ b/apps/www/src/lib/fonts.ts @@ -1,5 +1,11 @@ -import { Inter } from "next/font/google"; +import { Inter, Bricolage_Grotesque } from "next/font/google"; export const fontSans = Inter({ subsets: ["latin"], + variable: "--font-sans", +}); + +export const fontHeading = Bricolage_Grotesque({ + subsets: ["latin"], + variable: "--font-heading", }); diff --git a/apps/www/src/server/actions/github.ts b/apps/www/src/server/actions/github.ts new file mode 100644 index 0000000..95beef3 --- /dev/null +++ b/apps/www/src/server/actions/github.ts @@ -0,0 +1,20 @@ +"use server"; + +export async function getRepoStars() { + const response = await fetch( + "https://api.github.com/repos/afarooq-oss/rapidlaunch", + { + next: { + revalidate: 86400, + }, + }, + ); + + const data: unknown = await response.json(); + const stars: number = (data as { stargazers_count?: number }) + ?.stargazers_count + ? Number((data as { stargazers_count?: number }).stargazers_count) + : 0; + + return stars; +} diff --git a/apps/www/tailwind.config.ts b/apps/www/tailwind.config.ts index 06ad3d4..baabec9 100644 --- a/apps/www/tailwind.config.ts +++ b/apps/www/tailwind.config.ts @@ -1,4 +1,5 @@ import type { Config } from "tailwindcss"; +import { fontFamily } from "tailwindcss/defaultTheme"; import baseConfig from "@rapidlaunch/tailwind-config/base"; @@ -7,7 +8,12 @@ export default { // those classes are included correctly. content: [...baseConfig.content], presets: [baseConfig], + safelist: ["dark"], theme: { extend: {}, + fontFamily: { + sans: ["var(--font-sans)", ...fontFamily.sans], + heading: ["var(--font-heading)", ...fontFamily.sans], + }, }, } satisfies Config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 106df0e..1bf9e2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,12 +32,21 @@ importers: '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 version: 2.0.6(@types/react-dom@18.2.19)(@types/react@18.2.60)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-icons': + specifier: ^1.3.0 + version: 1.3.0(react@18.2.0) '@radix-ui/react-label': specifier: ^2.0.2 version: 2.0.2(@types/react-dom@18.2.19)(@types/react@18.2.60)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-scroll-area': + specifier: ^1.0.5 + version: 1.0.5(@types/react-dom@18.2.19)(@types/react@18.2.60)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.2.60)(react@18.2.0) + '@radix-ui/react-tabs': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.60)(react-dom@18.2.0)(react@18.2.0) '@t3-oss/env-nextjs': specifier: ^0.9.2 version: 0.9.2(typescript@5.3.3)(zod@3.22.4) @@ -77,6 +86,9 @@ importers: react-wrap-balancer: specifier: ^1.1.0 version: 1.1.0(react@18.2.0) + sharp: + specifier: ^0.33.3 + version: 0.33.3 sonner: specifier: ^1.4.2 version: 1.4.2(react-dom@18.2.0)(react@18.2.0) @@ -752,6 +764,14 @@ packages: superjson: 2.2.1 dev: true + /@emnapi/runtime@1.1.1: + resolution: {integrity: sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ==} + requiresBuild: true + dependencies: + tslib: 2.6.2 + dev: false + optional: true + /@esbuild-kit/core-utils@3.3.2: resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} dependencies: @@ -1294,6 +1314,194 @@ packages: resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} dev: true + /@img/sharp-darwin-arm64@0.33.3: + resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.2 + dev: false + optional: true + + /@img/sharp-darwin-x64@0.33.3: + resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.2 + dev: false + optional: true + + /@img/sharp-libvips-darwin-arm64@1.0.2: + resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} + engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-darwin-x64@1.0.2: + resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} + engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm64@1.0.2: + resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm@1.0.2: + resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-s390x@1.0.2: + resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-x64@1.0.2: + resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linuxmusl-arm64@1.0.2: + resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linuxmusl-x64@1.0.2: + resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-linux-arm64@0.33.3: + resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.2 + dev: false + optional: true + + /@img/sharp-linux-arm@0.33.3: + resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.2 + dev: false + optional: true + + /@img/sharp-linux-s390x@0.33.3: + resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.2 + dev: false + optional: true + + /@img/sharp-linux-x64@0.33.3: + resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.2 + dev: false + optional: true + + /@img/sharp-linuxmusl-arm64@0.33.3: + resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + dev: false + optional: true + + /@img/sharp-linuxmusl-x64@0.33.3: + resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + dev: false + optional: true + + /@img/sharp-wasm32@0.33.3: + resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [wasm32] + requiresBuild: true + dependencies: + '@emnapi/runtime': 1.1.1 + dev: false + optional: true + + /@img/sharp-win32-ia32@0.33.3: + resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-win32-x64@0.33.3: + resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -3970,6 +4178,21 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + + /color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + dev: false + /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} dev: false @@ -4134,6 +4357,11 @@ packages: engines: {node: '>=12.20'} dev: true + /detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + dev: false + /detect-newline@4.0.1: resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6179,6 +6407,10 @@ packages: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} dev: true + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -8425,6 +8657,14 @@ packages: dependencies: lru-cache: 6.0.0 + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + /server-only@0.0.1: resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} dev: false @@ -8460,6 +8700,36 @@ packages: has-property-descriptors: 1.0.1 dev: true + /sharp@0.33.3: + resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} + engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + requiresBuild: true + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.0 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.3 + '@img/sharp-darwin-x64': 0.33.3 + '@img/sharp-libvips-darwin-arm64': 1.0.2 + '@img/sharp-libvips-darwin-x64': 1.0.2 + '@img/sharp-libvips-linux-arm': 1.0.2 + '@img/sharp-libvips-linux-arm64': 1.0.2 + '@img/sharp-libvips-linux-s390x': 1.0.2 + '@img/sharp-libvips-linux-x64': 1.0.2 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + '@img/sharp-linux-arm': 0.33.3 + '@img/sharp-linux-arm64': 0.33.3 + '@img/sharp-linux-s390x': 0.33.3 + '@img/sharp-linux-x64': 0.33.3 + '@img/sharp-linuxmusl-arm64': 0.33.3 + '@img/sharp-linuxmusl-x64': 0.33.3 + '@img/sharp-wasm32': 0.33.3 + '@img/sharp-win32-ia32': 0.33.3 + '@img/sharp-win32-x64': 0.33.3 + dev: false + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -8482,6 +8752,12 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true From 28159e0412122c024e691e516e31d0620504ba9a Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Sun, 7 Apr 2024 18:02:07 +0500 Subject: [PATCH 2/5] chore(www): Added vercel json, disabled nav links --- .../src/app/(app)/_components/main-nav.tsx | 2 ++ apps/www/vercel.json | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 apps/www/vercel.json diff --git a/apps/www/src/app/(app)/_components/main-nav.tsx b/apps/www/src/app/(app)/_components/main-nav.tsx index d08b62c..0eb625c 100644 --- a/apps/www/src/app/(app)/_components/main-nav.tsx +++ b/apps/www/src/app/(app)/_components/main-nav.tsx @@ -22,6 +22,8 @@ export function MainNav() { "text-foreground": pathname === item.href, }, + item.disabled && + "pointer-events-none opacity-60", )} > {item.label} diff --git a/apps/www/vercel.json b/apps/www/vercel.json new file mode 100644 index 0000000..1a3378e --- /dev/null +++ b/apps/www/vercel.json @@ -0,0 +1,20 @@ +{ + "redirects": [ + { + "source": "/github", + "destination": "https://github.com/afarooq-oss/rapidlaunch" + }, + { + "source": "/gh", + "destination": "https://github.com/afarooq-oss/rapidlaunch" + }, + { + "source": "/alifarooq", + "destination": "https://alifarooq.xyz" + }, + { + "source": "/ali", + "destination": "https://alifarooq.xyz" + } + ] +} From 09046cff359774994f69fc485c5ca9b6180812dc Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Sun, 7 Apr 2024 20:48:20 +0500 Subject: [PATCH 3/5] feat(www): Responsize landing page --- .../app/(app)/_components/highlight-tabs.tsx | 70 ++++++++++++------- .../_components/saas-startkit-highlight.tsx | 32 ++++----- apps/www/src/app/(app)/page.tsx | 4 +- 3 files changed, 62 insertions(+), 44 deletions(-) diff --git a/apps/www/src/app/(app)/_components/highlight-tabs.tsx b/apps/www/src/app/(app)/_components/highlight-tabs.tsx index 533370a..489157a 100644 --- a/apps/www/src/app/(app)/_components/highlight-tabs.tsx +++ b/apps/www/src/app/(app)/_components/highlight-tabs.tsx @@ -1,7 +1,10 @@ +"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 = [ { @@ -17,7 +20,7 @@ const highlights = [ description: "Auth forms, modals, hero sections, pricing tables, and more — all customizable and open source.", disabled: true, - badge: "Coming Soon", + badge: "Soon", }, { id: "guides", @@ -25,41 +28,58 @@ const highlights = [ description: "Authenticating users, setting up billing, and more — all the guides you need to launch your app.", disabled: true, - badge: "Coming Soon", + 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 ( setSelectedHighlight(value)} {...props} > - - {highlights.map((highlight) => ( - -
-

{highlight.title}

- {highlight?.badge && ( - - {highlight.badge} - - )} -
-

- {highlight.description} -

-
- ))} -
+
+ + {highlights.map((highlight) => ( + +
+

+ {highlight.title} +

+ {highlight?.badge && ( + + {highlight.badge} + + )} +
+

+ {highlight.description} +

+
+ ))} +
+ +

+ {activeHighlight?.description} +

+
diff --git a/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx b/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx index 157f33b..1b5894e 100644 --- a/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx +++ b/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx @@ -44,23 +44,21 @@ const saasStarterkitHighlights = [ export function SaasStarterkitHighlight() { return (
-
-

- For more information, Visit the{" "} - - SaaS Starterkit - - -

-
- - +

+ For more information, Visit the{" "} + + SaaS Starterkit + + +

+ + {saasStarterkitHighlights.map((tab) => ( - + - Get Early Access + Early Access Date: Tue, 9 Apr 2024 15:39:20 +0500 Subject: [PATCH 4/5] refactor(www): get github stars --- apps/www/src/app/(app)/page.tsx | 22 +++++++++++++++++++++- apps/www/src/server/actions/github.ts | 20 -------------------- 2 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 apps/www/src/server/actions/github.ts diff --git a/apps/www/src/app/(app)/page.tsx b/apps/www/src/app/(app)/page.tsx index d351fb1..9201018 100644 --- a/apps/www/src/app/(app)/page.tsx +++ b/apps/www/src/app/(app)/page.tsx @@ -5,7 +5,6 @@ import { siteUrls } from "@/config/urls"; import { buttonVariants } from "@/components/ui/button"; import { Icons } from "@/components/icons"; import { HighlightTabs } from "@/app/(app)/_components/highlight-tabs"; -import { getRepoStars } from "@/server/actions/github"; export default async function HomePage() { const repoStars = await getRepoStars(); @@ -66,3 +65,24 @@ export default async function HomePage() {
); } + +export async function getRepoStars() { + const response = await fetch( + "https://api.github.com/repos/afarooq-oss/rapidlaunch", + { + next: { + revalidate: 86400, + }, + }, + ); + + const data: unknown = await response.json(); + const stars: number = (data as { stargazers_count?: string }) + ?.stargazers_count + ? Number((data as { stargazers_count?: string }).stargazers_count) + : 0; + + console.log(data); + + return stars; +} diff --git a/apps/www/src/server/actions/github.ts b/apps/www/src/server/actions/github.ts deleted file mode 100644 index 95beef3..0000000 --- a/apps/www/src/server/actions/github.ts +++ /dev/null @@ -1,20 +0,0 @@ -"use server"; - -export async function getRepoStars() { - const response = await fetch( - "https://api.github.com/repos/afarooq-oss/rapidlaunch", - { - next: { - revalidate: 86400, - }, - }, - ); - - const data: unknown = await response.json(); - const stars: number = (data as { stargazers_count?: number }) - ?.stargazers_count - ? Number((data as { stargazers_count?: number }).stargazers_count) - : 0; - - return stars; -} From 7d9625256eb88d7d2a182c43a80a2d06b5b5c94f Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Tue, 9 Apr 2024 17:28:08 +0500 Subject: [PATCH 5/5] feat(www): Updated early access form --- .../(app)/_components}/early-access-form.tsx | 11 +- .../src/app/(app)/_components/mobile-nav.tsx | 1 + apps/www/src/app/(app)/page.tsx | 124 +++++++++++------- apps/www/src/components/background.tsx | 48 +++++++ apps/www/src/config/urls.ts | 1 + .../{actions.ts => actions/early-access.ts} | 0 6 files changed, 129 insertions(+), 56 deletions(-) rename apps/www/src/{components => app/(app)/_components}/early-access-form.tsx (90%) create mode 100644 apps/www/src/components/background.tsx rename apps/www/src/server/{actions.ts => actions/early-access.ts} (100%) diff --git a/apps/www/src/components/early-access-form.tsx b/apps/www/src/app/(app)/_components/early-access-form.tsx similarity index 90% rename from apps/www/src/components/early-access-form.tsx rename to apps/www/src/app/(app)/_components/early-access-form.tsx index 1968013..cd3c7db 100644 --- a/apps/www/src/components/early-access-form.tsx +++ b/apps/www/src/app/(app)/_components/early-access-form.tsx @@ -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"; @@ -62,7 +62,7 @@ export function EarlyAccessForm() {
@@ -88,7 +88,7 @@ export function EarlyAccessForm() { @@ -100,7 +100,8 @@ export function EarlyAccessForm() { diff --git a/apps/www/src/app/(app)/page.tsx b/apps/www/src/app/(app)/page.tsx index 9201018..3e54e48 100644 --- a/apps/www/src/app/(app)/page.tsx +++ b/apps/www/src/app/(app)/page.tsx @@ -5,68 +5,92 @@ import { siteUrls } from "@/config/urls"; import { buttonVariants } from "@/components/ui/button"; import { Icons } from "@/components/icons"; import { HighlightTabs } from "@/app/(app)/_components/highlight-tabs"; +import { EarlyAccessForm } from "@/app/(app)/_components/early-access-form"; +import Balancer from "react-wrap-balancer"; +import { Background } from "@/components/background"; export default async function HomePage() { const repoStars = await getRepoStars(); return ( -
- - 🎉 - - RapidLaunch is in development. Follow our progress on 𝕏 - (formally Twitter) - - - - - Rapidly launch your MVP with Beautiful Starterkits, Blocks, and - more. - - - Elevate your development game with Rapidlaunch! Launch your apps - faster with our SaaS starterkits, components, building guides, - and more. Customizable. Open Source. - -
- - Early Access - + <> +
- - Github - - - {repoStars} + 🎉 + + RapidLaunch is in development. Follow our progress on 𝕏 + (formally Twitter) + -
+ + Rapidly launch your MVP with Beautiful Starterkits, Blocks, + and more. + + + Elevate your development game with Rapidlaunch! Launch your + apps faster with our SaaS starterkits, components, building + guides, and more. Customizable. Open Source. + +
+ + Early Access + + + + Github - + + {repoStars} + + +
+ + + - -
+
+ +
+ + Join the Early Access List and get notified when we + launch! + + + +
+
+
+ ); } -export async function getRepoStars() { +async function getRepoStars() { const response = await fetch( "https://api.github.com/repos/afarooq-oss/rapidlaunch", { @@ -82,7 +106,5 @@ export async function getRepoStars() { ? Number((data as { stargazers_count?: string }).stargazers_count) : 0; - console.log(data); - return stars; } diff --git a/apps/www/src/components/background.tsx b/apps/www/src/components/background.tsx new file mode 100644 index 0000000..d705edd --- /dev/null +++ b/apps/www/src/components/background.tsx @@ -0,0 +1,48 @@ +interface BackgroundProps { + children: React.ReactNode; +} + +export function Background({ children }: BackgroundProps) { + return ( + <> +
+
+
+
+ + + + + + + + + + + + +
+
+ + {children} + + ); +} diff --git a/apps/www/src/config/urls.ts b/apps/www/src/config/urls.ts index 51e2277..841eaa0 100644 --- a/apps/www/src/config/urls.ts +++ b/apps/www/src/config/urls.ts @@ -6,4 +6,5 @@ export const siteUrls = { docs: "/docs", twitter: "https://twitter.com/AliFarooqDev", github: "/gh", + earlyAccess: "/#early-access", } as const; diff --git a/apps/www/src/server/actions.ts b/apps/www/src/server/actions/early-access.ts similarity index 100% rename from apps/www/src/server/actions.ts rename to apps/www/src/server/actions/early-access.ts