diff --git a/README.md b/README.md index 5b3a680..83cc8d5 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,11 @@ The official website for the DevHub developer community. Built with Next.js, Typ ## What's in here -- Community docs and guides - - rules - - getting started - - how-to's +- Landing page +- Community guides - Resource library, curated tools and learning materials -- Documentations: +- Partners page +- DevHub Pages: - Getting Started - Join Guide - Server Info @@ -20,6 +19,7 @@ The official website for the DevHub developer community. Built with Next.js, Typ - Moderation Guide - Staff Roles - FAQ + - and many many more ## Tech Stack @@ -27,6 +27,7 @@ The official website for the DevHub developer community. Built with Next.js, Typ - **Language** - TypeScript - **Styling** - Tailwind CSS - **Animation Libriary** - GSAP and Framer Motion +- **Component Libriary** - React Bits - **Icons** - Lucide - **Deployment** - Vercel @@ -35,14 +36,14 @@ The official website for the DevHub developer community. Built with Next.js, Typ ### Prerequisites - Node.js 18+ -- npm, yarn, or pnpm +- bun, npm, yarn, or pnpm ### Setup ```bash # Clone the repo git clone https://github.com/open-devhub/website -cd devhub-website +cd website # Install dependencies npm install @@ -63,7 +64,7 @@ Open [http://localhost:3000](http://localhost:3000) and you're in. │ └── 📄 settings.json ├── 📁 app │ ├── 📁 api -│ │ └── 📁 link-preview +│ │ └── 📁 preview │ │ └── 📄 route.ts │ ├── 📁 pages │ │ ├── 📁 [slug] @@ -73,6 +74,12 @@ Open [http://localhost:3000](http://localhost:3000) and you're in. │ │ │ └── 📄 page.tsx │ │ ├── 📄 layout.tsx │ │ └── 📄 page.tsx +│ ├── 📁 articles +│ │ ├── 📁 [slug] +│ │ │ ├── 📄 ArticleClient.tsx +│ │ │ └── 📄 page.tsx +│ │ ├── 📄 ArticlesListingClient.tsx +│ │ └── 📄 page.tsx │ ├── 📁 partners │ │ └── 📄 page.tsx │ ├── 📁 resources @@ -116,28 +123,9 @@ Open [http://localhost:3000](http://localhost:3000) and you're in. │ └── 📄 LinkPreviewCard.tsx ├── 📁 content │ ├── 📁 pages -│ │ ├── 📁 bots -│ │ │ ├── 📄 adding-a-bot.md -│ │ │ └── 📄 bots.md -│ │ ├── 📁 community -│ │ │ ├── 📄 acknowledgements.md -│ │ │ ├── 📄 code-of-conduct.md -│ │ │ ├── 📄 faq.md -│ │ │ ├── 📄 getting-started.md -│ │ │ ├── 📄 how-to-ask.md -│ │ │ ├── 📄 how-to-help.md -│ │ │ ├── 📄 join-guide.md -│ │ │ ├── 📄 moderation-guide.md -│ │ │ ├── 📄 server-info.md -│ │ │ └── 📄 staff-roles.md -│ │ ├── 📁 legal -│ │ │ ├── 📄 privacy-policy.md -│ │ │ └── 📄 security-notice.md -│ │ └── 📁 open-source -│ │ ├── 📄 contributing.md -│ │ ├── 📄 github-org.md -│ │ ├── 📄 project-guidelines.md -│ │ └── 📄 submit-project.md +│ │ └── ... +│ ├── 📁 articles +│ │ └── ... │ ├── 📄 pages-loader.ts │ ├── 📄 pages-sections.ts │ ├── 📄 resources.ts @@ -180,7 +168,7 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide. The short version: 4. Run `npm run lint` 5. Open a PR with a clear description -First time contributing to open source? Look for issues tagged [`good first issue`](https://github.com/devhub-community/devhub-website/issues?q=is%3Aopen+label%3A%22good+first+issue%22). +First time contributing to open source? Look for issues tagged [`good first issue`](https://github.com/open-devhub/website/issues?q=is%3Aopen+label%3A%22good+first+issue%22). ## Scripts diff --git a/app/articles/[slug]/page.tsx b/app/articles/[slug]/page.tsx index 4f03971..d8be432 100644 --- a/app/articles/[slug]/page.tsx +++ b/app/articles/[slug]/page.tsx @@ -1,5 +1,5 @@ import { articles } from "@/content/articles-loader"; -import { PREVIEWS } from "@/lib/previews"; +import { PREVIEWS } from "@/content/previews"; import { notFound } from "next/navigation"; import ArticleClient from "./ArticleClient"; diff --git a/app/pages/[slug]/[subslug]/page.tsx b/app/pages/[slug]/[subslug]/page.tsx index 0f58df4..c1121d5 100644 --- a/app/pages/[slug]/[subslug]/page.tsx +++ b/app/pages/[slug]/[subslug]/page.tsx @@ -1,5 +1,5 @@ import { getAdjacentPages, getPage } from "@/content/pages-loader"; -import { PREVIEWS } from "@/lib/previews"; +import { PREVIEWS } from "@/content/previews"; import { notFound } from "next/navigation"; import PageClient from "../PageClient"; diff --git a/app/pages/[slug]/page.tsx b/app/pages/[slug]/page.tsx index 68b0a6b..3f8200c 100644 --- a/app/pages/[slug]/page.tsx +++ b/app/pages/[slug]/page.tsx @@ -1,5 +1,5 @@ import { getAdjacentPages, getPage } from "@/content/pages-loader"; -import { PREVIEWS } from "@/lib/previews"; +import { PREVIEWS } from "@/content/previews"; import { notFound } from "next/navigation"; import PageClient from "./PageClient"; diff --git a/app/partners/page.tsx b/app/partners/page.tsx index da162eb..34ad503 100644 --- a/app/partners/page.tsx +++ b/app/partners/page.tsx @@ -1,6 +1,8 @@ "use client"; import ShinyText from "@/components/bits/ShinyText"; +import { Partner, partners } from "@/content/partners"; +import { fadeInUp, staggerContainer } from "@/lib/animations"; import { accent, background, @@ -11,7 +13,6 @@ import { semantic, text, } from "@/lib/colors"; -import { fadeInUp, staggerContainer } from "@/lib/animations"; import { motion } from "framer-motion"; import { ArrowRight, @@ -24,41 +25,6 @@ import { } from "lucide-react"; import { useEffect, useState } from "react"; -type Partner = { - inviteCode: string; - tags?: string[]; - websiteUrl?: string; - githubUrl?: string; - - // Optional fallback if Discord has no banner - banner?: string; -}; - -const partners: Partner[] = [ - { - inviteCode: "3xKFvKhuGR", - tags: ["Coding", "Programming", "Developer", "Python", "Community"], - websiteUrl: "https://thecodeversehub.tech", - githubUrl: "https://github.com/TheCodeVerseHub", - }, - { - inviteCode: "F6Z27BMBhE", - tags: [ - "Coding", - "Programming", - "Developing", - "Games and fun", - "Server Not Found", - ], - }, - { - inviteCode: "BGrCXccWDa", - banner: partnerColors.bannerBrown, - tags: ["Javaceans", "Coding", "DEV Support"], - githubUrl: "https://github.com/drive-for-java", - }, -]; - type DiscordData = { guildId: string; @@ -71,7 +37,8 @@ type DiscordData = { iconUrl: string | null; bannerUrl: string | null; - traits: string[]; + traits: { label: string }[]; + features: string[]; }; const TRAIT_LABELS: Record = @@ -220,9 +187,9 @@ function PartnerCard({ const serverDescription = discord?.description ?? "No server description available."; - const tags = partner.tags ?? []; + const features = (discord?.features ?? []).filter((t) => TRAIT_LABELS[t]); - const traits = (discord?.traits ?? []).filter((t) => TRAIT_LABELS[t]); + const traits = (discord?.traits ?? []).filter((t) => t.label); const fallbackBanner = partner.banner; @@ -359,7 +326,7 @@ function PartnerCard({ {/* Name */}

