diff --git a/apps/www/package.json b/apps/www/package.json index 9cf45f1..ddb315f 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -24,6 +24,7 @@ "@vercel/analytics": "^1.2.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", + "geist": "^1.3.0", "lucide-react": "^0.343.0", "next": "^14.1.0", "next-themes": "^0.2.1", diff --git a/apps/www/src/app/(app)/(marketing)/page.tsx b/apps/www/src/app/(app)/(marketing)/page.tsx deleted file mode 100644 index d4ffb95..0000000 --- a/apps/www/src/app/(app)/(marketing)/page.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import Balance from "react-wrap-balancer"; -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 { EarlyAccessForm } from "@/app/(app)/_components/early-access-form"; -import Balancer from "react-wrap-balancer"; -import { Background } from "@/components/background"; - -export default async function HomePage() { - 8; - 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} - - -
- - -
- -
- -
- - Join the Early Access List and get notified when we - launch! - - - -
-
-
- - ); -} - -async function getRepoStars() { - const response = await fetch( - "https://api.github.com/repos/alifarooq9/rapidlaunch", - { - next: { - // run every 15 minutes - revalidate: 900, - }, - }, - ); - - 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; - - return stars; -} diff --git a/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx b/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx deleted file mode 100644 index 1a458e0..0000000 --- a/apps/www/src/app/(app)/_components/saas-startkit-highlight.tsx +++ /dev/null @@ -1,110 +0,0 @@ -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 Live Demo - - - - {saasStarterkitHighlights.map((tab) => ( - - {tab.title} - - {tab.title} - - ))} - -
- ); -} diff --git a/apps/www/src/app/(marketing)/page.tsx b/apps/www/src/app/(marketing)/page.tsx index 2fb8fff..3180c93 100644 --- a/apps/www/src/app/(marketing)/page.tsx +++ b/apps/www/src/app/(marketing)/page.tsx @@ -1,9 +1,10 @@ import { MarketingLayout } from "@/components/layout/marketing-layout"; +import { Hero } from "@/components/marketing/hero"; export default function HomePage() { return ( -

Marketing Page

+
); } diff --git a/apps/www/src/app/layout.tsx b/apps/www/src/app/layout.tsx index bd73aff..9286fb4 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, fontHeading } from "@/lib/fonts"; +import { fontSans } from "@/lib/fonts"; const TITLE = "Rapidlaunch | Open Source Nextjs SaaS Starterkits and Components"; @@ -49,9 +49,7 @@ export default function RootLayout({ }) { return ( - + {children} diff --git a/apps/www/src/components/background.tsx b/apps/www/src/components/background.tsx index d705edd..d815917 100644 --- a/apps/www/src/components/background.tsx +++ b/apps/www/src/components/background.tsx @@ -5,42 +5,29 @@ interface BackgroundProps { export function Background({ children }: BackgroundProps) { return ( <> -
-
-
-
- -
-
+ + + + + {children} diff --git a/apps/www/src/components/icons.tsx b/apps/www/src/components/icons.tsx index 7b3e585..dfbfbbe 100644 --- a/apps/www/src/components/icons.tsx +++ b/apps/www/src/components/icons.tsx @@ -221,4 +221,28 @@ export const Icons = { /> ), + externalLink: (props: IconProps) => ( + + + + + ), }; diff --git a/apps/www/src/components/layout/marketing-nav.tsx b/apps/www/src/components/layout/marketing-nav.tsx index 3caaf39..af219cf 100644 --- a/apps/www/src/components/layout/marketing-nav.tsx +++ b/apps/www/src/components/layout/marketing-nav.tsx @@ -54,7 +54,7 @@ export function MarketingMainNav() { + {children} + + ); +} + +export function PageHeaderDescription({ + children, +}: { + children: React.ReactNode; +}) { + return

{children}

; +} diff --git a/apps/www/src/components/marketing/announment.tsx b/apps/www/src/components/marketing/announment.tsx new file mode 100644 index 0000000..b7b0454 --- /dev/null +++ b/apps/www/src/components/marketing/announment.tsx @@ -0,0 +1,25 @@ +import { Icons } from "@/components/icons"; +import { badgeVariants } from "@/components/ui/badge"; +import { BorderBeam } from "@/components/ui/border-beam"; +import { siteUrls } from "@/config/urls"; +import { cn } from "@/lib/utils"; +import Link from "next/link"; + +export function Announcment() { + return ( + + Get Early Access for SaaS Starterkit + + + + ); +} diff --git a/apps/www/src/components/marketing/hero.tsx b/apps/www/src/components/marketing/hero.tsx new file mode 100644 index 0000000..a55ad50 --- /dev/null +++ b/apps/www/src/components/marketing/hero.tsx @@ -0,0 +1,24 @@ +import { Background } from "@/components/background"; +import { + PageHeaderDescription, + PageHeaderHeading, +} from "@/components/layout/page-header"; +import { Announcment } from "@/components/marketing/announment"; + +export function Hero() { + return ( + +
+ + +
+ Copy. Build. Launch. + + Open Source SaaS + Starterkit, Building Blocks and Guides + +
+
+
+ ); +} diff --git a/apps/www/src/components/providers.tsx b/apps/www/src/components/providers.tsx index 204ea1d..2892fba 100644 --- a/apps/www/src/components/providers.tsx +++ b/apps/www/src/components/providers.tsx @@ -1,7 +1,6 @@ "use client"; import type { ReactNode } from "react"; -import { ThemeProvider } from "@/components/theme-provider"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; interface ProvidersProps { @@ -13,14 +12,7 @@ export default function Providers({ children }: ProvidersProps) { return ( - - {children} - + {children} ); } diff --git a/apps/www/src/components/theme-provider.tsx b/apps/www/src/components/theme-provider.tsx deleted file mode 100644 index b7792a0..0000000 --- a/apps/www/src/components/theme-provider.tsx +++ /dev/null @@ -1,9 +0,0 @@ -"use client"; - -import * as React from "react"; -import { ThemeProvider as NextThemesProvider } from "next-themes"; -import type { ThemeProviderProps } from "next-themes/dist/types"; - -export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return {children}; -} diff --git a/apps/www/src/components/theme-toggle.tsx b/apps/www/src/components/theme-toggle.tsx deleted file mode 100644 index ad1ec6f..0000000 --- a/apps/www/src/components/theme-toggle.tsx +++ /dev/null @@ -1,37 +0,0 @@ -"use client"; - -import * as React from "react"; -import { useTheme } from "next-themes"; - -import { - DropdownMenu, - DropdownMenuCheckboxItem, - DropdownMenuContent, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; - -interface ThemeToggleProps { - button: React.ReactNode; -} - -export function ThemeToggle({ button }: ThemeToggleProps) { - const { setTheme, theme, themes } = useTheme(); - - return ( - - {button} - - {themes.map((t) => ( - setTheme(t)} - className="text-sm capitalize" - > - {t} - - ))} - - - ); -} diff --git a/apps/www/src/components/ui/badge.tsx b/apps/www/src/components/ui/badge.tsx index bc3f36b..e3320eb 100644 --- a/apps/www/src/components/ui/badge.tsx +++ b/apps/www/src/components/ui/badge.tsx @@ -5,7 +5,7 @@ import type { VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + "inline-flex items-center rounded-full border font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", { variants: { variant: { @@ -15,11 +15,17 @@ const badgeVariants = cva( "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", - outline: "text-foreground", + outline: "text-foreground border-border", + }, + size: { + sm: "px-2.5 h-8 text-xs", + default: "px-3 h-9 text-sm", + lg: "px-4 py-h-10 text-base", }, }, defaultVariants: { variant: "default", + size: "default", }, }, ); @@ -28,9 +34,12 @@ export interface BadgeProps extends React.HTMLAttributes, VariantProps {} -function Badge({ className, variant, ...props }: BadgeProps) { +function Badge({ className, variant, size, ...props }: BadgeProps) { return ( -
+
); } diff --git a/apps/www/src/components/ui/border-beam.tsx b/apps/www/src/components/ui/border-beam.tsx new file mode 100644 index 0000000..a6a11ae --- /dev/null +++ b/apps/www/src/components/ui/border-beam.tsx @@ -0,0 +1,51 @@ +import { cn } from "@/lib/utils"; + +interface BorderBeamProps { + className?: string; + size?: number; + duration?: number; + borderWidth?: number; + anchor?: number; + colorFrom?: string; + colorTo?: string; + delay?: number; +} + +const BorderBeam = ({ + className, + size = 200, + duration = 15, + anchor = 90, + borderWidth = 1.5, + colorFrom = "#ffaa40", + colorTo = "#9c40ff", + delay = 0, +}: BorderBeamProps) => { + return ( +
+ ); +}; + +export { BorderBeam }; diff --git a/apps/www/src/components/ui/button.tsx b/apps/www/src/components/ui/button.tsx index 636b860..af5e4f5 100644 --- a/apps/www/src/components/ui/button.tsx +++ b/apps/www/src/components/ui/button.tsx @@ -15,7 +15,7 @@ const buttonVariants = cva( destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: - "border-2 border-input bg-background hover:bg-accent hover:text-accent-foreground", + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", diff --git a/apps/www/src/lib/fonts.ts b/apps/www/src/lib/fonts.ts index ff01282..68f7dca 100644 --- a/apps/www/src/lib/fonts.ts +++ b/apps/www/src/lib/fonts.ts @@ -1,11 +1,3 @@ -import { Inter, Bricolage_Grotesque } from "next/font/google"; +import { GeistSans } from "geist/font/sans"; -export const fontSans = Inter({ - subsets: ["latin"], - variable: "--font-sans", -}); - -export const fontHeading = Bricolage_Grotesque({ - subsets: ["latin"], - variable: "--font-heading", -}); +export const fontSans = GeistSans; diff --git a/apps/www/src/styles/globals.css b/apps/www/src/styles/globals.css index ef8a7c3..a3cf252 100644 --- a/apps/www/src/styles/globals.css +++ b/apps/www/src/styles/globals.css @@ -32,7 +32,7 @@ --input: 240 5.9% 90%; --ring: 240 10% 3.9%; - --radius: 0.6rem; + --radius: 0.7rem; } :root[class~="dark"] { diff --git a/apps/www/tailwind.config.ts b/apps/www/tailwind.config.ts index baabec9..2db0f79 100644 --- a/apps/www/tailwind.config.ts +++ b/apps/www/tailwind.config.ts @@ -1,5 +1,4 @@ import type { Config } from "tailwindcss"; -import { fontFamily } from "tailwindcss/defaultTheme"; import baseConfig from "@rapidlaunch/tailwind-config/base"; @@ -10,10 +9,18 @@ export default { presets: [baseConfig], safelist: ["dark"], theme: { - extend: {}, - fontFamily: { - sans: ["var(--font-sans)", ...fontFamily.sans], - heading: ["var(--font-heading)", ...fontFamily.sans], + extend: { + animation: { + "border-beam": + "border-beam calc(var(--duration)*1s) infinite linear", + }, + keyframes: { + "border-beam": { + "100%": { + "offset-distance": "100%", + }, + }, + }, }, }, } satisfies Config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e259d5..470744e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: clsx: specifier: ^2.1.0 version: 2.1.1 + geist: + specifier: ^1.3.0 + version: 1.3.0(next@14.2.3) lucide-react: specifier: ^0.343.0 version: 0.343.0(react@18.2.0) @@ -4964,7 +4967,7 @@ packages: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.1(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -5022,7 +5025,7 @@ packages: enhanced-resolve: 5.16.0 eslint: 8.57.0 eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.3 is-core-module: 2.13.1 @@ -5117,35 +5120,6 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} engines: {node: '>=6.5.0'} @@ -5192,41 +5166,6 @@ packages: - supports-color dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.8.0)(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}