diff --git a/app/(footer)/contact/page.tsx b/app/(footer)/contact/page.tsx
index a0b41d6..17952bb 100644
--- a/app/(footer)/contact/page.tsx
+++ b/app/(footer)/contact/page.tsx
@@ -7,33 +7,35 @@ import {
Send,
Home
} from "lucide-react";
+import { siteConfig } from "@/lib/seo";
export const metadata: Metadata = {
- title: "Contact Us - FlagForge CTF Platform",
+ title: "Contact FlagForge | CTF Support and Cybersecurity Collaboration",
description:
- "Contact FlagForge for CTF support and cybersecurity inquiries via email, phone, or our Lalitpur office.",
+ "Contact FlagForge for platform support, partnerships, CTF collaboration, or general cybersecurity learning inquiries.",
keywords: [
"contact FlagForge",
- "CTF support",
- "cybersecurity help",
- "FlagForge team",
- "Nepal cybersecurity support",
- "Nepal CTF community",
+ "FlagForge support",
+ "CTF platform contact",
+ "cybersecurity collaboration",
+ "Nepal cybersecurity community",
],
authors: [{ name: "FlagForge Team" }],
openGraph: {
- title: "Contact FlagForge - Get in Touch",
+ title: "Contact FlagForge | CTF Support and Cybersecurity Collaboration",
description:
- "Contact the FlagForge team for inquiries, support, or collaboration opportunities.",
- url: "https://flagforgectf.com/contact",
+ "Contact the FlagForge team for platform support, partnerships, or cybersecurity collaboration.",
+ url: `${siteConfig.url}/contact`,
type: "website",
- siteName: "FlagForge",
+ siteName: siteConfig.name,
locale: "en_US",
+ images: [{ url: siteConfig.ogImage, alt: "Contact FlagForge" }],
},
twitter: {
- card: "summary",
- title: "Contact FlagForge - Get in Touch",
+ card: "summary_large_image",
+ title: "Contact FlagForge | CTF Support and Cybersecurity Collaboration",
description: "Reach out to the FlagForge team for support, inquiries, or collaboration.",
+ images: [siteConfig.ogImage],
},
alternates: {
canonical: "/contact",
@@ -47,31 +49,24 @@ export const metadata: Metadata = {
export default function Contact() {
return (
-
- {/* Background Effects */}
-
- {/* Compact Glass Dashboard */}
-
-
- {/* Left Column: Header & Info */}
-
- Contact Us
+ Contact FlagForge
- Get in touch with us. We'd love to hear from you!
+ Reach the team for platform support, partnership conversations, and CTF or cybersecurity learning inquiries.
-
FlagForge Contact Details
+
FlagForge contact details
Email, phone, and office location
@@ -79,7 +74,7 @@ export default function Contact() {
Get in Touch
{[
- { icon: Mail, label: "Email", value: "info@flagforgectf.com", href: "mailto:info@flagforgectf.com" },
+ { icon: Mail, label: "Email", value: "info@flagforge.xyz", href: "mailto:info@flagforge.xyz" },
{ icon: Phone, label: "Phone", value: "+977 9828137085", href: "tel:+9779828137085" },
{ icon: MapPin, label: "Address", value: "Lalitpur, 44600" }
].map((item, idx) => (
@@ -108,10 +103,9 @@ export default function Contact() {
- {/* Right Column: Contact Form */}
- Send us a Message
+ Send Us a Message
-
diff --git a/app/(main)/blogs/[id]/page.tsx b/app/(main)/blogs/[id]/page.tsx
index a100804..a85c03f 100644
--- a/app/(main)/blogs/[id]/page.tsx
+++ b/app/(main)/blogs/[id]/page.tsx
@@ -6,6 +6,7 @@ import type {
PartialBlockObjectResponse,
} from "@notionhq/client/build/src/api-endpoints";
import JsonLd from "@/components/JsonLd";
+import { siteConfig } from "@/lib/seo";
import BlogPostClient from "./BlogPostClient";
export const revalidate = 300;
@@ -228,13 +229,13 @@ export async function generateMetadata({
description,
keywords,
alternates: {
- canonical: `/blogs/${canonicalSlug}`,
+ canonical: `${siteConfig.blogUrl}/${canonicalSlug}`,
},
openGraph: {
title: post.title,
description,
type: "article",
- url: `/blogs/${canonicalSlug}`,
+ url: `${siteConfig.blogUrl}/${canonicalSlug}`,
images: imageUrl ? [{ url: imageUrl, alt: post.title }] : [],
},
twitter: {
@@ -254,8 +255,7 @@ export default async function BlogPostPage({
const { id } = await params;
const post = await fetchBlogPost(id);
const postSlug = post?.slug || id;
- const seoImage =
- post?.cover || post?.thumbnail || post?.image || "https://flagforgectf.com/flagforge-logo.png";
+ const seoImage = post?.cover || post?.thumbnail || post?.image || siteConfig.ogImage;
const wordCount = post?.content
? post.content.split(/\s+/).filter(Boolean).length
: undefined;
@@ -286,18 +286,18 @@ export default async function BlogPostPage({
name: "FlagForge",
logo: {
"@type": "ImageObject",
- url: "https://flagforgectf.com/flagforge-logo.png",
+ url: siteConfig.ogImage,
},
},
mainEntityOfPage: {
"@type": "WebPage",
- "@id": `https://flagforgectf.com/blogs/${postSlug}`,
+ "@id": `${siteConfig.blogUrl}/${postSlug}`,
},
keywords: post.tags?.join(", ") || "",
isPartOf: {
"@type": "Blog",
name: "FlagForge Blog",
- url: "https://flagforgectf.com/blogs",
+ url: siteConfig.blogUrl,
},
}}
/>
@@ -310,19 +310,19 @@ export default async function BlogPostPage({
"@type": "ListItem",
position: 1,
name: "Home",
- item: "https://flagforgectf.com/",
+ item: `${siteConfig.url}/`,
},
{
"@type": "ListItem",
position: 2,
name: "Blogs",
- item: "https://flagforgectf.com/blogs",
+ item: siteConfig.blogUrl,
},
{
"@type": "ListItem",
position: 3,
name: post.title,
- item: `https://flagforgectf.com/blogs/${postSlug}`,
+ item: `${siteConfig.blogUrl}/${postSlug}`,
},
],
}}
diff --git a/app/(main)/blogs/layout.tsx b/app/(main)/blogs/layout.tsx
index 88ee465..0a33b42 100644
--- a/app/(main)/blogs/layout.tsx
+++ b/app/(main)/blogs/layout.tsx
@@ -1,26 +1,29 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
+import { siteConfig } from "@/lib/seo";
export const metadata: Metadata = {
- title: "FlagForge Blog",
+ title: "FlagForge Blog | CTF Guides and Cybersecurity Tutorials",
description:
- "Read FlagForge blog posts on CTF challenges, cybersecurity tutorials, and competition guides.",
+ "Read FlagForge blog posts covering capture the flag walkthroughs, cybersecurity tutorials, learning paths, and community updates.",
alternates: {
- canonical: "/blogs",
+ canonical: siteConfig.blogUrl,
},
openGraph: {
- title: "FlagForge Blog",
+ title: "FlagForge Blog | CTF Guides and Cybersecurity Tutorials",
description:
- "Read FlagForge blog posts on CTF challenges, cybersecurity tutorials, and competition guides.",
- url: "https://flagforgectf.com/blogs",
+ "Read FlagForge blog posts covering capture the flag walkthroughs, cybersecurity tutorials, learning paths, and community updates.",
+ url: siteConfig.blogUrl,
type: "website",
- siteName: "FlagForge",
+ siteName: siteConfig.name,
+ images: [{ url: siteConfig.ogImage, alt: "FlagForge Blog" }],
},
twitter: {
card: "summary_large_image",
- title: "FlagForge Blog",
+ title: "FlagForge Blog | CTF Guides and Cybersecurity Tutorials",
description:
- "Read FlagForge blog posts on CTF challenges, cybersecurity tutorials, and competition guides.",
+ "Read FlagForge blog posts covering capture the flag walkthroughs, cybersecurity tutorials, learning paths, and community updates.",
+ images: [siteConfig.ogImage],
},
};
diff --git a/app/(main)/blogs/page.tsx b/app/(main)/blogs/page.tsx
index d9c088a..8110dcd 100644
--- a/app/(main)/blogs/page.tsx
+++ b/app/(main)/blogs/page.tsx
@@ -38,7 +38,7 @@ export default function BlogsPage() {
"@type": "ListItem",
"position": 2,
"name": "Blogs",
- "item": "https://flagforgectf.com/blogs"
+ "item": "https://blogs.flagforgectf.com"
}
]
};
@@ -135,11 +135,11 @@ export default function BlogsPage() {
"@type": "Blog",
name: "FlagForge Blog",
description: "Discover insights, tutorials, and stories from our team at FlagForge.",
- url: "https://flagforgectf.com/blogs",
+ url: "https://blogs.flagforgectf.com",
blogPost: posts.map((post) => ({
"@type": "BlogPosting",
headline: post.title,
- url: `https://flagforgectf.com/blogs/${post.slug || post.id}`,
+ url: `https://blogs.flagforgectf.com/${post.slug || post.id}`,
datePublished: post.created,
description: post.excerpt,
})),
diff --git a/app/(main)/resources/layout.tsx b/app/(main)/resources/layout.tsx
index db1266a..e5b8f04 100644
--- a/app/(main)/resources/layout.tsx
+++ b/app/(main)/resources/layout.tsx
@@ -1,26 +1,29 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
+import { siteConfig } from "@/lib/seo";
export const metadata: Metadata = {
- title: "Learning Resources",
+ title: "FlagForge Resources | CTF Learning Materials and Security Study Guides",
description:
- "Explore FlagForge learning resources and CTF training materials organized by category to build cybersecurity skills.",
+ "Explore FlagForge resources for capture the flag preparation, cybersecurity study paths, curated tools, and practical learning materials.",
alternates: {
canonical: "/resources",
},
openGraph: {
- title: "Learning Resources - FlagForge",
+ title: "FlagForge Resources | CTF Learning Materials and Security Study Guides",
description:
- "Explore FlagForge learning resources and CTF training materials organized by category to build cybersecurity skills.",
- url: "https://flagforgectf.com/resources",
+ "Explore FlagForge resources for capture the flag preparation, cybersecurity study paths, curated tools, and practical learning materials.",
+ url: `${siteConfig.url}/resources`,
type: "website",
- siteName: "FlagForge",
+ siteName: siteConfig.name,
+ images: [{ url: siteConfig.ogImage, alt: "FlagForge Resources" }],
},
twitter: {
card: "summary_large_image",
- title: "Learning Resources - FlagForge",
+ title: "FlagForge Resources | CTF Learning Materials and Security Study Guides",
description:
- "Explore FlagForge learning resources and CTF training materials organized by category to build cybersecurity skills.",
+ "Explore FlagForge resources for capture the flag preparation, cybersecurity study paths, curated tools, and practical learning materials.",
+ images: [siteConfig.ogImage],
},
};
diff --git a/app/globals.css b/app/globals.css
index f9010ef..ddad2f5 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -65,6 +65,7 @@
body {
@apply bg-background text-foreground;
+ font-family: "Segoe UI", "Aptos", "Helvetica Neue", Arial, sans-serif;
}
/* Custom dark mode styles */
diff --git a/app/layout.tsx b/app/layout.tsx
index 18f52c1..8ae81d0 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,5 +1,4 @@
import type { Metadata, Viewport } from "next";
-import { DM_Sans } from "next/font/google";
import Script from "next/script";
import "./globals.css";
import Navbar from "@/components/Navbar";
@@ -8,40 +7,20 @@ import CookieConsent from "@/components/CookieConsent";
import Authprovider from "@/providers/auth-provider";
import { ThemeProvider } from "@/context/ThemeContext";
import { Analytics } from "@vercel/analytics/react";
-
-const dmSans = DM_Sans({
- subsets: ["latin"],
- display: "swap",
- preload: true,
-});
+import { defaultKeywords, siteConfig } from "@/lib/seo";
export const metadata: Metadata = {
+ metadataBase: new URL(siteConfig.url),
title: {
- default: "FlagForge - The Ultimate CTF Platform",
+ default: "FlagForge | Capture the Flag Platform for Cybersecurity Training",
template: "%s | FlagForge",
},
- description:
- "Join FlagForge, the premier CTF platform to hone your cybersecurity skills with engaging challenges. Compete, learn, and grow your hacking expertise.",
- metadataBase: new URL("https://flagforgectf.com"),
- applicationName: "FlagForge CTF",
+ description: siteConfig.description,
+ applicationName: siteConfig.name,
referrer: "origin-when-cross-origin",
- keywords: [
- "CTF",
- "Capture The Flag",
- "Cybersecurity",
- "Ethical Hacking",
- "FlagForge",
- "CTF Challenges",
- "Cybersecurity Platform",
- "Online CTF Competitions",
- "Nepal cybersecurity",
- "Nepal CTF platform",
- ],
- authors: [{ name: "@Aryanstha", url: "https://github.com/aryan4859" }],
- publisher: "FlagForge",
- alternates: {
- canonical: "/",
- },
+ keywords: defaultKeywords,
+ authors: [{ name: "FlagForge Team", url: "https://github.com/FlagForgeCTF/" }],
+ publisher: siteConfig.name,
robots: {
index: true,
follow: true,
@@ -57,17 +36,16 @@ export const metadata: Metadata = {
"google-adsense-account": "ca-pub-2506540900080142",
},
openGraph: {
- title: "FlagForge - The Ultimate CTF Platform",
- description:
- "FlagForge is the go-to platform for Capture The Flag (CTF) competitions. Test your hacking skills with thrilling challenges in cybersecurity.",
- url: "https://flagforgectf.com",
- siteName: "FlagForge",
+ title: "FlagForge | Capture the Flag Platform for Cybersecurity Training",
+ description: siteConfig.description,
+ url: siteConfig.url,
+ siteName: siteConfig.name,
images: [
{
- url: "/flagforge.gif",
+ url: siteConfig.ogImage,
width: 1200,
height: 630,
- alt: "FlagForge - Capture The Flag Platform",
+ alt: "FlagForge CTF Platform",
},
],
locale: "en_US",
@@ -75,11 +53,9 @@ export const metadata: Metadata = {
},
twitter: {
card: "summary_large_image",
- site: "@Aryanstha",
- title: "FlagForge - The Ultimate CTF Platform",
- description:
- "Join FlagForge, the leading Capture The Flag platform to enhance your cybersecurity skills. Compete and learn with exciting CTF challenges.",
- images: ["/flagforge.gif"],
+ title: "FlagForge | Capture the Flag Platform for Cybersecurity Training",
+ description: siteConfig.description,
+ images: [siteConfig.ogImage],
},
icons: {
icon: "/favicon.ico",
@@ -95,37 +71,6 @@ export const viewport: Viewport = {
userScalable: true,
};
-const structuredData = {
- "@context": "https://schema.org",
- "@graph": [
- {
- "@type": "WebSite",
- "@id": "https://flagforgectf.com/#website",
- url: "https://flagforgectf.com",
- name: "FlagForge",
- alternateName: "FlagForge CTF Platform",
- potentialAction: {
- "@type": "SearchAction",
- target: "https://flagforgectf.com/search?q={search_term_string}",
- "query-input": "required name=search_term_string",
- },
- publisher: {
- "@id": "https://flagforgectf.com/#organization",
- },
- },
- {
- "@type": "Organization",
- "@id": "https://flagforgectf.com/#organization",
- name: "FlagForge",
- url: "https://flagforgectf.com",
- logo: {
- "@type": "ImageObject",
- url: "https://flagforgectf.com/flagforge-logo.png",
- },
- },
- ],
-};
-
export default function RootLayout({
children,
}: {
@@ -133,22 +78,13 @@ export default function RootLayout({
}) {
return (
-
-
-
-
+
{children}
- {typeof window !== "undefined" &&
}
+
diff --git a/app/page.tsx b/app/page.tsx
index 7d8127e..84a3c00 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,83 +1,156 @@
-"use client";
-
-import { useSession } from "next-auth/react";
-import { useRouter } from "next/navigation";
-import { useEffect } from "react";
+import type { Metadata } from "next";
+import Link from "next/link";
import Hero from "@/components/Hero";
+import HomeIntroSection from "@/components/HomeIntroSection";
import JsonLd from "@/components/JsonLd";
+import HomepageRedirect from "@/components/HomepageRedirect";
import { landingFaqItems } from "@/lib/faq";
+import { defaultKeywords, siteConfig } from "@/lib/seo";
-export default function Home() {
- const { status } = useSession();
- const router = useRouter();
-
- useEffect(() => {
- if (status === "authenticated") {
- router.replace("/home");
- }
- }, [status, router]);
+export const metadata: Metadata = {
+ title: "FlagForge | Capture the Flag Platform for Cybersecurity Training",
+ description:
+ "FlagForge is a Nepal-rooted capture the flag platform where learners practice cybersecurity challenges, study writeups, and build hands-on offensive and defensive security skills.",
+ keywords: defaultKeywords,
+ alternates: {
+ canonical: "/",
+ },
+ robots: {
+ index: true,
+ follow: true,
+ googleBot: {
+ index: true,
+ follow: true,
+ "max-image-preview": "large",
+ "max-snippet": -1,
+ "max-video-preview": -1,
+ },
+ },
+ openGraph: {
+ title: "FlagForge | Capture the Flag Platform for Cybersecurity Training",
+ description:
+ "Practice web exploitation, cryptography, reverse engineering, forensics, and other CTF categories on FlagForge.",
+ url: siteConfig.url,
+ siteName: siteConfig.name,
+ images: [
+ {
+ url: siteConfig.ogImage,
+ width: 1200,
+ height: 630,
+ alt: "FlagForge CTF Platform",
+ },
+ ],
+ locale: "en_US",
+ type: "website",
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: "FlagForge | Capture the Flag Platform for Cybersecurity Training",
+ description:
+ "Train with practical CTF challenges, security writeups, and community-driven cybersecurity learning on FlagForge.",
+ images: [siteConfig.ogImage],
+ },
+};
+export default function Home() {
const organizationData = {
"@context": "https://schema.org",
"@type": "Organization",
- "name": "FlagForge",
- "url": "https://flagforgectf.com",
- "logo": "https://flagforgectf.com/flagforge.gif",
- "sameAs": [
- "https://github.com/aryan4859"
- ]
+ name: siteConfig.name,
+ alternateName: siteConfig.secondaryName,
+ url: siteConfig.url,
+ logo: siteConfig.ogImage,
+ description: siteConfig.organizationDescription,
+ sameAs: [
+ "https://github.com/FlagForgeCTF/",
+ "https://www.instagram.com/flag.forge/",
+ "https://www.linkedin.com/company/flagforge/",
+ ],
};
const websiteData = {
"@context": "https://schema.org",
"@type": "WebSite",
- "name": "FlagForge",
- "url": "https://flagforgectf.com",
- "potentialAction": {
- "@type": "SearchAction",
- "target": "https://flagforgectf.com/search?q={search_term_string}",
- "query-input": "required name=search_term_string"
- }
+ name: siteConfig.name,
+ alternateName: siteConfig.secondaryName,
+ url: siteConfig.url,
+ description: siteConfig.description,
+ publisher: {
+ "@type": "Organization",
+ name: siteConfig.name,
+ url: siteConfig.url,
+ },
};
const faqData = {
"@context": "https://schema.org",
"@type": "FAQPage",
- "mainEntity": landingFaqItems.map((item) => ({
+ mainEntity: landingFaqItems.map((item) => ({
"@type": "Question",
- "name": item.question,
- "acceptedAnswer": {
+ name: item.question,
+ acceptedAnswer: {
"@type": "Answer",
- "text": item.answer
- }
- }))
- };
-
- const breadcrumbData = {
- "@context": "https://schema.org",
- "@type": "BreadcrumbList",
- "itemListElement": [
- {
- "@type": "ListItem",
- "position": 1,
- "name": "Home",
- "item": "https://flagforgectf.com/"
- }
- ]
+ text: item.answer,
+ },
+ })),
};
- if (status !== "authenticated") {
- return (
- <>
-
-
-
-
-
-
-
- >
- );
- }
- return null;
+ return (
+ <>
+
+
+
+
+
+
+
+
+ FlagForge CTF Platform
+
+
+ Train with real capture the flag challenges and practical cybersecurity learning.
+
+
+ FlagForge is a Nepal-rooted cybersecurity community and training platform built for learners who want
+ hands-on experience in web exploitation, cryptography, reverse engineering, forensics, and secure
+ problem solving. Start with guided resources, study writeups, and grow through practical CTF practice.
+
+
+
+ Read FlagForge blog guides
+
+
+ Explore CTF learning resources
+
+
+ About the FlagForge community
+
+
+
+
+
+ Core Challenge Tracks
+
+
+ Web exploitation and secure web app testing
+ Cryptography, encoding, and flag recovery
+ Reverse engineering and binary analysis
+ Digital forensics, OSINT, and incident-style puzzles
+ Community learning for students and aspiring security teams
+
+
+
+
+
+ >
+ );
}
diff --git a/app/robots.ts b/app/robots.ts
new file mode 100644
index 0000000..aa3e7d9
--- /dev/null
+++ b/app/robots.ts
@@ -0,0 +1,26 @@
+import type { MetadataRoute } from "next";
+import { siteConfig } from "@/lib/seo";
+
+export default function robots(): MetadataRoute.Robots {
+ return {
+ rules: [
+ {
+ userAgent: "*",
+ allow: ["/", "/about", "/resources", "/contact"],
+ disallow: [
+ "/api/",
+ "/authentication",
+ "/home",
+ "/leaderboard",
+ "/problems",
+ "/profile",
+ "/resources/upload",
+ "/roles/developers/",
+ "/testprofile",
+ "/unauthorized",
+ ],
+ },
+ ],
+ sitemap: `${siteConfig.url}/sitemap.xml`,
+ };
+}
diff --git a/app/sitemap.ts b/app/sitemap.ts
new file mode 100644
index 0000000..d36c292
--- /dev/null
+++ b/app/sitemap.ts
@@ -0,0 +1,77 @@
+import fs from "node:fs";
+import path from "node:path";
+import type { MetadataRoute } from "next";
+import { siteConfig } from "@/lib/seo";
+
+type SitemapEntry = MetadataRoute.Sitemap[number];
+
+type RouteDefinition = {
+ url: string;
+ filePath: string;
+ changeFrequency: NonNullable;
+ priority: number;
+};
+
+const staticRoutes: RouteDefinition[] = [
+ { url: "/", filePath: "app/page.tsx", changeFrequency: "weekly", priority: 1 },
+ {
+ url: "/about",
+ filePath: "app/(footer)/about/page.tsx",
+ changeFrequency: "monthly",
+ priority: 0.85,
+ },
+ {
+ url: "/resources",
+ filePath: "app/(main)/resources/page.tsx",
+ changeFrequency: "weekly",
+ priority: 0.85,
+ },
+ {
+ url: "/contact",
+ filePath: "app/(footer)/contact/page.tsx",
+ changeFrequency: "monthly",
+ priority: 0.7,
+ },
+ {
+ url: "/privacy-policy",
+ filePath: "app/(footer)/privacy-policy/page.tsx",
+ changeFrequency: "yearly",
+ priority: 0.4,
+ },
+ {
+ url: "/terms-of-service",
+ filePath: "app/(footer)/terms-of-service/page.tsx",
+ changeFrequency: "yearly",
+ priority: 0.4,
+ },
+ {
+ url: "/licensing",
+ filePath: "app/(footer)/licensing/page.tsx",
+ changeFrequency: "yearly",
+ priority: 0.3,
+ },
+ {
+ url: "/cookie-consent",
+ filePath: "app/(footer)/cookie-consent/page.tsx",
+ changeFrequency: "yearly",
+ priority: 0.2,
+ },
+];
+
+const getLastModified = (relativePath: string) => {
+ const absolutePath = path.join(process.cwd(), relativePath);
+ try {
+ return fs.statSync(absolutePath).mtime;
+ } catch {
+ return new Date();
+ }
+};
+
+export default async function sitemap(): Promise {
+ return staticRoutes.map((route) => ({
+ url: `${siteConfig.url}${route.url}`,
+ lastModified: getLastModified(route.filePath),
+ changeFrequency: route.changeFrequency,
+ priority: route.priority,
+ }));
+}
diff --git a/app/user/[username]/layout.tsx b/app/user/[username]/layout.tsx
index 79e19ab..845c01f 100644
--- a/app/user/[username]/layout.tsx
+++ b/app/user/[username]/layout.tsx
@@ -6,25 +6,33 @@ export const generateMetadata = ({
}: {
params: { username: string };
}): Metadata => ({
- title: "FlagForge User Profile",
+ title: `${params.username} | FlagForge profile`,
description:
- "View FlagForge user profiles with CTF rank, badges, and cybersecurity achievements.",
+ "Public FlagForge profile pages are available for sharing, but are excluded from search indexing to keep discovery focused on FlagForge learning content.",
alternates: {
canonical: `/user/${params.username}`,
},
+ robots: {
+ index: false,
+ follow: true,
+ googleBot: {
+ index: false,
+ follow: true,
+ },
+ },
openGraph: {
- title: "FlagForge User Profile",
+ title: `${params.username} | FlagForge profile`,
description:
- "View FlagForge user profiles with CTF rank, badges, and cybersecurity achievements.",
+ "View a public FlagForge profile with badges, challenge activity, and CTF achievements.",
url: `https://flagforgectf.com/user/${params.username}`,
type: "profile",
siteName: "FlagForge",
},
twitter: {
card: "summary",
- title: "FlagForge User Profile",
+ title: `${params.username} | FlagForge profile`,
description:
- "View FlagForge user profiles with CTF rank, badges, and cybersecurity achievements.",
+ "Public FlagForge profile with badges, challenge activity, and CTF achievements.",
},
});
diff --git a/components/Footer.tsx b/components/Footer.tsx
index 597984c..fddffe1 100644
--- a/components/Footer.tsx
+++ b/components/Footer.tsx
@@ -1,7 +1,7 @@
import React from "react";
import Link from "next/link";
import Image from "next/image";
-import { Linkedin, Github } from "lucide-react";
+import { Linkedin, Instagram, Github } from "lucide-react";
import logo from "@/public/flagforge-logo.png";
export default function Footer() {
@@ -10,9 +10,16 @@ export default function Footer() {
name: "LinkedIn",
url: "https://www.linkedin.com/company/flagforge/",
icon: ,
- color: "hover:text-[#0077b5] dark:hover:text-[#38b6ff]", // Lighter blue for dark mode visibility
+ color: "hover:text-[#0077b5] dark:hover:text-[#38b6ff]",
bg: "hover:bg-[#0077b5]/10 dark:hover:bg-[#38b6ff]/15",
},
+ {
+ name: "Instagram",
+ url: "https://www.instagram.com/flag.forge/",
+ icon: ,
+ color: "hover:text-[#e4405f] dark:hover:text-[#ff4d6d]",
+ bg: "hover:bg-[#e4405f]/10 dark:hover:bg-[#ff4d6d]/15",
+ },
{
name: "GitHub",
url: "https://github.com/FlagForgeCTF/",
@@ -20,52 +27,27 @@ export default function Footer() {
color: "hover:text-gray-950 dark:hover:text-white",
bg: "hover:bg-gray-950/10 dark:hover:bg-white/10",
},
- {
- name: "Instagram",
- url: "https://www.instagram.com/flag.forge/",
- icon: (
-
-
-
-
-
- ),
- color: "hover:text-[#E4405F]",
- bg: "hover:bg-[#E4405F]/10",
- },
];
const footerLinks = [
- { name: "About", href: "/about" },
- { name: "Resources", href: "/resources" },
- { name: "Contact", href: "/contact" },
- { name: "Privacy Policy", href: "/privacy-policy" },
- { name: "Licensing", href: "/licensing" },
+ { name: "About FlagForge", href: "/about", label: "Learn about FlagForge and our cybersecurity mission" },
+ { name: "CTF Resources", href: "/resources", label: "Browse FlagForge cybersecurity resources and study materials" },
+ { name: "Contact FlagForge", href: "/contact", label: "Contact the FlagForge team" },
+ { name: "Privacy Policy", href: "/privacy-policy", label: "Read the FlagForge privacy policy" },
+ { name: "Licensing", href: "/licensing", label: "Read FlagForge licensing information" },
];
return (
);
diff --git a/components/Hero.tsx b/components/Hero.tsx
index c9687fa..a6a5df8 100644
--- a/components/Hero.tsx
+++ b/components/Hero.tsx
@@ -1,522 +1,529 @@
-"use client";
-import { useSession } from "next-auth/react";
-import Link from "next/link";
-import Image from "next/image";
-import React, { useState, useEffect } from "react";
-import { landingFaqItems } from "@/lib/faq";
-
-// Import images statically
-import nirmalImage from "@/public/NirmalDahal.jpeg";
-import sobitImage from "@/public/SobitThakuri.jpeg";
-import bibekImage from "@/public/bibekghimire.jpeg";
-
-import { Activity, Rocket, Target, Users, Layers, Clock } from "lucide-react";
-
-const Hero: React.FC = () => {
- const { status } = useSession();
- const [currentTestimonial, setCurrentTestimonial] = useState(0);
- const [isAutoPlaying, setIsAutoPlaying] = useState(true);
- const [isAnimating, setIsAnimating] = useState(false);
- const [openFaqIndex, setOpenFaqIndex] = useState(null);
-
- // Icons for the stats section, mapped by index to preserve original data structure
- const statIcons = [Target, Users, Layers, Clock];
-
- const testimonials = [
- {
- id: 1,
- name: "Nirmal Dahal",
- position: "Cofounder of Cryptogen Nepal",
- image: nirmalImage,
- testimonial:
- "FlagForge provides an exceptional platform for cybersecurity professionals to validate their skills. The challenges mirror real-world attack vectors and help teams stay sharp in an ever-evolving threat landscape.",
- },
- {
- id: 2,
- name: "Sobit Thakuri",
- position: "Information Security Officer and ISO 27001:2022 Lead Auditor",
- image: sobitImage,
- testimonial:
- "I appreciate FlagForge's comprehensive approach to security training. The platform effectively bridges the gap between theoretical knowledge and practical application in cybersecurity.",
- },
- {
- id: 3,
- name: "Bibek Ghimire",
- position: "CTO of Bardali Creation",
- image: bibekImage,
- testimonial:
- "FlagForge is an engaging and fun CTF platform that helped me sharpen my cybersecurity and problem-solving skills in web exploitation and cryptography. A great place to learn, compete, and grow as a hacker!",
- },
- ];
-
- const categories = [
- {
- icon: "π",
- title: "Web Exploitation",
- description: "Master web vulnerabilities like SQL injection, XSS, CSRF, and more. Learn to identify and exploit common web application security flaws.",
- },
- {
- icon: "π",
- title: "Cryptography",
- description: "Decode encrypted messages, break ciphers, and understand cryptographic algorithms. From classical to modern encryption techniques.",
- },
- {
- icon: "π",
- title: "Reverse Engineering",
- description: "Analyze binaries, understand assembly code, and reverse engineer software to uncover hidden flags and vulnerabilities.",
- },
- {
- icon: "π΅οΈ",
- title: "Forensics",
- description: "Investigate digital artifacts, analyze memory dumps, recover hidden data, and solve mysteries through digital forensics.",
- },
- {
- icon: "π―",
- title: "Binary Exploitation",
- description: "Exploit buffer overflows, format string vulnerabilities, and other binary-level security issues in compiled programs.",
- },
- {
- icon: "π§©",
- title: "Miscellaneous",
- description: "Tackle unique challenges that don't fit traditional categories. Logic puzzles, OSINT, steganography, and creative problem-solving.",
- },
- ];
-
- const features = [
- {
- icon: "π",
- title: "Learn by Doing",
- description: "Hands-on challenges that teach real-world cybersecurity skills through practical application.",
- },
- {
- icon: "π",
- title: "Track Your Progress",
- description: "Monitor your improvement with detailed statistics, solve rates, and performance analytics.",
- },
- {
- icon: "π",
- title: "Compete & Rank",
- description: "Climb the leaderboard, earn points, and compete with cybersecurity enthusiasts worldwide.",
- },
- {
- icon: "π‘",
- title: "Smart Hint System",
- description: "Get unstuck with our intelligent hint system. Choose between watching ads or using points for hints.",
- },
- {
- icon: "π",
- title: "Dark Mode Support",
- description: "Comfortable coding experience with full dark mode support for extended practice sessions.",
- },
- {
- icon: "π±",
- title: "Fully Responsive",
- description: "Practice anywhere, anytime. Our platform works seamlessly on desktop, tablet, and mobile devices.",
- },
- ];
-
- const howItWorks = [
- {
- step: "1",
- title: "Create Your Account",
- description: "Sign up for free and join our community of cybersecurity enthusiasts.",
- },
- {
- step: "2",
- title: "Choose Your Challenge",
- description: "Browse challenges across multiple categories and difficulty levels.",
- },
- {
- step: "3",
- title: "Solve & Submit",
- description: "Work through the challenge, find the flag, and submit your solution.",
- },
- {
- step: "4",
- title: "Earn Points & Rank Up",
- description: "Gain points for correct solutions and climb the global leaderboard.",
- },
- ];
-
- const stats = [
- { number: "100+", label: "Challenges" },
- { number: "1000+", label: "Active Users" },
- { number: "6", label: "Categories" },
- { number: "24/7", label: "Availability" },
- ];
-
- const changeTestimonial = (newIndex: number) => {
- if (newIndex === currentTestimonial || isAnimating) return;
-
- setIsAnimating(true);
-
- setTimeout(() => {
- setCurrentTestimonial(newIndex);
- setTimeout(() => {
- setIsAnimating(false);
- }, 50);
- }, 200);
- };
-
- const nextTestimonial = () => {
- const newIndex = (currentTestimonial + 1) % testimonials.length;
- changeTestimonial(newIndex);
- };
-
- const prevTestimonial = () => {
- const newIndex =
- (currentTestimonial - 1 + testimonials.length) % testimonials.length;
- changeTestimonial(newIndex);
- };
-
- useEffect(() => {
- if (!isAutoPlaying || isAnimating) return;
-
- const interval = setInterval(() => {
- nextTestimonial();
- }, 3000);
-
- return () => clearInterval(interval);
- }, [isAutoPlaying, currentTestimonial, isAnimating]);
-
- const handleManualNavigation = (action: () => void) => {
- setIsAutoPlaying(false);
- action();
- setTimeout(() => setIsAutoPlaying(true), 6000);
- };
-
- const toggleFaq = (index: number) => {
- setOpenFaqIndex(openFaqIndex === index ? null : index);
- };
-
- return (
-
-
- {/* Background Effects (Static) */}
-
-
-
- {/* Volumetric Spotlight */}
-
-
-
-
-
-
- {/* Hero Section: Asymmetric Split */}
-
- {/* Left: Content */}
-
-
-
- {/* Typography with fixed clipping */}
-
- WELCOME TO
- FLAGFORGE
- CTF PLAYGROUND
-
-
-
- FlagForge is a dynamic platform for
- Cybersecurity
- excellence. Sharpen your skills in cryptography, web exploitation, reverse engineering, and more.
-
-
-
-
- Start Solving
-
-
-
-
-
- {/* Right: Clean Connected Stats Grid (Reference Style) */}
-
-
-
- {/* Central Connector Lines */}
-
-
- {stats.map((stat, index) => {
- const Icon = statIcons[index];
- // Determine corner badge position based on index
- // 0: top-left (badge bottom-right), 1: top-right (badge bottom-left)
- // 2: bottom-left (badge top-right), 3: bottom-right (badge top-left)
- const badgePosition =
- index === 0 ? "bottom-[-6px] right-[-6px]" :
- index === 1 ? "bottom-[-6px] left-[-6px]" :
- index === 2 ? "top-[-6px] right-[-6px]" :
- "top-[-6px] left-[-6px]";
-
- return (
-
- {/* Inner Corner Connection Dot */}
-
-
-
-
-
{stat.number}
-
{stat.label}
-
-
- );
- })}
-
-
-
-
- {/* Features Section: Bento Grid */}
-
-
-
-
- Why Choose FlagForge
-
-
- Everything you need to master cybersecurity through hands-on practice
-
-
-
-
-
- {features.map((feature, index) => (
-
-
-
-
- {feature.icon}
-
-
-
- {feature.title}
-
-
- {feature.description}
-
-
-
-
- ))}
-
-
-
- {/* Challenge Categories: Hover Cards */}
-
-
-
- Challenge Categories
-
-
-
-
- {categories.map((category, index) => (
-
-
-
{category.icon}
-
- {category.title}
-
-
-
-
-
- {category.title}
-
-
- {category.description}
-
-
-
- ))}
-
-
-
- {/* How It Works: Horizontal Circuit Flow */}
-
-
-
- How It Works
-
-
- Get started in just four simple steps
-
-
-
-
- {/* Connecting Line (Desktop) */}
-
-
-
- {howItWorks.map((item, index) => (
-
- {/* Step Node */}
-
- {item.step}
-
-
- {/* Content Card */}
-
-
- {item.title}
-
-
- {item.description}
-
-
-
- {/* Connecting Line (Mobile Vertical) */}
- {index !== howItWorks.length - 1 && (
-
- )}
-
- ))}
-
-
-
-
- {/* Testimonial Carousel */}
-
-
-
- Expert Vouches
-
-
-
-
-
setIsAutoPlaying(false)}
- onMouseLeave={() => setIsAutoPlaying(true)}
- >
-
-
-
-
-
-
- "{testimonials[currentTestimonial].testimonial}"
-
-
-
- {testimonials[currentTestimonial].name}
-
-
- {testimonials[currentTestimonial].position}
-
-
-
-
-
-
- {/* Controls */}
-
-
handleManualNavigation(prevTestimonial)}
- disabled={isAnimating}
- className="w-10 h-10 rounded-full bg-white dark:bg-white/5 border border-gray-100 dark:border-white/10 flex items-center justify-center hover:bg-red-500 hover:text-white transition-all shadow-xl disabled:opacity-50"
- >
-
-
-
handleManualNavigation(nextTestimonial)}
- disabled={isAnimating}
- className="w-10 h-10 rounded-full bg-white dark:bg-white/5 border border-gray-100 dark:border-white/10 flex items-center justify-center hover:bg-red-500 hover:text-white transition-all shadow-xl disabled:opacity-50"
- >
-
-
-
-
-
-
- {/* CTA: Minimalist */}
-
-
- Ready to Hack?
-
-
-
- Get Started Now
-
-
-
-
- {/* FAQ: Split Layout */}
-
- {/* Sticky Header */}
-
-
-
- FAQS
-
-
- Common questions about the platform, challenges, and community.
-
-
-
-
- {/* Accordion List */}
-
- {landingFaqItems.map((faq, index) => (
-
-
toggleFaq(index)}
- className="w-full px-8 py-6 flex items-center justify-between text-left hover:bg-gray-50 dark:hover:bg-white/5 transition-colors"
- >
-
- {faq.question}
-
-
-
-
-
- ))}
-
-
-
-
-
- );
-};
-
-export default Hero;
+"use client";
+import { useSession } from "next-auth/react";
+import Link from "next/link";
+import Image from "next/image";
+import React, { useState, useEffect } from "react";
+import { landingFaqItems } from "@/lib/faq";
+
+// Import images statically
+import nirmalImage from "@/public/NirmalDahal.jpeg";
+import sobitImage from "@/public/SobitThakuri.jpeg";
+import bibekImage from "@/public/bibekghimire.jpeg";
+
+import { Activity, Rocket, Target, Users, Layers, Clock } from "lucide-react";
+
+interface HeroProps {
+ afterFaqSection?: React.ReactNode;
+}
+
+const Hero: React.FC = ({ afterFaqSection }) => {
+ const { status } = useSession();
+ const [currentTestimonial, setCurrentTestimonial] = useState(0);
+ const [isAutoPlaying, setIsAutoPlaying] = useState(true);
+ const [isAnimating, setIsAnimating] = useState(false);
+ const [openFaqIndex, setOpenFaqIndex] = useState(null);
+
+ // Icons for the stats section, mapped by index to preserve original data structure
+ const statIcons = [Target, Users, Layers, Clock];
+
+ const testimonials = [
+ {
+ id: 1,
+ name: "Nirmal Dahal",
+ position: "Cofounder of Cryptogen Nepal",
+ image: nirmalImage,
+ testimonial:
+ "FlagForge provides an exceptional platform for cybersecurity professionals to validate their skills. The challenges mirror real-world attack vectors and help teams stay sharp in an ever-evolving threat landscape.",
+ },
+ {
+ id: 2,
+ name: "Sobit Thakuri",
+ position: "Information Security Officer and ISO 27001:2022 Lead Auditor",
+ image: sobitImage,
+ testimonial:
+ "I appreciate FlagForge's comprehensive approach to security training. The platform effectively bridges the gap between theoretical knowledge and practical application in cybersecurity.",
+ },
+ {
+ id: 3,
+ name: "Bibek Ghimire",
+ position: "CTO of Bardali Creation",
+ image: bibekImage,
+ testimonial:
+ "FlagForge is an engaging and fun CTF platform that helped me sharpen my cybersecurity and problem-solving skills in web exploitation and cryptography. A great place to learn, compete, and grow as a hacker!",
+ },
+ ];
+
+ const categories = [
+ {
+ icon: "π",
+ title: "Web Exploitation",
+ description: "Master web vulnerabilities like SQL injection, XSS, CSRF, and more. Learn to identify and exploit common web application security flaws.",
+ },
+ {
+ icon: "π",
+ title: "Cryptography",
+ description: "Decode encrypted messages, break ciphers, and understand cryptographic algorithms. From classical to modern encryption techniques.",
+ },
+ {
+ icon: "π",
+ title: "Reverse Engineering",
+ description: "Analyze binaries, understand assembly code, and reverse engineer software to uncover hidden flags and vulnerabilities.",
+ },
+ {
+ icon: "π΅οΈ",
+ title: "Forensics",
+ description: "Investigate digital artifacts, analyze memory dumps, recover hidden data, and solve mysteries through digital forensics.",
+ },
+ {
+ icon: "π―",
+ title: "Binary Exploitation",
+ description: "Exploit buffer overflows, format string vulnerabilities, and other binary-level security issues in compiled programs.",
+ },
+ {
+ icon: "π§©",
+ title: "Miscellaneous",
+ description: "Tackle unique challenges that don't fit traditional categories. Logic puzzles, OSINT, steganography, and creative problem-solving.",
+ },
+ ];
+
+ const features = [
+ {
+ icon: "π",
+ title: "Learn by Doing",
+ description: "Hands-on challenges that teach real-world cybersecurity skills through practical application.",
+ },
+ {
+ icon: "π",
+ title: "Track Your Progress",
+ description: "Monitor your improvement with detailed statistics, solve rates, and performance analytics.",
+ },
+ {
+ icon: "π",
+ title: "Compete & Rank",
+ description: "Climb the leaderboard, earn points, and compete with cybersecurity enthusiasts worldwide.",
+ },
+ {
+ icon: "π‘",
+ title: "Smart Hint System",
+ description: "Get unstuck with our intelligent hint system. Choose between watching ads or using points for hints.",
+ },
+ {
+ icon: "π",
+ title: "Dark Mode Support",
+ description: "Comfortable coding experience with full dark mode support for extended practice sessions.",
+ },
+ {
+ icon: "π±",
+ title: "Fully Responsive",
+ description: "Practice anywhere, anytime. Our platform works seamlessly on desktop, tablet, and mobile devices.",
+ },
+ ];
+
+ const howItWorks = [
+ {
+ step: "1",
+ title: "Create Your Account",
+ description: "Sign up for free and join our community of cybersecurity enthusiasts.",
+ },
+ {
+ step: "2",
+ title: "Choose Your Challenge",
+ description: "Browse challenges across multiple categories and difficulty levels.",
+ },
+ {
+ step: "3",
+ title: "Solve & Submit",
+ description: "Work through the challenge, find the flag, and submit your solution.",
+ },
+ {
+ step: "4",
+ title: "Earn Points & Rank Up",
+ description: "Gain points for correct solutions and climb the global leaderboard.",
+ },
+ ];
+
+ const stats = [
+ { number: "100+", label: "Challenges" },
+ { number: "1000+", label: "Active Users" },
+ { number: "6", label: "Categories" },
+ { number: "24/7", label: "Availability" },
+ ];
+
+ const changeTestimonial = (newIndex: number) => {
+ if (newIndex === currentTestimonial || isAnimating) return;
+
+ setIsAnimating(true);
+
+ setTimeout(() => {
+ setCurrentTestimonial(newIndex);
+ setTimeout(() => {
+ setIsAnimating(false);
+ }, 50);
+ }, 200);
+ };
+
+ const nextTestimonial = () => {
+ const newIndex = (currentTestimonial + 1) % testimonials.length;
+ changeTestimonial(newIndex);
+ };
+
+ const prevTestimonial = () => {
+ const newIndex =
+ (currentTestimonial - 1 + testimonials.length) % testimonials.length;
+ changeTestimonial(newIndex);
+ };
+
+ useEffect(() => {
+ if (!isAutoPlaying || isAnimating) return;
+
+ const interval = setInterval(() => {
+ nextTestimonial();
+ }, 3000);
+
+ return () => clearInterval(interval);
+ }, [isAutoPlaying, currentTestimonial, isAnimating]);
+
+ const handleManualNavigation = (action: () => void) => {
+ setIsAutoPlaying(false);
+ action();
+ setTimeout(() => setIsAutoPlaying(true), 6000);
+ };
+
+ const toggleFaq = (index: number) => {
+ setOpenFaqIndex(openFaqIndex === index ? null : index);
+ };
+
+ return (
+
+
+ {/* Background Effects (Static) */}
+
+
+
+ {/* Volumetric Spotlight */}
+
+
+
+
+
+
+ {/* Hero Section: Asymmetric Split */}
+
+ {/* Left: Content */}
+
+
+
+ {/* Typography with fixed clipping */}
+
+ WELCOME TO
+ FLAGFORGE
+ CTF PLAYGROUND
+
+
+
+ FlagForge is a dynamic platform for
+ Cybersecurity
+ excellence. Sharpen your skills in cryptography, web exploitation, reverse engineering, and more.
+
+
+
+
+ Start Solving
+
+
+
+
+
+ {/* Right: Clean Connected Stats Grid (Reference Style) */}
+
+
+
+ {/* Central Connector Lines */}
+
+
+ {stats.map((stat, index) => {
+ const Icon = statIcons[index];
+ // Determine corner badge position based on index
+ // 0: top-left (badge bottom-right), 1: top-right (badge bottom-left)
+ // 2: bottom-left (badge top-right), 3: bottom-right (badge top-left)
+ const badgePosition =
+ index === 0 ? "bottom-[-6px] right-[-6px]" :
+ index === 1 ? "bottom-[-6px] left-[-6px]" :
+ index === 2 ? "top-[-6px] right-[-6px]" :
+ "top-[-6px] left-[-6px]";
+
+ return (
+
+ {/* Inner Corner Connection Dot */}
+
+
+
+
+
{stat.number}
+
{stat.label}
+
+
+ );
+ })}
+
+
+
+
+ {/* Features Section: Bento Grid */}
+
+
+
+
+ Why Choose FlagForge
+
+
+ Everything you need to master cybersecurity through hands-on practice
+
+
+
+
+
+ {features.map((feature, index) => (
+
+
+
+
+ {feature.icon}
+
+
+
+ {feature.title}
+
+
+ {feature.description}
+
+
+
+
+ ))}
+
+
+
+ {/* Challenge Categories: Hover Cards */}
+
+
+
+ Challenge Categories
+
+
+
+
+ {categories.map((category, index) => (
+
+
+
{category.icon}
+
+ {category.title}
+
+
+
+
+
+ {category.title}
+
+
+ {category.description}
+
+
+
+ ))}
+
+
+
+ {/* How It Works: Horizontal Circuit Flow */}
+
+
+
+ How It Works
+
+
+ Get started in just four simple steps
+
+
+
+
+ {/* Connecting Line (Desktop) */}
+
+
+
+ {howItWorks.map((item, index) => (
+
+ {/* Step Node */}
+
+ {item.step}
+
+
+ {/* Content Card */}
+
+
+ {item.title}
+
+
+ {item.description}
+
+
+
+ {/* Connecting Line (Mobile Vertical) */}
+ {index !== howItWorks.length - 1 && (
+
+ )}
+
+ ))}
+
+
+
+
+ {/* Testimonial Carousel */}
+
+
+
+ Expert Vouches
+
+
+
+
+
setIsAutoPlaying(false)}
+ onMouseLeave={() => setIsAutoPlaying(true)}
+ >
+
+
+
+
+
+
+ "{testimonials[currentTestimonial].testimonial}"
+
+
+
+ {testimonials[currentTestimonial].name}
+
+
+ {testimonials[currentTestimonial].position}
+
+
+
+
+
+
+ {/* Controls */}
+
+
handleManualNavigation(prevTestimonial)}
+ disabled={isAnimating}
+ className="w-10 h-10 rounded-full bg-white dark:bg-white/5 border border-gray-100 dark:border-white/10 flex items-center justify-center hover:bg-red-500 hover:text-white transition-all shadow-xl disabled:opacity-50"
+ >
+
+
+
handleManualNavigation(nextTestimonial)}
+ disabled={isAnimating}
+ className="w-10 h-10 rounded-full bg-white dark:bg-white/5 border border-gray-100 dark:border-white/10 flex items-center justify-center hover:bg-red-500 hover:text-white transition-all shadow-xl disabled:opacity-50"
+ >
+
+
+
+
+
+
+ {/* CTA: Minimalist */}
+
+
+ Ready to Hack?
+
+
+
+ Get Started Now
+
+
+
+
+ {/* FAQ: Split Layout */}
+
+ {/* Sticky Header */}
+
+
+
+ FAQS
+
+
+ Common questions about the platform, challenges, and community.
+
+
+
+
+ {/* Accordion List */}
+
+ {landingFaqItems.map((faq, index) => (
+
+
toggleFaq(index)}
+ className="w-full px-8 py-6 flex items-center justify-between text-left hover:bg-gray-50 dark:hover:bg-white/5 transition-colors"
+ >
+
+ {faq.question}
+
+
+
+
+
+ ))}
+
+
+
+ {afterFaqSection}
+
+
+
+ );
+};
+
+export default Hero;
+
diff --git a/components/HomeIntroSection.tsx b/components/HomeIntroSection.tsx
new file mode 100644
index 0000000..4bb68eb
--- /dev/null
+++ b/components/HomeIntroSection.tsx
@@ -0,0 +1,56 @@
+import Link from "next/link";
+import { siteConfig } from "@/lib/seo";
+
+export default function HomeIntroSection() {
+ return (
+
+
+
+
+ FlagForge CTF Platform
+
+
+ Train with real capture the flag challenges and practical cybersecurity learning.
+
+
+ FlagForge is a Nepal-rooted cybersecurity community and training platform built for learners who want
+ hands-on experience in web exploitation, cryptography, reverse engineering, forensics, and secure
+ problem solving. Start with guided resources, study writeups, and grow through practical CTF practice.
+
+
+
+ Read FlagForge blog guides
+
+
+ Explore CTF learning resources
+
+
+ About the FlagForge community
+
+
+
+
+
+ Core Challenge Tracks
+
+
+ Web exploitation and secure web app testing
+ Cryptography, encoding, and flag recovery
+ Reverse engineering and binary analysis
+ Digital forensics, OSINT, and incident-style puzzles
+ Community learning for students and aspiring security teams
+
+
+
+
+ );
+}
diff --git a/components/HomepageRedirect.tsx b/components/HomepageRedirect.tsx
new file mode 100644
index 0000000..b3eb9f0
--- /dev/null
+++ b/components/HomepageRedirect.tsx
@@ -0,0 +1,18 @@
+"use client";
+
+import { useEffect } from "react";
+import { useSession } from "next-auth/react";
+import { useRouter } from "next/navigation";
+
+export default function HomepageRedirect() {
+ const { status } = useSession();
+ const router = useRouter();
+
+ useEffect(() => {
+ if (status === "authenticated") {
+ router.replace("/home");
+ }
+ }, [router, status]);
+
+ return null;
+}
diff --git a/components/Navbar.tsx b/components/Navbar.tsx
index 04a6f26..0da74d7 100644
--- a/components/Navbar.tsx
+++ b/components/Navbar.tsx
@@ -22,21 +22,20 @@ import {
} from "@/components/ui/dropdown-menu";
import { useTheme } from "@/context/ThemeContext";
import {
- Home,
- Terminal,
- Trophy,
+ Archive,
+ ArrowRight,
BookText,
+ Home,
+ LayoutDashboard,
LogIn,
LogOut,
- User as UserIcon,
ShieldCheck,
- LayoutDashboard,
- ArrowRight,
- Archive
+ Terminal,
+ Trophy,
} from "lucide-react";
const NavItem = ({ href, tags, onClick, style }: NavbarItems) => {
- const isExternal = href.startsWith('http');
+ const isExternal = href.startsWith("http");
return (
@@ -57,6 +56,7 @@ const NavItem = ({ href, tags, onClick, style }: NavbarItems) => {
const Navbar: React.FC = () => {
const [open, setOpen] = useState(false);
+ const [mounted, setMounted] = useState(false);
const session = useSession();
const [standing, setStanding] = useState("");
const [isAdmin, setIsAdmin] = useState(false);
@@ -65,6 +65,10 @@ const Navbar: React.FC = () => {
const pendingCloseRef = React.useRef(false);
const closeTimeoutRef = React.useRef | null>(null);
+ const isAuthenticated = mounted && session.status === "authenticated";
+ const isUnauthenticated = !mounted || session.status === "unauthenticated";
+ const visibleNavItems = NavbarData.filter((item) => isAuthenticated || item.tags !== "Home");
+
const handleMobileItemClick = () => {
pendingCloseRef.current = true;
};
@@ -85,6 +89,10 @@ const Navbar: React.FC = () => {
}
};
+ React.useEffect(() => {
+ setMounted(true);
+ }, []);
+
React.useEffect(() => {
if (!pendingCloseRef.current) return;
pendingCloseRef.current = false;
@@ -103,7 +111,7 @@ const Navbar: React.FC = () => {
}, []);
React.useEffect(() => {
- if (session.status !== "authenticated") {
+ if (!isAuthenticated) {
setStanding("");
setIsAdmin(false);
return;
@@ -112,7 +120,6 @@ const Navbar: React.FC = () => {
let active = true;
const loadUserData = async () => {
try {
- // Load user profile data
const profileResponse = await fetch("/api/profile");
if (profileResponse.ok) {
const data = await profileResponse.json();
@@ -124,13 +131,12 @@ const Navbar: React.FC = () => {
if (active) setStanding(nextStanding);
}
- // Load user role data
const roleResponse = await fetch("/api/user/role");
if (roleResponse.ok) {
const roleData = await roleResponse.json();
if (active) setIsAdmin(roleData.isAdmin || false);
}
- } catch (error) {
+ } catch {
if (active) {
setStanding("");
setIsAdmin(false);
@@ -142,7 +148,7 @@ const Navbar: React.FC = () => {
return () => {
active = false;
};
- }, [session.status]);
+ }, [isAuthenticated]);
return (
@@ -153,7 +159,7 @@ const Navbar: React.FC = () => {
{