Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"radix-ui": "^1.4.3",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-helmet-async": "^3.0.0",
"react-use": "^17.6.0",
"shadcn": "^4.0.6",
"tailwind-merge": "^3.5.0",
Expand Down
64 changes: 64 additions & 0 deletions frontend/src/components/SEO.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Helmet } from 'react-helmet-async';
import { useLocation } from 'react-router-dom';

interface SEOProps {
title: string;
description: string;
canonical?: string;
image?: string;
type?: string;
robots?: string;
keywords?: string;
twitterCard?: string;
}

export default function SEO({
title,
description,
canonical,
image,
type = 'website',
robots = 'index,follow',
keywords,
twitterCard = 'summary_large_image',
}: SEOProps) {
const location = useLocation();
const siteUrl = 'https://codex-iter.in';
const url = canonical || `${siteUrl}${location.pathname}`;

// Fallback to a global default social preview image if none provided
const defaultImage = `${siteUrl}/codex_dark.png`; // Using the existing icon as default
const ogImage = image || defaultImage;

return (
<Helmet>
{/* Basic Metadata */}
<title>{title}</title>
<meta name="description" content={description} />
<meta name="robots" content={robots} />
{keywords && <meta name="keywords" content={keywords} />}

{/* Canonical URL */}
<link rel="canonical" href={url} />

{/* Open Graph / Facebook */}
<meta property="og:type" content={type} />
<meta property="og:url" content={url} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={ogImage} />
<meta property="og:site_name" content="CODEX ITER" />
<meta property="og:locale" content="en_US" />

{/* Twitter */}
<meta name="twitter:card" content={twitterCard} />
<meta name="twitter:url" content={url} />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage} />

{/* Viewport & Language (usually in index.html, but safe to reinforce if needed) */}
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</Helmet>
);
}
8 changes: 5 additions & 3 deletions frontend/src/components/layout/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ export default function Footer() {
<motion.h5 variants={itemAnim} className="font-black text-xl mb-6 uppercase tracking-widest text-primary">Connect</motion.h5>
<div className="flex gap-4">
{[
{ icon: <Linkedin size={24} />, href: settings?.linkedin || "#", id: "linkedin" },
{ icon: <Mail size={24} />, href: settings?.email ? `mailto:${settings.email}` : "#", id: "email" },
{ icon: <Instagram size={24} />, href: settings?.instagram || "#", id: "instagram" },
{ icon: <Linkedin size={24} />, href: settings?.linkedin || "https://www.linkedin.com/company/codex-iter", id: "linkedin" },
{ icon: <Mail size={24} />, href: settings?.email ? `mailto:${settings.email}` : "mailto:codexiter@gmail.com", id: "email" },
{ icon: <Instagram size={24} />, href: settings?.instagram || "https://www.instagram.com/codexiter", id: "instagram" },
].map(({ icon, href, id }) => (
<motion.a
key={id}
href={href}
target="_blank"
rel="noopener noreferrer"
variants={itemAnim}
whileHover={{ rotate: 15, scale: 1.15 }}
whileTap={{ scale: 0.9 }}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/layout/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function Navbar() {
<div className="max-w-7xl mx-auto flex items-center justify-between">
<Link to="/" className="flex items-center gap-2">
<div className="p-1">
{scrolled ? <img src={codex_light} alt="" className="h-10 w-9" /> : <img src={codex} alt="" className="h-10 w-9" />}
{scrolled ? <img src={codex_light} alt="CODEX ITER Logo" className="h-10 w-9" /> : <img src={codex} alt="CODEX ITER Logo" className="h-10 w-9" />}
</div>
<span className={`text-2xl font-black tracking-tighter transition-colors ${scrolled ? "text-white" : "text-slate-900"}`}>
CODEX ITER
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { HelmetProvider } from 'react-helmet-async'
import './index.css'
import App from './App.tsx'

createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
<HelmetProvider>
<App />
</HelmetProvider>
</StrictMode>,
)
8 changes: 8 additions & 0 deletions frontend/src/pages/BlogDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { client } from "../sanity/client";
import { urlFor } from "../sanity/image";
import { PortableText } from "@portabletext/react";
import { ScrollReveal } from "../components/animations/ScrollReveal";
import SEO from "../components/SEO";

export default function BlogDetail() {
const { slug } = useParams<{ slug: string }>();
Expand Down Expand Up @@ -58,6 +59,13 @@ export default function BlogDetail() {

return (
<div className="bg-background-light min-h-screen font-display text-slate-900 pb-20">
<SEO
title={`${post.title} | CODEX ITER`}
description={post.desc}
image={post.image ? urlFor(post.image).url() : undefined}
canonical={`https://codex-iter.in/blogs/${slug}`}
type="article"
/>
<div className="max-w-4xl mx-auto px-6 pt-32">
<ScrollReveal>
<Link to="/blogs" className="inline-flex items-center gap-2 text-primary font-bold uppercase text-sm mb-8 hover:underline">
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/pages/Blogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ScrollReveal, StaggerContainer, StaggerItem } from "../components/anima
import { useEffect, useState } from "react";
import { client } from "../sanity/client";
import { urlFor } from "../sanity/image";
import SEO from "../components/SEO";

export default function Blogs() {
const { hero } = mockData.blogs;
Expand Down Expand Up @@ -68,6 +69,10 @@ export default function Blogs() {

return (
<div className="bg-white min-h-screen">
<SEO
title="Blogs | CODEX ITER"
description="Read our latest technical blogs, insights, and updates from the Codex community."
/>
<main className="px-6 md:px-20 py-12 max-w-7xl mx-auto w-full">

{/* Header Section */}
Expand Down
9 changes: 7 additions & 2 deletions frontend/src/pages/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TiltCard from "../components/animations/TiltCard";
import { useEffect, useState } from "react";
import { client } from "../sanity/client";
import { urlFor } from "../sanity/image";
import SEO from "../components/SEO";

const prefersReduced =
typeof window !== "undefined" &&
Expand Down Expand Up @@ -194,16 +195,20 @@ export default function Events() {

return (
<div className="bg-background-light text-primary min-h-screen">
<SEO
title="Events | CODEX ITER"
description="Discover upcoming, ongoing, and past events at Codex ITER."
/>
<main className="flex-1 px-6 py-12 md:px-20 max-w-7xl mx-auto w-full">

{/* Header */}
<ScrollReveal className="mb-16">
<div className="inline-block px-4 py-1 text-white text-xs font-black uppercase tracking-[0.3em] mb-4" style={{ backgroundColor: '#00B4D8' }}>
{hero.label}
</div>
<h2 className="text-6xl md:text-8xl font-black uppercase leading-none tracking-tighter mb-6 font-display">
<h1 className="text-6xl md:text-8xl font-black uppercase leading-none tracking-tighter mb-6 font-display">
{hero.titlePart1}<br /><span className="text-white bg-primary px-2">{hero.titlePart2}</span>
</h2>
</h1>
<p className="max-w-xl text-lg font-bold leading-tight border-l-4 border-primary pl-4 uppercase">
{hero.description}
</p>
Expand Down
11 changes: 8 additions & 3 deletions frontend/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ScrollReveal, StaggerContainer, StaggerItem } from "../components/anima
import main_logo from "../assets/main_logo.png"
import { client } from "../sanity/client";
import { urlFor } from "../sanity/image";
import SEO from "../components/SEO";

const prefersReduced =
typeof window !== "undefined" &&
Expand Down Expand Up @@ -134,6 +135,10 @@ export default function Home() {

return (
<div>
<SEO
title="CODEX ITER | A Decade of Technical Culture"
description="Join the league of exceptional developers and help us build the next decade of engineering culture."
/>
{/* ── HERO ────────────────────────────────────────────────── */}
<section className="relative min-h-[90vh] flex items-center overflow-hidden border-b-4 border-slate-900 grid-pattern bg-background-light">
<div className="max-w-6xl mx-auto px-6 grid lg:grid-cols-2 gap-12 items-center w-full py-20">
Expand All @@ -147,15 +152,15 @@ export default function Home() {
{hero.established}
</motion.div>

<p className="text-5xl md:text-[5.5rem] font-black leading-[0.9] text-slate-900 mb-6 font-display">
<h1 className="text-5xl md:text-[5.5rem] font-black leading-[0.9] text-slate-900 mb-6 font-display">
<AnimatedHeading text={hero.title} />{" "}
<br />
<span className="text-primary italic">
<AnimatedHeading text={hero.subtitle1} />
</span>{" "}
<br />
<AnimatedHeading text={hero.subtitle2} />
</p>
</h1>

{/* Typing subheading */}
<p className="text-xl md:text-xl font-medium text-slate-800 mb-10 max-w-lg border-l-4 border-primary pl-6 min-h-16">
Expand Down Expand Up @@ -199,7 +204,7 @@ export default function Home() {
<div className="absolute inset-0 bg-white border-4 border-slate-900 brutalist-shadow -rotate-2 flex items-center justify-center overflow-hidden">
<div className="absolute inset-0 opacity-20 grid-pattern" />
<div className="relative z-10 text-center">
<img src={main_logo} alt="" className="h-60 w-60" />
<img src={main_logo} alt="CODEX ITER Main Logo" className="h-60 w-60" />
<div className="mt-4 font-mono text-slate-900 font-bold bg-background-light p-2 tracking-widest text-sm">
{hero.loadingText}
</div>
Expand Down
9 changes: 7 additions & 2 deletions frontend/src/pages/Team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TiltCard from "../components/animations/TiltCard";
import { useEffect, useState, useRef } from "react";
import { client } from "../sanity/client";
import { urlFor } from "../sanity/image";
import SEO from "../components/SEO";

const prefersReduced =
typeof window !== "undefined" &&
Expand Down Expand Up @@ -152,16 +153,20 @@ export default function Team() {

return (
<div className="bg-background-light min-h-screen font-display text-slate-900">
<SEO
title="Team | CODEX ITER"
description="Meet the force behind Codex ITER. The coordinators, members, and alumni."
/>
<main className="max-w-7xl mx-auto px-6 md:px-20 py-16">

{/* Hero */}
<ScrollReveal className="mb-20">
<div className="inline-block bg-primary text-white px-4 py-1 mb-4 font-bold uppercase tracking-widest text-xs border-2 border-slate-900">
{hero.label}
</div>
<h2 className="text-6xl md:text-8xl font-black text-slate-900 uppercase leading-none tracking-tighter mb-6 font-display">
<h1 className="text-6xl md:text-8xl font-black text-slate-900 uppercase leading-none tracking-tighter mb-6 font-display">
{hero.titlePart1}<br /><span className="text-primary italic">{hero.titlePart2}</span>
</h2>
</h1>
<p className="text-xl md:text-2xl font-medium max-w-2xl text-slate-700 border-l-8 border-primary pl-6">
{hero.description}
</p>
Expand Down
2 changes: 0 additions & 2 deletions frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ export default defineConfig({
sitemap({
hostname: 'https://codex-iter.in',
dynamicRoutes: [
'/',
'/about',
'/blogs',
'/events',
'/team'
Expand Down