diff --git a/client/src/app/user/[name]/not-found.tsx b/client/src/app/user/[name]/not-found.tsx
new file mode 100644
index 0000000..e967d00
--- /dev/null
+++ b/client/src/app/user/[name]/not-found.tsx
@@ -0,0 +1,8 @@
+export default function NotFound() {
+ return (
+
+
Error 404
+
User not found
+
+ );
+}
diff --git a/client/src/app/user/[name]/page.tsx b/client/src/app/user/[name]/page.tsx
new file mode 100644
index 0000000..7a768b5
--- /dev/null
+++ b/client/src/app/user/[name]/page.tsx
@@ -0,0 +1,158 @@
+import CopyLink from "@/components/user/CopyLink";
+import { fetchProfileData } from "@/lib/user";
+import { notFound } from "next/navigation";
+
+export async function generateMetadata({ params }: { params: { name: string } }) {
+ const data = await fetchProfileData(params.name);
+ if (!data) {
+ return {
+ description: "User not found",
+ robots: {
+ index: false,
+ follow: false,
+ nocache: true,
+ noarchive: true
+ }
+ };
+ }
+ return {
+ title: `${data.name} | chessu`,
+ description: `${data.name}'s profile`,
+ openGraph: {
+ title: `${data.name} | chessu`,
+ description: `${data.name}'s profile on chessu`,
+ url: `https://ches.su/user/${data.name}`,
+ siteName: "chessu",
+ locale: "en_US",
+ type: "website"
+ },
+ robots: {
+ index: true,
+ follow: false,
+ nocache: true
+ }
+ };
+}
+
+export default async function Profile({ params }: { params: { name: string } }) {
+ const data = await fetchProfileData(params.name);
+ if (!data) {
+ notFound();
+ }
+
+ return (
+
+
+
{data.name}
+
+
+ Wins
+ {data.wins}
+
+
+ Draws
+ {data.draws}
+
+
+ Losses
+ {data.losses}
+
+
+
+
+
+
+
+ );
+}
diff --git a/client/src/components/user/CopyLink.tsx b/client/src/components/user/CopyLink.tsx
new file mode 100644
index 0000000..e47521d
--- /dev/null
+++ b/client/src/components/user/CopyLink.tsx
@@ -0,0 +1,37 @@
+"use client";
+
+import { useState } from "react";
+import { IconCopy } from "@tabler/icons-react";
+
+export default function CopyLink({ name }: { name: string }) {
+ const [copiedLink, setCopiedLink] = useState(false);
+
+ function copyLink() {
+ const text = `https://ches.su/user/${name}`;
+
+ if ("clipboard" in navigator) {
+ navigator.clipboard.writeText(text);
+ } else {
+ document.execCommand("copy", true, text);
+ }
+ setCopiedLink(true);
+ setTimeout(() => {
+ setCopiedLink(false);
+ }, 5000);
+ }
+ return (
+
+
+
+ copied to clipboard
+
+
+ );
+}