From 44fccf9cd571010083d331db87ff899dfb3e4347 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 29 Oct 2025 20:49:41 +0000 Subject: [PATCH] feat: add oss friends page --- apps/web/src/pages/api/oss-friends.ts | 23 +++++ apps/web/src/pages/oss-friends/index.tsx | 5 + apps/web/src/views/home/components/Footer.tsx | 2 +- apps/web/src/views/oss-friends/index.tsx | 99 +++++++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/pages/api/oss-friends.ts create mode 100644 apps/web/src/pages/oss-friends/index.tsx create mode 100644 apps/web/src/views/oss-friends/index.tsx diff --git a/apps/web/src/pages/api/oss-friends.ts b/apps/web/src/pages/api/oss-friends.ts new file mode 100644 index 00000000..7ad34ea4 --- /dev/null +++ b/apps/web/src/pages/api/oss-friends.ts @@ -0,0 +1,23 @@ +import type { NextApiRequest, NextApiResponse } from "next"; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse, +) { + if (req.method !== "GET") { + return res.status(405).json({ message: "Method not allowed" }); + } + + try { + const response = await fetch("https://formbricks.com/api/oss-friends"); + if (!response.ok) { + throw new Error("Failed to fetch from Formbricks"); + } + const data = await response.json(); + + return res.status(200).json(data); + } catch (error) { + console.error("Error fetching OSS friends:", error); + return res.status(500).json({ message: "Failed to fetch OSS friends" }); + } +} diff --git a/apps/web/src/pages/oss-friends/index.tsx b/apps/web/src/pages/oss-friends/index.tsx new file mode 100644 index 00000000..6c17497d --- /dev/null +++ b/apps/web/src/pages/oss-friends/index.tsx @@ -0,0 +1,5 @@ +import OSSFriendsView from "~/views/oss-friends"; + +export default function OSSFriends() { + return ; +} diff --git a/apps/web/src/views/home/components/Footer.tsx b/apps/web/src/views/home/components/Footer.tsx index 2452ef1d..1ab2c640 100644 --- a/apps/web/src/views/home/components/Footer.tsx +++ b/apps/web/src/views/home/components/Footer.tsx @@ -36,7 +36,7 @@ const Footer = () => { { name: t`Roadmap`, href: "/kan/roadmap" }, { name: t`GitHub`, href: "https://github.com/kanbn/kan" }, { name: t`Contact`, href: "mailto:support@kan.bn" }, - { name: t`OSS Friends`, href: "https://kan.bn/oss-friends" }, + { name: t`OSS Friends`, href: "/oss-friends" }, ], legal: [ { name: t`Terms of service`, href: "/terms" }, diff --git a/apps/web/src/views/oss-friends/index.tsx b/apps/web/src/views/oss-friends/index.tsx new file mode 100644 index 00000000..9c95ffe9 --- /dev/null +++ b/apps/web/src/views/oss-friends/index.tsx @@ -0,0 +1,99 @@ +import Link from "next/link"; +import { t } from "@lingui/core/macro"; +import { useEffect, useState } from "react"; + +import Button from "~/components/Button"; +import { PageHead } from "~/components/PageHead"; +import Layout from "../home/components/Layout"; + +interface OSSFriend { + name: string; + description: string; + href: string; +} + +interface OSSFriendsResponse { + data: OSSFriend[]; +} + +export default function OSSFriendsView() { + const [ossFriends, setOSSFriends] = useState([]); + const fetchOSSFriends = async (): Promise => { + try { + const response = await fetch("/api/oss-friends"); + + if (!response.ok) { + throw new Error("Failed to fetch OSS friends"); + } + const { data } = (await response.json()) as OSSFriendsResponse; + + return data; + } catch (error) { + console.error("Error fetching OSS friends:", error); + return []; + } + }; + + useEffect(() => { + async function fetchData() { + const data = await fetchOSSFriends(); + setOSSFriends(data); + } + void fetchData(); + }, []); + + return ( + + + +
+
+
+

+ {t`Open Source Friends`} +

+

+ {t`Check out some of our favorite open source projects.`} +

+
+
+
+
+ {ossFriends.map((friend, idx) => { + return ( +
+
+ +

+ {friend.name} +

+ + +

+ {friend.description} +

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