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) => (
-
-
-
-
-
- ))}
-
-
- );
-}
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}