Skip to content

Commit 1d6a07d

Browse files
committed
feat: Complete Phase 1 - Static Pages & Layouts
Implement complete page structure with navigation: **Layout Components:** - ✅ Header with navigation and branding - ✅ Footer with links - ✅ Browse layout wrapper for all content pages **Pages Implemented:** - ✅ Homepage with hero and CTA buttons - ✅ /tech - Technologies listing page - ✅ /tech/[slug] - Technology detail page - ✅ /stacks - Stacks listing page - ✅ /stacks/[slug] - Stack detail page - ✅ /top - Top technologies and stacks ranking - ✅ /favorites - User favorites page **Features:** - Responsive design with Tailwind CSS - Modern UI with gradient accents - Card-based layouts - Hover animations and transitions - Search input placeholders - Mock data for demonstration - Next.js 15 App Router with route groups **Build Stats:** - 8 pages total - First Load JS: 102 kB - 6 static pages, 2 dynamic routes - All pages building successfully Ready for Phase 2: Data Integration
1 parent 4ad9b92 commit 1d6a07d

File tree

10 files changed

+633
-36
lines changed

10 files changed

+633
-36
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
2+
3+
export default function FavoritesPage() {
4+
// Mock favorites - in real app, this would come from user's session
5+
const favoriteTechs = [
6+
{ id: 1, name: 'React', tier: 'Frontend Library' },
7+
{ id: 2, name: 'TypeScript', tier: 'Programming Language' },
8+
{ id: 3, name: 'Next.js', tier: 'Frontend Framework' },
9+
]
10+
11+
const favoriteStacks = [
12+
{ id: 1, name: 'Modern Web Stack', techCount: 8 },
13+
{ id: 2, name: 'E-commerce Platform', techCount: 12 },
14+
]
15+
16+
return (
17+
<div className="container py-8">
18+
<div className="mb-8">
19+
<h1 className="text-4xl font-bold tracking-tight">My Favorites</h1>
20+
<p className="text-lg text-muted-foreground mt-2">
21+
Technologies and stacks you&apos;ve favorited
22+
</p>
23+
</div>
24+
25+
{favoriteTechs.length === 0 && favoriteStacks.length === 0 ? (
26+
<Card>
27+
<CardContent className="flex flex-col items-center justify-center py-16">
28+
<div className="text-4xl mb-4">❤️</div>
29+
<h3 className="text-xl font-semibold mb-2">No favorites yet</h3>
30+
<p className="text-muted-foreground text-center max-w-md">
31+
Start exploring technologies and stacks, then favorite the ones you love to see them here!
32+
</p>
33+
</CardContent>
34+
</Card>
35+
) : (
36+
<div className="space-y-8">
37+
{favoriteTechs.length > 0 && (
38+
<div>
39+
<h2 className="text-2xl font-bold mb-4">Favorite Technologies</h2>
40+
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
41+
{favoriteTechs.map((tech) => (
42+
<Card key={tech.id}>
43+
<CardHeader>
44+
<CardTitle>{tech.name}</CardTitle>
45+
<CardDescription>{tech.tier}</CardDescription>
46+
</CardHeader>
47+
</Card>
48+
))}
49+
</div>
50+
</div>
51+
)}
52+
53+
{favoriteStacks.length > 0 && (
54+
<div>
55+
<h2 className="text-2xl font-bold mb-4">Favorite Stacks</h2>
56+
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
57+
{favoriteStacks.map((stack) => (
58+
<Card key={stack.id}>
59+
<CardHeader>
60+
<CardTitle>{stack.name}</CardTitle>
61+
<CardDescription>{stack.techCount} technologies</CardDescription>
62+
</CardHeader>
63+
</Card>
64+
))}
65+
</div>
66+
</div>
67+
)}
68+
</div>
69+
)}
70+
</div>
71+
)
72+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Header } from '@/components/layout/header'
2+
import { Footer } from '@/components/layout/footer'
3+
4+
export default function BrowseLayout({
5+
children,
6+
}: {
7+
children: React.ReactNode
8+
}) {
9+
return (
10+
<div className="relative flex min-h-screen flex-col">
11+
<Header />
12+
<main className="flex-1">{children}</main>
13+
<Footer />
14+
</div>
15+
)
16+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
2+
import { Button } from '@/components/ui/button'
3+
4+
export default async function StackDetailPage({ params }: { params: Promise<{ slug: string }> }) {
5+
const { slug } = await params
6+
// Mock data for demonstration
7+
const stack = {
8+
name: 'Modern Web Stack',
9+
description: 'A comprehensive full-stack web development setup with React and Node.js',
10+
creator: 'TechCorp',
11+
favCount: 42,
12+
technologies: [
13+
{ id: 1, name: 'React', tier: 'Frontend Library' },
14+
{ id: 2, name: 'Next.js', tier: 'Frontend Framework' },
15+
{ id: 3, name: 'TypeScript', tier: 'Programming Language' },
16+
{ id: 4, name: 'Node.js', tier: 'Runtime' },
17+
{ id: 5, name: 'PostgreSQL', tier: 'Database' },
18+
{ id: 6, name: 'Tailwind CSS', tier: 'CSS Framework' },
19+
{ id: 7, name: 'Vercel', tier: 'Hosting' },
20+
{ id: 8, name: 'GitHub Actions', tier: 'CI/CD' },
21+
],
22+
}
23+
24+
return (
25+
<div className="container py-8">
26+
<div className="mb-8">
27+
<div className="flex items-start justify-between">
28+
<div>
29+
<h1 className="text-4xl font-bold tracking-tight">{stack.name}</h1>
30+
<p className="text-lg text-muted-foreground mt-2">
31+
by {stack.creator}
32+
</p>
33+
</div>
34+
<Button size="lg">❤️ Favorite</Button>
35+
</div>
36+
</div>
37+
38+
<div className="grid gap-8 lg:grid-cols-3">
39+
<div className="lg:col-span-2">
40+
<Card className="mb-8">
41+
<CardHeader>
42+
<CardTitle>About This Stack</CardTitle>
43+
</CardHeader>
44+
<CardContent>
45+
<p className="text-muted-foreground">{stack.description}</p>
46+
</CardContent>
47+
</Card>
48+
49+
<div>
50+
<h2 className="text-2xl font-bold mb-4">Technology Stack</h2>
51+
<div className="grid gap-4 sm:grid-cols-2">
52+
{stack.technologies.map((tech) => (
53+
<Card key={tech.id} className="hover:shadow-md transition-shadow">
54+
<CardHeader>
55+
<CardTitle className="text-lg">{tech.name}</CardTitle>
56+
<CardDescription>{tech.tier}</CardDescription>
57+
</CardHeader>
58+
</Card>
59+
))}
60+
</div>
61+
</div>
62+
</div>
63+
64+
<div>
65+
<Card>
66+
<CardHeader>
67+
<CardTitle>Stats</CardTitle>
68+
</CardHeader>
69+
<CardContent className="space-y-4">
70+
<div>
71+
<div className="text-2xl font-bold">{stack.favCount}</div>
72+
<div className="text-sm text-muted-foreground">Favorites</div>
73+
</div>
74+
<div>
75+
<div className="text-2xl font-bold">{stack.technologies.length}</div>
76+
<div className="text-sm text-muted-foreground">Technologies</div>
77+
</div>
78+
</CardContent>
79+
</Card>
80+
</div>
81+
</div>
82+
</div>
83+
)
84+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
2+
3+
export default function StacksPage() {
4+
// Temporary mock data for layout demonstration
5+
const mockStacks = [
6+
{
7+
id: 1,
8+
name: 'Modern Web Stack',
9+
description: 'Full-stack web development with React and Node.js',
10+
techCount: 8,
11+
favCount: 42,
12+
},
13+
{
14+
id: 2,
15+
name: 'Serverless Stack',
16+
description: 'Cloud-native serverless architecture',
17+
techCount: 6,
18+
favCount: 31,
19+
},
20+
{
21+
id: 3,
22+
name: 'E-commerce Platform',
23+
description: 'Scalable e-commerce technology stack',
24+
techCount: 12,
25+
favCount: 58,
26+
},
27+
{
28+
id: 4,
29+
name: 'Mobile-First Stack',
30+
description: 'Cross-platform mobile development',
31+
techCount: 7,
32+
favCount: 26,
33+
},
34+
{
35+
id: 5,
36+
name: 'Data Science Stack',
37+
description: 'Machine learning and data analysis',
38+
techCount: 10,
39+
favCount: 39,
40+
},
41+
{
42+
id: 6,
43+
name: 'DevOps Pipeline',
44+
description: 'Complete CI/CD infrastructure',
45+
techCount: 9,
46+
favCount: 45,
47+
},
48+
]
49+
50+
return (
51+
<div className="container py-8">
52+
<div className="mb-8">
53+
<h1 className="text-4xl font-bold tracking-tight">Technology Stacks</h1>
54+
<p className="text-lg text-muted-foreground mt-2">
55+
Explore complete technology stacks from successful companies
56+
</p>
57+
</div>
58+
59+
<div className="mb-6">
60+
<input
61+
type="search"
62+
placeholder="Search stacks..."
63+
className="w-full rounded-md border border-input bg-background px-4 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
64+
/>
65+
</div>
66+
67+
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
68+
{mockStacks.map((stack) => (
69+
<Card key={stack.id} className="hover:shadow-lg transition-shadow">
70+
<CardHeader>
71+
<CardTitle>{stack.name}</CardTitle>
72+
<CardDescription>{stack.description}</CardDescription>
73+
</CardHeader>
74+
<CardContent>
75+
<div className="flex items-center gap-4 text-sm text-muted-foreground">
76+
<span>🔧 {stack.techCount} technologies</span>
77+
<span>❤️ {stack.favCount} favorites</span>
78+
</div>
79+
</CardContent>
80+
</Card>
81+
))}
82+
</div>
83+
</div>
84+
)
85+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
2+
import { Button } from '@/components/ui/button'
3+
4+
export default async function TechDetailPage({ params }: { params: Promise<{ slug: string }> }) {
5+
const { slug } = await params
6+
// Mock data for demonstration
7+
const technology = {
8+
name: 'React',
9+
tier: 'Frontend Library',
10+
vendor: 'Meta',
11+
description: 'React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called "components".',
12+
website: 'https://react.dev',
13+
favCount: 1234,
14+
stackCount: 567,
15+
}
16+
17+
const relatedStacks = [
18+
{ id: 1, name: 'Modern Web Stack', techCount: 8 },
19+
{ id: 2, name: 'E-commerce Platform', techCount: 12 },
20+
{ id: 3, name: 'SaaS Starter', techCount: 10 },
21+
]
22+
23+
return (
24+
<div className="container py-8">
25+
<div className="mb-8">
26+
<div className="flex items-start justify-between">
27+
<div>
28+
<h1 className="text-4xl font-bold tracking-tight">{technology.name}</h1>
29+
<p className="text-lg text-muted-foreground mt-2">
30+
{technology.tier} by {technology.vendor}
31+
</p>
32+
</div>
33+
<Button size="lg">❤️ Favorite</Button>
34+
</div>
35+
</div>
36+
37+
<div className="grid gap-8 lg:grid-cols-3">
38+
<div className="lg:col-span-2">
39+
<Card>
40+
<CardHeader>
41+
<CardTitle>About {technology.name}</CardTitle>
42+
</CardHeader>
43+
<CardContent className="prose max-w-none">
44+
<p>{technology.description}</p>
45+
</CardContent>
46+
</Card>
47+
48+
<div className="mt-8">
49+
<h2 className="text-2xl font-bold mb-4">Stacks using {technology.name}</h2>
50+
<div className="grid gap-4">
51+
{relatedStacks.map((stack) => (
52+
<Card key={stack.id}>
53+
<CardHeader>
54+
<CardTitle>{stack.name}</CardTitle>
55+
<CardDescription>{stack.techCount} technologies</CardDescription>
56+
</CardHeader>
57+
</Card>
58+
))}
59+
</div>
60+
</div>
61+
</div>
62+
63+
<div>
64+
<Card>
65+
<CardHeader>
66+
<CardTitle>Stats</CardTitle>
67+
</CardHeader>
68+
<CardContent className="space-y-4">
69+
<div>
70+
<div className="text-2xl font-bold">{technology.favCount}</div>
71+
<div className="text-sm text-muted-foreground">Favorites</div>
72+
</div>
73+
<div>
74+
<div className="text-2xl font-bold">{technology.stackCount}</div>
75+
<div className="text-sm text-muted-foreground">Used in Stacks</div>
76+
</div>
77+
{technology.website && (
78+
<div className="pt-4">
79+
<Button variant="outline" className="w-full" asChild>
80+
<a href={technology.website} target="_blank" rel="noopener noreferrer">
81+
Visit Website →
82+
</a>
83+
</Button>
84+
</div>
85+
)}
86+
</CardContent>
87+
</Card>
88+
</div>
89+
</div>
90+
</div>
91+
)
92+
}

0 commit comments

Comments
 (0)