diff --git a/frontend/app/friends/add/page.tsx b/frontend/app/friends/add/page.tsx
new file mode 100644
index 0000000..cef6fa0
--- /dev/null
+++ b/frontend/app/friends/add/page.tsx
@@ -0,0 +1,27 @@
+'use client'
+
+import { useRouter } from 'next/navigation'
+import { ChevronLeft } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+
+export default function AddFriendsPage() {
+ const router = useRouter()
+
+ return (
+
+
+
+
+
Add Friends
+
Find and add friends to your network.
+
+
+ )
+}
diff --git a/frontend/app/friends/page.tsx b/frontend/app/friends/page.tsx
new file mode 100644
index 0000000..7d7c38c
--- /dev/null
+++ b/frontend/app/friends/page.tsx
@@ -0,0 +1,159 @@
+'use client'
+
+import { useState } from 'react'
+import { useRouter } from 'next/navigation'
+import { Flame, Plus, X } from 'lucide-react'
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
+import { FriendListItem } from '@/components/friend-list-item'
+import { StreakCalendar } from '@/components/streak-calendar'
+import Button from '@/components/Button'
+
+
+// Mocked data for Following and Followers
+const mockFollowing = [
+ { id: '1', username: 'Aaron', avatar: '', avatarFallback: 'A' },
+ { id: '2', username: 'Jordan', avatar: '', avatarFallback: 'J' },
+ { id: '3', username: 'Casey', avatar: '', avatarFallback: 'C' },
+ { id: '4', username: 'Morgan', avatar: '', avatarFallback: 'M' },
+]
+
+const mockFollowers = [
+ { id: '1', username: 'Alex', avatar: '', avatarFallback: 'A' },
+ { id: '2', username: 'Taylor', avatar: '', avatarFallback: 'T' },
+ { id: '3', username: 'Riley', avatar: '', avatarFallback: 'R' },
+]
+
+export default function FriendsPage() {
+ const router = useRouter()
+ const [activeTab, setActiveTab] = useState('following')
+
+ const handleAddFriends = () => {
+ router.push('/friends/add')
+ }
+
+ const handleFriendClick = (username: string) => {
+ // Navigate to friend profile or handle friend interaction
+ console.log('Clicked friend:', username)
+ }
+
+ return (
+
+ {/* Close Button - Top Right */}
+
+
+
+
+ {/* Main Content */}
+
+ {/* Header with Streak */}
+
+
+
0 day streak!
+
Streak
+
+
+
+
+ {/* Streak Calendar */}
+
+
+
+
+ {/* Share Your Streak Section */}
+
+
+
+ 4
+
+
I'm on a
+
4 day streak!
+
mind block
+
+
+
+
+
+
+
+
+
+
+
+ {/* Tabs and Friends List */}
+
+
+ Following
+ Followers
+
+
+
+
+ {mockFollowing.map((friend) => (
+ handleFriendClick(friend.username)}
+ />
+ ))}
+
+
+
+
+
+ {mockFollowers.map((friend) => (
+ handleFriendClick(friend.username)}
+ />
+ ))}
+
+
+
+
+ {/* Add Friends Action */}
+
+
+
+ )
+}
diff --git a/frontend/components.json b/frontend/components.json
new file mode 100644
index 0000000..cfbafe2
--- /dev/null
+++ b/frontend/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "src/styles/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
\ No newline at end of file
diff --git a/frontend/components/friend-list-item.tsx b/frontend/components/friend-list-item.tsx
new file mode 100644
index 0000000..2519875
--- /dev/null
+++ b/frontend/components/friend-list-item.tsx
@@ -0,0 +1,43 @@
+'use client'
+
+import { ChevronRight } from 'lucide-react'
+import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'
+import { cn } from '@/lib/utils'
+
+interface FriendListItemProps {
+ avatar?: string
+ avatarFallback?: string
+ username: string
+ onClick?: () => void
+ className?: string
+}
+
+export function FriendListItem({
+ avatar,
+ avatarFallback = '?',
+ username,
+ onClick,
+ className,
+}: FriendListItemProps) {
+ return (
+
+
+
+
+ )
+}
diff --git a/frontend/components/streak-calendar.tsx b/frontend/components/streak-calendar.tsx
new file mode 100644
index 0000000..fecf169
--- /dev/null
+++ b/frontend/components/streak-calendar.tsx
@@ -0,0 +1,105 @@
+'use client'
+
+import { useState } from 'react'
+import { ChevronLeft, ChevronRight } from 'lucide-react'
+
+const DAYS_OF_WEEK = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
+
+interface StreakCalendarProps {
+ streakDays?: number[]
+}
+
+export function StreakCalendar({ streakDays = [4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 20, 21, 25, 26, 27] }: StreakCalendarProps) {
+ const [currentDate, setCurrentDate] = useState(new Date(2022, 7, 1)) // August 2022
+
+ const getDaysInMonth = (date: Date) => {
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
+ }
+
+ const getFirstDayOfMonth = (date: Date) => {
+ return new Date(date.getFullYear(), date.getMonth(), 1).getDay()
+ }
+
+ const monthName = currentDate.toLocaleString('default', { month: 'short' }).toUpperCase()
+ const year = currentDate.getFullYear()
+ const daysInMonth = getDaysInMonth(currentDate)
+ const firstDay = getFirstDayOfMonth(currentDate)
+
+ // Create array of day numbers, accounting for empty cells at start
+ const calendarDays = []
+ for (let i = 0; i < firstDay; i++) {
+ calendarDays.push(null)
+ }
+ for (let i = 1; i <= daysInMonth; i++) {
+ calendarDays.push(i)
+ }
+
+ const handlePreviousMonth = () => {
+ setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1))
+ }
+
+ const handleNextMonth = () => {
+ setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1))
+ }
+
+ const isStreakDay = (day: number | null) => {
+ return day !== null && streakDays.includes(day)
+ }
+
+ return (
+
+
Streak Calendar
+
+ {/* Month Navigation */}
+
+
+
+
+ {monthName} {year}
+
+
+
+
+
+ {/* Day Headers */}
+
+ {DAYS_OF_WEEK.map((day) => (
+
+ {day}
+
+ ))}
+
+
+ {/* Calendar Grid */}
+
+ {calendarDays.map((day, index) => (
+
+ {day === null ? (
+
+ ) : (
+
+ {day}
+
+ )}
+
+ ))}
+
+
+ )
+}