- {/* Traits */} - {traits.length > 0 && ( -
- {traits.map((trait) => { - const { label, icon: Icon } = TRAIT_LABELS[trait]; + {/* Features */} + {features.length > 0 && ( +
+ {features.map((feature) => { + const { label, icon: Icon } = TRAIT_LABELS[feature]; return ( - {/* Tags */} + {/* Traits */}
- {tags.map((tag) => ( + {traits.map((trait) => ( - {tag} + {trait.label} ))}
@@ -424,7 +391,7 @@ function PartnerCard({ {/* Buttons */}
>({}); const [loadingMap, setLoadingMap] = useState>(() => - Object.fromEntries(partners.map((p) => [p.inviteCode, true])), + Object.fromEntries(partners.map((p) => [p.code, true])), ); useEffect(() => { @@ -513,26 +480,27 @@ export default function PartnersPage() { partners.map(async (p) => { try { const res = await fetch( - `https://discord.com/api/v10/invites/${p.inviteCode}?with_counts=true`, + `https://discord.com/api/v10/invites/${p.code}?with_counts=true`, { signal: controller.signal }, ); if (!res.ok) { - setDiscordData((prev) => ({ ...prev, [p.inviteCode]: null })); + setDiscordData((prev) => ({ ...prev, [p.code]: null })); return; } const data = await res.json(); const guild = data.guild; + const profile = data.profile; if (!guild) { - setDiscordData((prev) => ({ ...prev, [p.inviteCode]: null })); + setDiscordData((prev) => ({ ...prev, [p.code]: null })); return; } setDiscordData((prev) => ({ ...prev, - [p.inviteCode]: { + [p.code]: { guildId: guild.id, name: guild.name, @@ -549,18 +517,19 @@ export default function PartnersPage() { ? `https://cdn.discordapp.com/banners/${guild.id}/${guild.banner}.png?size=1024` : null, - traits: guild.features ?? [], + features: guild.features ?? [], + traits: profile.traits ?? [], }, })); } catch (error) { const aborted = error instanceof DOMException && error.name === "AbortError"; if (!aborted) { - setDiscordData((prev) => ({ ...prev, [p.inviteCode]: null })); + setDiscordData((prev) => ({ ...prev, [p.code]: null })); } } finally { if (!controller.signal.aborted) { - setLoadingMap((prev) => ({ ...prev, [p.inviteCode]: false })); + setLoadingMap((prev) => ({ ...prev, [p.code]: false })); } } }), @@ -727,13 +696,13 @@ export default function PartnersPage() { {/* ─── Cards ─── */}
{partners.map((partner, i) => - loadingMap[partner.inviteCode] ? ( - + loadingMap[partner.code] ? ( + ) : ( ), diff --git a/components/LinkPreviewCard.tsx b/components/LinkPreviewCard.tsx index 5a36788..6dc000c 100644 --- a/components/LinkPreviewCard.tsx +++ b/components/LinkPreviewCard.tsx @@ -9,7 +9,7 @@ export interface PreviewData { image?: string | null; } -function truncate(desc: string, maxLength = 300) { +function truncate(desc: string, maxLength = 200) { if (desc.length <= maxLength) return desc; const cut = desc.slice(0, maxLength); const lastSpace = cut.lastIndexOf(" "); diff --git a/content/partners.ts b/content/partners.ts new file mode 100644 index 0000000..aef67ca --- /dev/null +++ b/content/partners.ts @@ -0,0 +1,27 @@ +import { partner as partnerColors } from "@/lib/colors"; + +export type Partner = { + code: string; + tags?: string[]; + websiteUrl?: string; + githubUrl?: string; + + // Optional fallback if Discord has no banner + banner?: string; +}; + +export const partners: Partner[] = [ + { + code: "3xKFvKhuGR", + websiteUrl: "https://thecodeversehub.tech", + githubUrl: "https://github.com/TheCodeVerseHub", + }, + { + code: "F6Z27BMBhE", + }, + { + code: "BGrCXccWDa", + banner: partnerColors.bannerBrown, + githubUrl: "https://github.com/drive-for-java", + }, +]; diff --git a/lib/previews.ts b/content/previews.ts similarity index 97% rename from lib/previews.ts rename to content/previews.ts index b1d54b3..cc6a9d5 100644 --- a/lib/previews.ts +++ b/content/previews.ts @@ -64,6 +64,8 @@ const HARDCODED_PREVIEWS: Record = { title: "The CodeVerse Hub", description: "The Codeverse Hub is a developer community and open-source organization. We build real projects, review each other's code, and help developers grow — from first commit to production maintainer.", + image: + "https://cdn.discordapp.com/icons/1263067254153805905/be135eaf9deb55ef9a4c0b52648de511.webp?size=96&quality=lossless", }, // GitHub