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/(marketing)/page.tsx b/apps/www/src/app/(marketing)/page.tsx
index 2e402bc..ae9bc32 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}