diff --git a/apps/www/app/(home)/page.tsx b/apps/www/app/page.tsx similarity index 86% rename from apps/www/app/(home)/page.tsx rename to apps/www/app/page.tsx index 2e670b3..2259911 100644 --- a/apps/www/app/(home)/page.tsx +++ b/apps/www/app/page.tsx @@ -1,6 +1,8 @@ import React from "react"; -import Hero from "../../components/hero"; +import Hero from "@/components/hero"; import { + Heart, + LayoutTemplate, LibraryBig, Palette, Plus, @@ -13,10 +15,11 @@ import { cn } from "@/utils/cn"; import { File, Folder, Files } from "fumadocs-ui/components/files"; import { Spinner } from "ruru-ui/components/spinner"; import dynamic from "next/dynamic"; -import { GitHubLogoIcon } from "@radix-ui/react-icons"; +import { GitHubLogoIcon, HeartIcon } from "@radix-ui/react-icons"; import Link from "next/link"; -import { Button } from "ruru-ui/components/button"; import { Footer } from "@/components/footer"; +import ContributorCounter from "@/components/contributor-count"; +import Image from "next/image"; const CodeBlockServer = dynamic( () => import("@/components/ui/code-block-server"), @@ -81,9 +84,9 @@ export default function App() { return ( <>
-
+
-
+
+
+ +

+ Made Possible by You. +

+

+ Ruru UI is 100% powered by passion and open source community. +

+ + + +

+ Some of our best contributors. +

+
+ + + +
+ +
+
+ +

Theming

+
+

+ Customize theme your components. +

+
+
+ theme +
+ + +
+
+ +

Blocks

+
+

+ The Blocks To Build Your App Faster +

+
+
+ blocks +
+ +
+ + +
{ + repoOwner: string; + repoName: string; + displayCount?: number; +} + +export default async function ContributorCounter({ + repoOwner, + repoName, + displayCount = 20, + ...props +}: ContributorCounterProps): Promise { + const contributors = await fetchContributors(repoOwner, repoName); + const topContributors = contributors + .filter((contributor) => contributor.login !== "turbobot-temp") + .slice(0, displayCount); + + return ( +
+
+ {topContributors.map((contributor, i) => ( + + {`${contributor.login}'s + + ))} + {displayCount < contributors.length ? ( +
+ +{contributors.length - displayCount} +
+ ) : null} +
+
+ ); +} diff --git a/apps/www/components/hero.tsx b/apps/www/components/hero.tsx index 7c66728..33c5ece 100644 --- a/apps/www/components/hero.tsx +++ b/apps/www/components/hero.tsx @@ -5,45 +5,68 @@ import { GitHubLogoIcon } from "@radix-ui/react-icons"; import Link from "next/link"; import { Button, buttonVariants } from "ruru-ui/components/button"; import { useRouter } from "next/navigation"; +import Image from "next/image"; +import { cn } from "@/utils/utils"; const Hero = () => { const router = useRouter(); return ( -
+
+ bg dots + bg dots + bg dots -
+

-
+
330 x 56
Craft Seamless , - + {" "} @@ -58,7 +81,10 @@ const Hero = () => {
- +
{
Customizable - - + + Interfaces - with - + with + Ruru UI

-

+

the ultimate design system and UI library for creating seamless, beautiful, and highly customizable user interfaces.

-
+
- {/* */}
+
+ {["docs", "blocks", "theme", "sponsors"].map((i) => ( + + {i.charAt(0).toUpperCase() + i.slice(1)} + + ))} +
); diff --git a/apps/www/public/assets/background_dots.svg b/apps/www/public/assets/background_dots.svg new file mode 100644 index 0000000..5d45440 --- /dev/null +++ b/apps/www/public/assets/background_dots.svg @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/www/public/assets/blocks.svg b/apps/www/public/assets/blocks.svg new file mode 100644 index 0000000..eb820e9 --- /dev/null +++ b/apps/www/public/assets/blocks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/public/assets/glowing_logo.svg b/apps/www/public/assets/glowing_logo.svg new file mode 100644 index 0000000..58ce83e --- /dev/null +++ b/apps/www/public/assets/glowing_logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/public/assets/shaders.svg b/apps/www/public/assets/shaders.svg new file mode 100644 index 0000000..ee31c6c --- /dev/null +++ b/apps/www/public/assets/shaders.svg @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/www/public/assets/theme.svg b/apps/www/public/assets/theme.svg new file mode 100644 index 0000000..5269e1e --- /dev/null +++ b/apps/www/public/assets/theme.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/utils/get-contributors.ts b/apps/www/utils/get-contributors.ts new file mode 100644 index 0000000..5a25226 --- /dev/null +++ b/apps/www/utils/get-contributors.ts @@ -0,0 +1,31 @@ +export interface Contributor { + avatar_url: string; + login: string; + contributions: number; +} + +export async function fetchContributors( + repoOwner: string, + repoName: string, +): Promise { + const headers = new Headers(); + if (process.env.GITHUB_TOKEN) + headers.set("Authorization", `Bearer ${process.env.GITHUB_TOKEN}`); + + const response = await fetch( + `https://api.github.com/repos/${repoOwner}/${repoName}/contributors?per_page=50`, + { + headers, + next: { revalidate: 1000 * 1000 }, + }, + ); + + if (!response.ok) { + throw new Error(`Failed to fetch contributors: ${response.statusText}`); + } + + const contributors = (await response.json()) as Contributor[]; + return contributors + .filter((contributor) => !contributor.login.endsWith("[bot]")) + .sort((a, b) => b.contributions - a.contributions); +}