diff --git a/frontend/src/components/competition/ProjectDetail.jsx b/frontend/src/components/competition/ProjectDetail.jsx
new file mode 100644
index 0000000..0674322
--- /dev/null
+++ b/frontend/src/components/competition/ProjectDetail.jsx
@@ -0,0 +1,188 @@
+import React, { useState } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import { useQuery } from '@tanstack/react-query';
+import { Typography, Card, Button, Row, Col, Tag, Descriptions, Empty, Spin, Avatar, List, Image, Grid } from 'antd';
+import { UserOutlined, ArrowLeftOutlined, LinkOutlined, FileTextOutlined, TrophyOutlined, MessageOutlined } from '@ant-design/icons';
+import ReactMarkdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
+import rehypeRaw from 'rehype-raw';
+import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
+import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
+import dayjs from 'dayjs';
+import { getProjectDetail, getComments } from '../../api';
+import 'github-markdown-css/github-markdown-dark.css';
+
+const { Title, Paragraph, Text } = Typography;
+const { useBreakpoint } = Grid;
+
+const getImageUrl = (url) => {
+ if (!url) return '';
+ if (url.startsWith('http') || url.startsWith('//')) return url;
+ const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000/api';
+ const baseUrl = apiUrl.replace(/\/api\/?$/, '');
+ return `${baseUrl}${url}`;
+};
+
+const CodeBlock = ({ inline, className, children, ...props }) => {
+ const match = /language-(\w+)/.exec(className || '');
+ return !inline && match ? (
+
+ {children}
+
+ );
+};
+
+const ProjectDetail = () => {
+ const { id } = useParams();
+ const navigate = useNavigate();
+ const screens = useBreakpoint();
+ const isMobile = !screens.md;
+
+ const { data: project, isLoading } = useQuery({
+ queryKey: ['project', id],
+ queryFn: () => getProjectDetail(id).then(res => res.data)
+ });
+
+ const { data: comments } = useQuery({
+ queryKey: ['comments', id],
+ queryFn: () => getComments({ project: id }).then(res => res.data?.results || res.data || []),
+ enabled: !!project
+ });
+
+ if (isLoading) return