From 6d5d609449b56140f0f0b95e9c76c565a7e58306 Mon Sep 17 00:00:00 2001 From: Julien Tanay Date: Sat, 3 May 2025 14:34:12 +0200 Subject: [PATCH] feat: add work page --- .github/copilot-instructions.md | 11 ++ next.config.ts | 3 +- src/app/work/page.tsx | 297 ++++++++++++++++++++++++++++++++ 3 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 .github/copilot-instructions.md create mode 100644 src/app/work/page.tsx diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..c120a3e --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,11 @@ +# About + +This project is a landing page for our collective called "Lourd.dev". We're a duo of creative developers that partner with brands and influencers to create unique digital experiences. This is our portfolio site, showcasing our work and the services we offer. + +The website is made with React, Typescript, Next.js and Tailwind CSS. We want to create a modern, clean, and responsive design that reflects our brand identity. + +Our main colors are black and red. Our logo is a stylized gym weight with the word "Lourd" in a bold, modern font. We want to use this logo as a focal point on the landing page. + +# Your role + +Help us build a landing page for our collective. The page should be visually appealing, easy to navigate, and effectively communicate our brand identity. We want to highlight our work, the services we offer, and provide a way for potential clients to get in touch with us. diff --git a/next.config.ts b/next.config.ts index 676fa21..a7d4cbc 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,8 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - output: "export" + output: "export", + images: { unoptimized: true }, }; export default nextConfig; diff --git a/src/app/work/page.tsx b/src/app/work/page.tsx new file mode 100644 index 0000000..87c9e8a --- /dev/null +++ b/src/app/work/page.tsx @@ -0,0 +1,297 @@ +"use client"; + +import { useState, useEffect } from "react"; +import Image from "next/image"; +import Link from "next/link"; + +interface PortfolioItem { + name: string; + year: number; + avgViewers: string; + technologies: string[]; + influencers: string[]; + brands: string[]; + image: string; + links: Array<{ + label: string; + url: string; + }>; + description: string; +} + +export default function Work() { + const [password, setPassword] = useState(""); + const [isAuthenticated, setIsAuthenticated] = useState(false); + const [showError, setShowError] = useState(false); + const correctPassword = "letsworktogether"; + + const portfolioItems: PortfolioItem[] = [ + { + name: "Twitch Extension for Team Vitality", + year: 2024, + avgViewers: "85K+", + technologies: [ + "Twitch Extensions API", + "React", + "WebSockets", + "Node.js", + "AWS", + ], + influencers: ["Gotaga", "Kaydop", "ZywOo"], + brands: ["Team Vitality", "Red Bull"], + image: "/bkp/partners/vitality.png", + links: [ + { label: "Extension Store", url: "#" }, + { label: "Case Study", url: "#" }, + ], + description: + "Interactive viewer engagement tools for esports streams, including real-time polls, stats overlays, and viewer predictions. Integrated with team statistics and tournament data.", + }, + { + name: "RocketBaguette Tournament Platform", + year: 2023, + avgViewers: "45K", + technologies: [ + "Twitch Chat Interactions", + "Overlay System", + "Tournament API", + "WebSockets", + ], + influencers: ["Fairy Peak", "Mout"], + brands: ["RocketBaguette", "Psyonix"], + image: "/bkp/partners/rocketbaguette.png", + links: [ + { label: "Platform", url: "#" }, + { label: "GitHub", url: "#" }, + ], + description: + "Custom overlay system for Rocket League tournaments with automated score tracking, player statistics, and interactive audience features including viewer predictions and chat commands.", + }, + { + name: "Interactive Stream for JK", + year: 2023, + avgViewers: "120K", + technologies: [ + "Twitch Chat Interactions", + "Custom Alerts", + "Donation Integration", + "Backoffice Dashboard", + ], + influencers: ["JK", "Squeezie"], + brands: ["YouTube Gaming", "Logitech"], + image: "/bkp/partners/jk.png", + links: [ + { label: "Stream Highlights", url: "#" }, + { label: "Behind the Scenes", url: "#" }, + ], + description: + "Audience participation features for high-profile Twitch streamer including custom alerts, interactive minigames triggered by chat, and advanced moderation tools with analytics dashboard.", + }, + { + name: "Custom Chat Bot System", + year: 2024, + avgViewers: "30K-75K", + technologies: [ + "Bot Framework", + "Chat Analysis", + "Backoffice", + "Analytics Dashboard", + "Moderation Tools", + ], + influencers: ["Various Partners"], + brands: ["Multiple Gaming Brands"], + image: "/bkp/partners/vitality.png", // Placeholder - should be replaced with actual image + links: [ + { label: "Documentation", url: "#" }, + { label: "Demo", url: "#" }, + ], + description: + "Advanced moderation and engagement tools for growing communities including AI-powered content filtering, custom commands, viewer analytics, and interactive games.", + }, + ]; + + // Check if user has previously authenticated + useEffect(() => { + const auth = localStorage.getItem("lourdWorkAuth"); + if (auth === "true") { + setIsAuthenticated(true); + } + }, []); + + const handlePasswordChange = (e: React.ChangeEvent) => { + setPassword(e.target.value); + setShowError(false); + + // Check if password is correct + if (e.target.value === correctPassword) { + setIsAuthenticated(true); + localStorage.setItem("lourdWorkAuth", "true"); + } + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + if (password !== correctPassword) { + setShowError(true); + } + } + }; + + return ( +
+ {!isAuthenticated ? ( +
+ Lourd logo +

work

+

+ Our portfolio is protected. Please enter the password to view our + work. +

+
+ + {showError && ( +

Incorrect password

+ )} +
+
+ ) : ( +
+

our work

+ + {/* NDA Disclaimer */} +
+

Confidentiality Notice

+

+ The projects showcased here are presented with respect to the timelines and constraints of our clients. + All work is covered by non-disclosure agreements, and the information shared has been approved for + portfolio purposes. Some details may be omitted to respect client confidentiality. + Last updated: May 3, 2025 +

+
+ + {/* Portfolio items */} +
+ {portfolioItems.map((item, index) => ( +
+
+ {/* Project image */} +
+ {item.name} +
+ + {/* Project details */} +
+

{item.name}

+

{item.description}

+ + {/* Details grid */} +
+
+

+ Year +

+

{item.year}

+
+
+

+ Avg. Viewers +

+

{item.avgViewers}

+
+
+

+ Technologies +

+
+ {item.technologies.map((tech, techIndex) => ( + + {tech} + + ))} +
+
+
+

+ Influencers +

+

{item.influencers.join(", ")}

+
+
+

+ Brands +

+

{item.brands.join(", ")}

+
+
+ + {/* Links */} +
+

+ Links +

+
+ {item.links.map((link, linkIndex) => ( + + {link.label} + + ))} +
+
+
+
+
+ ))} +
+ + {/* Contact section */} +
+

+ Let's create something together +

+

+ Interested in working with us? We're always looking for exciting + new projects that push the boundaries of interactive experiences + for streamers and their communities. +

+ + Contact us + +
+
+ )} +
+ ); +}