From 1c20027d33bcf303d6a9b40970cd8216c489f0d5 Mon Sep 17 00:00:00 2001 From: "Dominik K." Date: Wed, 30 Jul 2025 15:20:44 +0200 Subject: feat: create external tools section (#493) * feat: create external tools section * fix: better wording --- apps/web/package.json | 2 +- apps/web/src/app/contributors/page.tsx | 57 ++++++++++++++++++++++++++++++++-- apps/web/src/components/icons.tsx | 50 +++++++++++++++++++++++++++++ apps/web/src/constants/site.ts | 22 +++++++++++++ 4 files changed, 128 insertions(+), 3 deletions(-) (limited to 'apps') diff --git a/apps/web/package.json b/apps/web/package.json index f5cd7da4..9531b6c7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -43,7 +43,7 @@ "input-otp": "^1.4.1", "lucide-react": "^0.468.0", "motion": "^12.18.1", - "next": "^15.4.3", + "next": "^15.4.5", "next-themes": "^0.4.4", "pg": "^8.16.2", "radix-ui": "^1.4.2", diff --git a/apps/web/src/app/contributors/page.tsx b/apps/web/src/app/contributors/page.tsx index 6a524866..29151bd8 100644 --- a/apps/web/src/app/contributors/page.tsx +++ b/apps/web/src/app/contributors/page.tsx @@ -5,8 +5,14 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { ExternalLink } from "lucide-react"; import Link from "next/link"; -import { GithubIcon } from "@/components/icons"; +import { + GithubIcon, + MarbleIcon, + VercelIcon, + DataBuddyIcon, +} from "@/components/icons"; import { Badge } from "@/components/ui/badge"; +import { EXTERNAL_TOOLS } from "@/constants/site"; export const metadata: Metadata = { title: "Contributors - OpenCut", @@ -39,7 +45,7 @@ async function getContributors(): Promise { "User-Agent": "OpenCut-Web-App", }, next: { revalidate: 600 }, // 10 minutes - } + } as RequestInit ); if (!response.ok) { @@ -236,6 +242,53 @@ export default async function ContributorsPage() { )} +
+
+

External Tools

+

+ Tools we use to build OpenCut +

+
+ +
+ {EXTERNAL_TOOLS.map((tool, index) => { + const IconComponent = { + MarbleIcon, + VercelIcon, + DataBuddyIcon, + }[tool.icon]; + + return ( + + + +
+
+ +
+
+

+ {tool.name} +

+

+ {tool.description} +

+
+
+ + ); + })} +
+
+

Join the community

diff --git a/apps/web/src/components/icons.tsx b/apps/web/src/components/icons.tsx index 6099c052..43f953e8 100644 --- a/apps/web/src/components/icons.tsx +++ b/apps/web/src/components/icons.tsx @@ -113,3 +113,53 @@ export function BackgroundIcon({ className }: { className?: string }) { ); } + +export function MarbleIcon({ + className = "", + size = 32, +}: { + className?: string; + size?: number; +}) { + return ( + + + + + ); +} + +export function DataBuddyIcon({ + className = "", + size = 32, +}: { + className?: string; + size?: number; +}) { + return ( + + + + + ); +} diff --git a/apps/web/src/constants/site.ts b/apps/web/src/constants/site.ts index f47f6470..00bd649f 100644 --- a/apps/web/src/constants/site.ts +++ b/apps/web/src/constants/site.ts @@ -9,3 +9,25 @@ export const SITE_INFO = { twitterImage: "/open-graph/default.jpg", favicon: "/favicon.ico", }; + +export const EXTERNAL_TOOLS = [ + { + name: "Marble", + description: + "Modern headless CMS for content management and the blog for OpenCut", + url: "https://marblecms.com?utm_source=opencut", + icon: "MarbleIcon" as const, + }, + { + name: "Vercel", + description: "Platform where we deploy and host OpenCut", + url: "https://vercel.com?utm_source=opencut", + icon: "VercelIcon" as const, + }, + { + name: "Databuddy", + description: "GDPR compliant analytics and user insights for OpenCut", + url: "https://databuddy.cc?utm_source=opencut", + icon: "DataBuddyIcon" as const, + }, +]; -- cgit v1.3.1