summaryrefslogtreecommitdiff
path: root/apps/web/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/app')
-rw-r--r--apps/web/src/app/contributors/page.tsx100
-rw-r--r--apps/web/src/app/favicon.icobin4286 -> 0 bytes
-rw-r--r--apps/web/src/app/globals.css2
-rw-r--r--apps/web/src/app/layout.tsx39
-rw-r--r--apps/web/src/app/metadata.ts66
-rw-r--r--apps/web/src/app/page.tsx8
6 files changed, 132 insertions, 83 deletions
diff --git a/apps/web/src/app/contributors/page.tsx b/apps/web/src/app/contributors/page.tsx
index f5fa0755..67957c32 100644
--- a/apps/web/src/app/contributors/page.tsx
+++ b/apps/web/src/app/contributors/page.tsx
@@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
import { ExternalLink } from "lucide-react";
import Link from "next/link";
import { GithubIcon } from "@/components/icons";
+import { Badge } from "@/components/ui/badge";
export const metadata: Metadata = {
title: "Contributors - OpenCut",
@@ -49,7 +50,7 @@ async function getContributors(): Promise<Contributor[]> {
const contributors = await response.json();
const filteredContributors = contributors.filter(
- (contributor: any) => contributor.type === "User"
+ (contributor: Contributor) => contributor.type === "User"
);
return filteredContributors;
@@ -61,8 +62,8 @@ async function getContributors(): Promise<Contributor[]> {
export default async function ContributorsPage() {
const contributors = await getContributors();
- const topContributor = contributors[0];
- const otherContributors = contributors.slice(1);
+ const topContributors = contributors.slice(0, 2);
+ const otherContributors = contributors.slice(2);
return (
<div className="min-h-screen bg-background">
@@ -77,10 +78,10 @@ export default async function ContributorsPage() {
<div className="relative container mx-auto px-4 py-16">
<div className="max-w-6xl mx-auto">
<div className="text-center mb-20">
- <div className="inline-flex items-center gap-2 bg-muted/50 text-muted-foreground px-3 py-1 rounded-full text-sm mb-6">
+ <Badge variant="secondary" className="gap-2 mb-6">
<GithubIcon className="h-3 w-3" />
Open Source
- </div>
+ </Badge>
<h1 className="text-5xl md:text-6xl font-bold tracking-tight mb-6">
Contributors
</h1>
@@ -105,54 +106,59 @@ export default async function ContributorsPage() {
</div>
</div>
- {topContributor && (
+ {topContributors.length > 0 && (
<div className="mb-20">
<div className="text-center mb-12">
<h2 className="text-2xl font-semibold mb-2">
- Top Contributor
+ Top Contributors
</h2>
<p className="text-muted-foreground">
Leading the way in contributions
</p>
</div>
- <Link
- href={topContributor.html_url}
- target="_blank"
- rel="noopener noreferrer"
- className="group block"
- >
- <div className="relative mx-auto max-w-md">
- <div className="absolute inset-0 bg-gradient-to-r from-muted/50 to-muted/30 rounded-2xl blur group-hover:blur-md transition-all duration-300" />
- <Card className="relative bg-background/80 backdrop-blur-sm border-2 group-hover:border-muted-foreground/20 transition-all duration-300 group-hover:shadow-xl">
- <CardContent className="p-8 text-center">
- <div className="relative mb-6">
- <Avatar className="h-24 w-24 mx-auto ring-4 ring-background shadow-2xl">
- <AvatarImage
- src={topContributor.avatar_url}
- alt={`${topContributor.login}'s avatar`}
- />
- <AvatarFallback className="text-lg font-semibold">
- {topContributor.login.charAt(0).toUpperCase()}
- </AvatarFallback>
- </Avatar>
- <div className="absolute -top-2 -right-2 bg-foreground text-background rounded-full w-8 h-8 flex items-center justify-center text-sm font-bold">
- 1
- </div>
- </div>
- <h3 className="text-xl font-semibold mb-2 group-hover:text-foreground/80 transition-colors">
- {topContributor.login}
- </h3>
- <div className="flex items-center justify-center gap-2 text-muted-foreground">
- <span className="font-medium text-foreground">
- {topContributor.contributions}
- </span>
- <span>contributions</span>
- </div>
- </CardContent>
- </Card>
- </div>
- </Link>
+ <div className="flex flex-col md:flex-row gap-6 justify-center max-w-4xl mx-auto">
+ {topContributors.map((contributor, index) => (
+ <Link
+ key={contributor.id}
+ href={contributor.html_url}
+ target="_blank"
+ rel="noopener noreferrer"
+ className="group block flex-1"
+ >
+ <div className="relative mx-auto max-w-md">
+ <div className="absolute inset-0 bg-gradient-to-r from-muted/50 to-muted/30 rounded-2xl blur group-hover:blur-md transition-all duration-300" />
+ <Card className="relative bg-background/80 backdrop-blur-sm border-2 group-hover:border-muted-foreground/20 transition-all duration-300 group-hover:shadow-xl">
+ <CardContent className="p-8 text-center">
+ <div className="relative mb-6">
+ <Avatar className="h-24 w-24 mx-auto ring-4 ring-background shadow-2xl">
+ <AvatarImage
+ src={contributor.avatar_url}
+ alt={`${contributor.login}'s avatar`}
+ />
+ <AvatarFallback className="text-lg font-semibold">
+ {contributor.login.charAt(0).toUpperCase()}
+ </AvatarFallback>
+ </Avatar>
+ <div className="absolute -top-2 -right-2 bg-foreground text-background rounded-full w-8 h-8 flex items-center justify-center text-sm font-bold">
+ {index + 1}
+ </div>
+ </div>
+ <h3 className="text-xl font-semibold mb-2 group-hover:text-foreground/80 transition-colors">
+ {contributor.login}
+ </h3>
+ <div className="flex items-center justify-center gap-2 text-muted-foreground">
+ <span className="font-medium text-foreground">
+ {contributor.contributions}
+ </span>
+ <span>contributions</span>
+ </div>
+ </CardContent>
+ </Card>
+ </div>
+ </Link>
+ ))}
+ </div>
</div>
)}
@@ -167,7 +173,7 @@ export default async function ContributorsPage() {
</p>
</div>
- <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
+ <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-6">
{otherContributors.map((contributor, index) => (
<Link
key={contributor.id}
@@ -179,8 +185,8 @@ export default async function ContributorsPage() {
animationDelay: `${index * 50}ms`,
}}
>
- <div className="text-center p-4 rounded-xl hover:bg-muted/50 transition-all duration-300 group-hover:scale-105">
- <Avatar className="h-16 w-16 mx-auto mb-3 ring-2 ring-transparent group-hover:ring-muted-foreground/20 transition-all duration-300">
+ <div className="text-center p-2 rounded-xl transition-all duration-300 hover:opacity-50">
+ <Avatar className="h-16 w-16 mx-auto mb-3">
<AvatarImage
src={contributor.avatar_url}
alt={`${contributor.login}'s avatar`}
diff --git a/apps/web/src/app/favicon.ico b/apps/web/src/app/favicon.ico
deleted file mode 100644
index cb20127b..00000000
--- a/apps/web/src/app/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css
index 2169dbbc..1c8a7887 100644
--- a/apps/web/src/app/globals.css
+++ b/apps/web/src/app/globals.css
@@ -39,7 +39,7 @@
--sidebar-ring: 0 0% 3.9%;
}
.dark {
- --background: 0 0% 8%;
+ --background: 0 0% 6%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 5d33100d..8188d31b 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -1,4 +1,3 @@
-import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { Analytics } from "@vercel/analytics/react";
@@ -6,46 +5,15 @@ import Script from "next/script";
import "./globals.css";
import { Toaster } from "../components/ui/sonner";
import { TooltipProvider } from "../components/ui/tooltip";
+import { DevelopmentDebug } from "../components/development-debug";
+import { baseMetaData } from "./metadata";
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
});
-export const metadata: Metadata = {
- title: "OpenCut",
- description:
- "A simple but powerful video editor that gets the job done. In your browser.",
- openGraph: {
- title: "OpenCut",
- description:
- "A simple but powerful video editor that gets the job done. In your browser.",
- url: "https://opencut.app",
- siteName: "OpenCut",
- locale: "en_US",
- type: "website",
- images: [
- {
- url: "https://opencut.app/opengraph-image.jpg",
- width: 1200,
- height: 630,
- alt: "OpenCut",
- },
- ],
- },
- twitter: {
- card: "summary_large_image",
- title: "OpenCut",
- description:
- "A simple but powerful video editor that gets the job done. In your browser.",
- creator: "@opencutapp",
- images: ["/opengraph-image.jpg"],
- },
- robots: {
- index: true,
- follow: true,
- },
-};
+export const metadata = baseMetaData;
export default function RootLayout({
children,
@@ -60,6 +28,7 @@ export default function RootLayout({
{children}
<Analytics />
<Toaster />
+ <DevelopmentDebug />
<Script
src="https://app.databuddy.cc/databuddy.js"
strategy="afterInteractive"
diff --git a/apps/web/src/app/metadata.ts b/apps/web/src/app/metadata.ts
new file mode 100644
index 00000000..4e387014
--- /dev/null
+++ b/apps/web/src/app/metadata.ts
@@ -0,0 +1,66 @@
+import { Metadata } from "next";
+
+const title = "OpenCut";
+const description = "A simple but powerful video editor that gets the job done. In your browser.";
+const openGraphImageUrl = "https://opencut.app/opengraph-image.jpg";
+const twitterImageUrl = "/opengraph-image.jpg";
+
+export const baseMetaData: Metadata = {
+ title: title,
+ description: description,
+ openGraph: {
+ title: title,
+ description: description,
+ url: "https://opencut.app",
+ siteName: "OpenCut",
+ locale: "en_US",
+ type: "website",
+ images: [
+ {
+ url: openGraphImageUrl,
+ width: 1200,
+ height: 630,
+ alt: "OpenCut",
+ },
+ ],
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: title,
+ description: description,
+ creator: "@opencutapp",
+ images: [twitterImageUrl],
+ },
+ robots: {
+ index: true,
+ follow: true,
+ },
+ icons: {
+ icon: [
+ { url: "/favicon.ico" },
+ { url: "/icons/favicon-16x16.png", sizes: "16x16", type: "image/png" },
+ { url: "/icons/favicon-32x32.png", sizes: "32x32", type: "image/png" },
+ { url: "/icons/favicon-96x96.png", sizes: "96x96", type: "image/png" },
+ ],
+ apple: [
+ { url: "/icons/apple-icon-57x57.png", sizes: "57x57", type: "image/png" },
+ { url: "/icons/apple-icon-60x60.png", sizes: "60x60", type: "image/png" },
+ { url: "/icons/apple-icon-72x72.png", sizes: "72x72", type: "image/png" },
+ { url: "/icons/apple-icon-76x76.png", sizes: "76x76", type: "image/png" },
+ { url: "/icons/apple-icon-114x114.png", sizes: "114x114", type: "image/png" },
+ { url: "/icons/apple-icon-120x120.png", sizes: "120x120", type: "image/png" },
+ { url: "/icons/apple-icon-144x144.png", sizes: "144x144", type: "image/png" },
+ { url: "/icons/apple-icon-152x152.png", sizes: "152x152", type: "image/png" },
+ { url: "/icons/apple-icon-180x180.png", sizes: "180x180", type: "image/png" },
+ ],
+ shortcut: ["/favicon.ico"]
+ },
+ appleWebApp: {
+ capable: true,
+ title: title,
+ },
+ manifest: "/manifest.json",
+ other: {
+ "msapplication-config": "/browserconfig.xml"
+ }
+};
diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx
index dcedab32..e9957e1b 100644
--- a/apps/web/src/app/page.tsx
+++ b/apps/web/src/app/page.tsx
@@ -1,6 +1,7 @@
import { Hero } from "@/components/landing/hero";
import { Header } from "@/components/header";
import { getWaitlistCount } from "@/lib/waitlist";
+import Image from "next/image";
// Force dynamic rendering so waitlist count updates in real-time
export const dynamic = "force-dynamic";
@@ -10,6 +11,13 @@ export default async function Home() {
return (
<div>
+ <Image
+ className="fixed top-0 left-0 -z-50 size-full object-cover"
+ src="/landing-page-bg.png"
+ height={1903.5}
+ width={1269}
+ alt="landing-page.bg"
+ />
<Header />
<Hero signupCount={signupCount} />
</div>