Skip to content

Commit 6f456f5

Browse files
feat: add image domain configuration, implement landing and home page components, and create stats page with latest questions and top contributors
1 parent 05836c4 commit 6f456f5

File tree

10 files changed

+160
-95
lines changed

10 files changed

+160
-95
lines changed

next.config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
4+
images: {
5+
domains: ['cloud.appwrite.io'],
6+
remotePatterns: [
7+
{
8+
protocol: 'https',
9+
hostname: 'cloud.appwrite.io',
10+
port: '',
11+
pathname: '/v1/storage/**',
12+
},
13+
],
14+
},
415
/* config options here */
516
};
617

src/app/components/HeroSection.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
1-
2-
import React from "react";
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import React, {useState, useEffect} from "react";
33
import { HeroParallax } from "@/components/ui/hero-parallax";
4-
import { databases } from "@/models/server/config";
4+
import { databases } from "@/models/client/config";
55
import { db, questionAttachmentbucket, questionCollection } from "@/models/name";
66
import { Query } from "node-appwrite";
77
import slugify from "@/utils/slugify";
88
import { storage } from "@/models/client/config";
99
import HeroSectionHeader from "./HeroSectionHeader";
1010

11-
export default async function HeroSection() {
12-
const questions = await databases.listDocuments(db, questionCollection, [
13-
Query.orderDesc("$createdAt"),
14-
Query.limit(15),
15-
]);
11+
export default function HeroSection() {
12+
const [questions, setQuestions] = useState<any[]>([]);
13+
14+
useEffect(() => {
15+
const fetchQuestions = async () => {
16+
const result = await databases.listDocuments(db, questionCollection, [
17+
Query.orderDesc("$createdAt"),
18+
Query.limit(15),
19+
]);
20+
setQuestions(result.documents);
21+
22+
};
23+
fetchQuestions();
24+
}, []);
25+
1626

1727
return (
1828
<HeroParallax
1929
header={<HeroSectionHeader />}
20-
products={questions.documents.map(q => ({
30+
products={questions.map(q => ({
2131
title: q.title,
2232
link: `/questions/${q.$id}/${slugify(q.title)}`,
23-
thumbnail: storage.getFilePreview(questionAttachmentbucket, q.attachmentId),
33+
thumbnail: storage.getFileView(questionAttachmentbucket, q.attachmentId),
2434
}))}
2535
/>
2636
);

src/app/components/HeroSectionHeader.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
"use client";
21

32
import {IconCloud} from "@/components/magicui/icon-cloud";
43
import {Particles} from "@/components/magicui/particles";
@@ -67,13 +66,22 @@ const HeroSectionHeader = () => {
6766
</p>
6867
<div className="flex items-center justify-center gap-4">
6968
{session ? (
70-
<Link href="/questions/ask">
69+
<div className="flex flex-row gap-4">
70+
<Link href="/questions/ask">
7171
<ShimmerButton className="shadow-2xl">
7272
<span className="whitespace-pre-wrap text-center text-sm font-medium leading-none tracking-tight text-white dark:from-white dark:to-slate-900/10 lg:text-lg">
7373
Ask a question
7474
</span>
7575
</ShimmerButton>
76-
</Link>
76+
</Link>
77+
<Link href="/stats">
78+
<ShimmerButton className="shadow-2xl">
79+
<span className="whitespace-pre-wrap text-center text-sm font-medium leading-none tracking-tight text-white dark:from-white dark:to-slate-900/10 lg:text-lg">
80+
See stats
81+
</span>
82+
</ShimmerButton>
83+
</Link>
84+
</div>
7785
) : (
7886
<>
7987
<Link href="/register">

src/app/components/HomePage.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import HeroSection from "./HeroSection";
2+
3+
export default function HomePage(){
4+
return(
5+
<>
6+
<HeroSection/>
7+
</>
8+
)
9+
}

src/app/components/Landing.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"use client";
2+
import Link from "next/link";
3+
import { ShimmerButton } from "@/components/magicui/shimmer-button";
4+
import { BorderBeam } from "@/components/magicui/border-beam";
5+
import React from "react";
6+
7+
export default function Landing() {
8+
const ref = React.useRef<HTMLDivElement>(null);
9+
const [height, setHeight] = React.useState(0);
10+
11+
React.useEffect(() => {
12+
if (ref.current) {
13+
setHeight(ref.current.clientHeight);
14+
}
15+
16+
}, [ref]);
17+
return (
18+
<div className="bg-black text-white min-h-screen py-20 mt-20">
19+
<header className="container mx-auto px-4 text-center items-center mb-12">
20+
<h1 className="text-5xl text-center font-bold">
21+
<span className="relative">
22+
<span className="absolute inset-0 bg-gray-800 rounded-md -ml-2 -mr-2 -mt-1 -mb-1 z-0"></span>
23+
<span className="relative z-1 text-blue-500">Outofbound</span>
24+
</span>
25+
</h1>
26+
</header>
27+
28+
<section className="container mx-auto px-4 text-center mb-24">
29+
<h1 className="text-3xl font-bold mb-6">
30+
Unlock the Power of Community Knowledge
31+
</h1>
32+
<p className="text-lg text-gray-400 mb-8">
33+
Outofbound is the platform for sharing and discovering solutions to
34+
your coding challenges. Join our community and level up your skills.
35+
</p>
36+
37+
<div className="mb-10 flex items-center justify-center">
38+
<Link href={"/register"}>
39+
<ShimmerButton className="shadow-2xl">
40+
<span className="whitespace-pre-wrap text-center text-sm font-bold py-3 px-6 leading-none tracking-tight text-white dark:from-white dark:to-slate-900/10 lg:text-lg">
41+
Get Started for Free
42+
</span>
43+
</ShimmerButton>
44+
</Link>
45+
</div>
46+
</section>
47+
48+
<section className="container mx-auto px-4 grid grid-cols-1 md:grid-cols-3 gap-8 mb-24">
49+
<div ref={ref}
50+
className="relative gap-4 overflow-hidden rounded-xl border border-white/20 bg-white/5 p-4 duration-200 hover:bg-white/10 sm:flex-row">
51+
<BorderBeam size={height} duration={12} delay={9}/>
52+
<h2 className="text-xl font-bold mb-4">Ask Questions</h2>
53+
<p className="text-gray-400">
54+
Get help from experienced developers in our community.
55+
</p>
56+
</div>
57+
<div ref={ref}
58+
className="relative gap-4 overflow-hidden rounded-xl border border-white/20 bg-white/5 p-4 duration-200 hover:bg-white/10 sm:flex-row">
59+
<BorderBeam size={height} duration={12} delay={9}/>
60+
<h2 className="text-xl font-bold mb-4">Share Answers</h2>
61+
<p className="text-gray-400">
62+
Showcase your expertise and help others solve their problems.
63+
</p>
64+
</div>
65+
<div ref={ref}
66+
className="relative gap-4 overflow-hidden rounded-xl border border-white/20 bg-white/5 p-4 duration-200 hover:bg-white/10 sm:flex-row">
67+
<BorderBeam size={height} duration={12} delay={9}/>
68+
<h2 className="text-xl font-bold mb-4">Level Up</h2>
69+
<p className="text-gray-400">
70+
Improve your coding skills and build your reputation.
71+
</p>
72+
</div>
73+
</section>
74+
75+
<footer className="container mx-auto px-4 text-center text-gray-500">
76+
<p>&copy; 2025 Outofbound. All rights reserved.</p>
77+
</footer>
78+
</div>
79+
);
80+
}

src/app/components/LatestQuestions.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ const LatestQuestions = async () => {
4141
})
4242
);
4343

44-
console.log("Latest question")
45-
console.log(questions)
4644
return (
4745
<div className="space-y-6">
4846
{questions.documents.map(question => (

src/app/components/TopContributors.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export default async function TopContributers() {
5252
const topUsers = await users.list<UserPrefs>([Query.limit(10)]);
5353

5454
return (
55-
<div className="bg-white/10 relative flex max-h-[400px] min-h-[400px] w-full max-w-[32rem] flex-col overflow-hidden rounded-lg bg-white/10 p-6 shadow-lg">
55+
<div className="bg-white/10 relative flex max-h-[400px] min-h-[400px] w-full max-w-[32rem] flex-col overflow-hidden rounded-lg p-6 shadow-lg">
5656
<AnimatedList>
5757
{topUsers.users.map(user => (
5858
<Notification user={user} key={user.$id} />

src/app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { cn } from "@/lib/utils";
88
import Header from "./components/Header";
99
import Footer from "./components/Footer";
1010
export const metadata: Metadata = {
11-
title: "Create Next App",
12-
description: "Generated by create next app",
11+
title: "outofbound",
12+
description: "Unlock the Power of Community Knowledge",
1313
};
1414

1515
export default function RootLayout({

src/app/page.tsx

Lines changed: 5 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,11 @@
1-
"use client"
2-
import Link from "next/link";
3-
import { ShimmerButton } from "@/components/magicui/shimmer-button";
1+
"use client";
42
import { useAuthStore } from "@/store/Auth";
5-
import slugify from "@/utils/slugify";
6-
import { BorderBeam } from "@/components/magicui/border-beam";
73
import React from "react";
4+
import Landing from "./components/Landing";
5+
import HomePage from "./components/HomePage";
86

97
export default function Home() {
10-
const {user} = useAuthStore()
11-
const ref = React.useRef<HTMLDivElement>(null);
12-
const [height, setHeight] = React.useState(0);
8+
const {user} = useAuthStore();
139

14-
React.useEffect(() => {
15-
if (ref.current) {
16-
setHeight(ref.current.clientHeight);
17-
}
18-
19-
}, [ref]);
20-
return (
21-
<div className="bg-black text-white min-h-screen py-20 mt-20">
22-
<header className="container mx-auto px-4 text-center items-center mb-12">
23-
<h1 className="text-5xl text-center font-bold">
24-
<span className="relative">
25-
<span className="absolute inset-0 bg-gray-800 rounded-md -ml-2 -mr-2 -mt-1 -mb-1 z-0"></span>
26-
<span className="relative z-1 text-blue-500">Outofbound</span>
27-
</span>
28-
</h1>
29-
</header>
30-
31-
<section className="container mx-auto px-4 text-center mb-24">
32-
<h1 className="text-3xl font-bold mb-6">
33-
Unlock the Power of Community Knowledge
34-
</h1>
35-
<p className="text-lg text-gray-400 mb-8">
36-
Outofbound is the platform for sharing and discovering solutions to
37-
your coding challenges. Join our community and level up your skills.
38-
</p>
39-
40-
<div className="mb-10 flex items-center justify-center">
41-
<Link href={user ?`/users/${user.$id}/${slugify(user.name)}`: "/register"}>
42-
<ShimmerButton className="shadow-2xl">
43-
<span className="whitespace-pre-wrap text-center text-sm font-bold py-3 px-6 leading-none tracking-tight text-white dark:from-white dark:to-slate-900/10 lg:text-lg">
44-
Get Started for Free
45-
</span>
46-
</ShimmerButton>
47-
</Link>
48-
</div>
49-
</section>
50-
51-
<section className="container mx-auto px-4 grid grid-cols-1 md:grid-cols-3 gap-8 mb-24">
52-
<div ref={ref}
53-
className="relative gap-4 overflow-hidden rounded-xl border border-white/20 bg-white/5 p-4 duration-200 hover:bg-white/10 sm:flex-row">
54-
<BorderBeam size={height} duration={12} delay={9}/>
55-
<h2 className="text-xl font-bold mb-4">Ask Questions</h2>
56-
<p className="text-gray-400">
57-
Get help from experienced developers in our community.
58-
</p>
59-
</div>
60-
<div ref={ref}
61-
className="relative gap-4 overflow-hidden rounded-xl border border-white/20 bg-white/5 p-4 duration-200 hover:bg-white/10 sm:flex-row">
62-
<BorderBeam size={height} duration={12} delay={9}/>
63-
<h2 className="text-xl font-bold mb-4">Share Answers</h2>
64-
<p className="text-gray-400">
65-
Showcase your expertise and help others solve their problems.
66-
</p>
67-
</div>
68-
<div ref={ref}
69-
className="relative gap-4 overflow-hidden rounded-xl border border-white/20 bg-white/5 p-4 duration-200 hover:bg-white/10 sm:flex-row">
70-
<BorderBeam size={height} duration={12} delay={9}/>
71-
<h2 className="text-xl font-bold mb-4">Level Up</h2>
72-
<p className="text-gray-400">
73-
Improve your coding skills and build your reputation.
74-
</p>
75-
</div>
76-
</section>
77-
78-
<footer className="container mx-auto px-4 text-center text-gray-500">
79-
<p>&copy; 2025 Outofbound. All rights reserved.</p>
80-
</footer>
81-
</div>
82-
);
10+
return user ? <HomePage/> : <Landing/>;
8311
}

src/app/stats/page.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import LatestQuestions from "../components/LatestQuestions";
2+
import TopContributers from "../components/TopContributors";
3+
4+
const Page = async () => {
5+
return (
6+
<div className="mt-20 container mx-auto px-4 py-8">
7+
<div className="grid sm:grid-cols-2 gap-4">
8+
<div className="w-full">
9+
<h1 className="m-4 text-3xl">Top Contributors</h1>
10+
<TopContributers />
11+
</div>
12+
<div className="w-full">
13+
<h1 className="m-4 text-3xl">Latest Questions</h1>
14+
<LatestQuestions />
15+
</div>
16+
</div>
17+
</div>
18+
)
19+
}
20+
21+
export default Page;

0 commit comments

Comments
 (0)