Skip to content

Commit cab2ddd

Browse files
feat: redesign the site and load repo metadata for every owner
- Darker palette, IBM Plex Sans/Mono, accent green kept for small signals (active language, online dot, hover, demo link); no gradient text - Header now holds the language switcher and social links; the Discord widget becomes a compact status line next to the section title - Cards in an equal-height grid: 16:9 covers, clamped text, one-line mono metadata with GitHub language colors, demo shown as primary action, hover with green border, image zoom and underline - Metadata labels are translated; fix "Developpé" typo; html lang follows the selected language - Fetch repos for every owner referenced by the cards (not only the Bit-Scripts org, and past the first 30) and match them by owner/repo Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 9f289f2 commit cab2ddd

16 files changed

Lines changed: 304 additions & 189 deletions

‎context/GlobalProvider.jsx‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { createContext, useState, useEffect } from "react";
2-
import { fetchReposData } from "../utils/helpers";
3-
import { ORGNAME } from "../config/globals";
2+
import { fetchReposData, getRepoFullName } from "../utils/helpers";
3+
import { cardsData } from "../data/cardsData";
4+
5+
// Propriétaires (orgs ou utilisateurs) des dépôts référencés par les cartes
6+
const REPO_OWNERS = [
7+
...new Set(
8+
cardsData
9+
.map((card) => getRepoFullName(card.github)?.split("/")[0])
10+
.filter(Boolean),
11+
),
12+
];
413

514
export const GlobalContext = createContext();
615

@@ -10,7 +19,7 @@ const GlobalProvider = ({ children }) => {
1019

1120
useEffect(() => {
1221
if (!reposData) {
13-
fetchReposData(ORGNAME)
22+
fetchReposData(REPO_OWNERS)
1423
.then((res) => {
1524
if (res) {
1625
setReposData(res);

‎hooks/useProjectInfo.jsx‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
import { useMemo } from "react";
2+
import { getRepoFullName } from "../utils/helpers";
23

3-
function useProjectInfo(reposData, githubRepoName) {
4-
const findProjectObjectByName = (array, name) => {
4+
function useProjectInfo(reposData, githubProjectUrl) {
5+
const findProjectObjectByFullName = (array, fullName) => {
56
if (!array) {
67
// console.log("Vous devez fournir un tableau");
78
return null;
89
}
910

10-
if (!name) {
11+
if (!fullName) {
1112
// console.log("Vous devez fournir un élément à rechercher");
1213
return null;
1314
}
14-
return array.find((item) => item.name === name);
15+
return array.find((item) => item.full_name.toLowerCase() === fullName);
1516
};
1617

1718
const projectInfo = useMemo(() => {
18-
return findProjectObjectByName(reposData, githubRepoName);
19-
}, [reposData, githubRepoName]);
19+
return findProjectObjectByFullName(
20+
reposData,
21+
getRepoFullName(githubProjectUrl),
22+
);
23+
}, [reposData, githubProjectUrl]);
2024

2125
return projectInfo;
2226
}

‎index.html‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<meta name="theme-color" content="#0a0a0a" />
8+
<meta
9+
name="description"
10+
content="Bit-Scripts — logiciels, scripts et bots open source."
11+
/>
12+
<link rel="preconnect" href="https://fonts.googleapis.com" />
13+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14+
<link
15+
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500;600&display=swap"
16+
rel="stylesheet"
17+
/>
718
<title>Bit-Scripts</title>
819
</head>
920
<body>

‎src/App.jsx‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
import CardsWrapper from "./components/CardsWrapper";
22
import Header from "./components/Header";
33
import Info from "./components/Info";
4-
import LangageSwitcher from "./components/LangSwitcher";
54
import GlobalProvider from "../context/GlobalProvider";
6-
import DiscordWidget from "./components/Discord";
75
import Footer from "./components/Footer";
86

97
function App() {
108
return (
119
<GlobalProvider>
12-
<div className="min-h-screen overflow-x-hidden bg-neutral-800">
10+
<div className="flex min-h-screen flex-col overflow-x-hidden">
1311
<Header />
14-
<LangageSwitcher />
15-
<DiscordWidget />
16-
<Info />
17-
<CardsWrapper />
12+
<main className="mx-auto w-full max-w-6xl flex-1 px-4 sm:px-6">
13+
<Info />
14+
<CardsWrapper />
15+
</main>
1816
<Footer />
1917
</div>
2018
</GlobalProvider>

‎src/components/Card.jsx‎

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useTranslation } from "react-i18next";
22
import { FaGithub } from "react-icons/fa";
3-
import { MdOutlineRemoveRedEye } from "react-icons/md";
3+
import { FiArrowUpRight } from "react-icons/fi";
44
import { BASE_IMG_PATH, DEFAULT_IMG_COVER } from "../../config/globals";
55
import GithubInfo from "./GithubInfo";
66

@@ -11,50 +11,61 @@ function Card({
1111
demoUrl,
1212
author,
1313
githubProjectUrl,
14-
githubRepoName,
1514
}) {
1615
const { t } = useTranslation();
1716

18-
const buttonStyle =
19-
"bg-accentDarker flex min-w-[120px] cursor-pointer items-center justify-center rounded-full py-2 text-white transition-opacity hover:opacity-80";
17+
const linkStyle =
18+
"flex items-center gap-1.5 text-neutral-300 transition-colors hover:text-accent";
19+
const demoStyle =
20+
"flex items-center gap-1 rounded-full border border-accent/30 bg-accent/[0.06] px-3 py-1 text-accent transition-colors hover:border-accent/60 hover:bg-accent/[0.12]";
2021

2122
return (
22-
<div className="h-[580px] w-[330px] overflow-hidden rounded-2xl bg-neutral-900 shadow-lg">
23-
<div
24-
className={`h-[200px] border-b border-accent bg-cover`}
25-
style={{ backgroundImage: `url(${BASE_IMG_PATH}${imgName})` }}
26-
></div>
27-
<div className="flex h-[calc(100%-200px)] flex-col px-4 py-4">
28-
<div className="text-center text-2xl font-bold text-neutral-200">
23+
<article className="group relative flex flex-col overflow-hidden rounded-lg border border-white/[0.08] bg-neutral-900 transition-[border-color,box-shadow] duration-300 hover:border-accent/30 hover:shadow-[0_12px_32px_-12px_rgba(0,255,11,0.18)]">
24+
<div className="relative aspect-[16/9] overflow-hidden border-b border-white/[0.06] bg-neutral-950">
25+
<img
26+
src={`${BASE_IMG_PATH}${imgName}`}
27+
alt=""
28+
loading="lazy"
29+
className="h-full w-full object-cover transition-transform duration-500 ease-out group-hover:scale-[1.04] motion-reduce:transition-none motion-reduce:group-hover:scale-100"
30+
/>
31+
<span className="absolute inset-x-0 bottom-0 h-px origin-left scale-x-0 bg-accent transition-transform duration-200 ease-out group-hover:scale-x-100 motion-reduce:transition-none" />
32+
</div>
33+
34+
<div className="flex flex-1 flex-col p-5">
35+
<h2 className="line-clamp-2 text-lg font-semibold leading-snug text-neutral-100">
2936
{title}
30-
</div>
37+
</h2>
3138

32-
<div className="max-h-[250px] overflow-hidden pt-2 text-sm text-neutral-200">
39+
<p className="mt-2 line-clamp-5 text-sm leading-relaxed text-neutral-400">
3340
{t(`app.card:${translationKey}.description`)}
34-
</div>
35-
<GithubInfo githubRepoName={githubRepoName} />
41+
</p>
3642

37-
<div className="flex grow flex-col justify-end">
38-
<div className="text-center italic text-neutral-300">
39-
{t("devby")} <span className="font-bold">{author}</span>
40-
</div>
41-
<div className="flex justify-center gap-x-4 py-2">
42-
{githubProjectUrl && (
43-
<a className={`${buttonStyle}`} href={githubProjectUrl}>
44-
<FaGithub size={"20"} className="mr-2" />
45-
GitHub
46-
</a>
47-
)}
48-
49-
{demoUrl && (
50-
<a className={`${buttonStyle}`} href={demoUrl}>
51-
<MdOutlineRemoveRedEye size={"24"} className="mr-2" /> Demo
52-
</a>
53-
)}
43+
<GithubInfo githubProjectUrl={githubProjectUrl} />
44+
45+
<div className="mt-auto pt-5">
46+
<div className="flex items-center justify-between gap-4 border-t border-white/[0.06] pt-4 text-sm">
47+
<span className="text-neutral-500">
48+
{t("devby")} <span className="text-neutral-300">{author}</span>
49+
</span>
50+
51+
<div className="flex min-h-[30px] items-center gap-4">
52+
{githubProjectUrl && (
53+
<a className={linkStyle} href={githubProjectUrl}>
54+
<FaGithub size={15} />
55+
{t("code")}
56+
</a>
57+
)}
58+
{demoUrl && (
59+
<a className={demoStyle} href={demoUrl}>
60+
{t("demo")}
61+
<FiArrowUpRight size={15} />
62+
</a>
63+
)}
64+
</div>
5465
</div>
5566
</div>
5667
</div>
57-
</div>
68+
</article>
5869
);
5970
}
6071

‎src/components/CardsWrapper.jsx‎

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,18 @@ import { cardsData } from "../../data/cardsData";
33

44
function CardsWrapper() {
55
return (
6-
<div className="flex items-center justify-center">
7-
<div className="flex max-w-[1280px] flex-wrap justify-center gap-8 p-8">
8-
{cardsData.map((card, i) => {
9-
return (
10-
<Card
11-
title={card.title}
12-
imgName={card.imageCover}
13-
key={i}
14-
translationKey={card.project}
15-
demoUrl={card.demo}
16-
author={card.author}
17-
githubProjectUrl={card.github}
18-
githubRepoName={card.githubRepoName}
19-
/>
20-
);
21-
})}
22-
</div>
6+
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
7+
{cardsData.map((card) => (
8+
<Card
9+
title={card.title}
10+
imgName={card.imageCover}
11+
key={card.project}
12+
translationKey={card.project}
13+
demoUrl={card.demo}
14+
author={card.author}
15+
githubProjectUrl={card.github}
16+
/>
17+
))}
2318
</div>
2419
);
2520
}

‎src/components/Discord.jsx‎

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
1-
import { MdOnlinePrediction } from "react-icons/md";
21
import { Avatar, AvatarGroup } from "@chakra-ui/react";
3-
import { FaDiscord } from "react-icons/fa";
42
import useDiscordInfo from "../../hooks/useDiscordInfo";
5-
import { GUILDID } from "../../config/globals";
3+
import { GUILDID, DISCORDINVITECODE } from "../../config/globals";
64
import { useTranslation } from "react-i18next";
75

86
function DiscordWidget() {
97
const { t } = useTranslation();
108
const { infos } = useDiscordInfo(GUILDID);
11-
const membersOnline = infos?.members ?? [];
12-
const presenceCount = infos?.presence_count ?? "🙈";
139

1410
if (!infos) return null;
1511

16-
return (
17-
<div className="flex justify-center pt-2 sm:pt-10">
18-
<div className="mx-4 flex w-full max-w-[800px] flex-wrap items-center justify-center gap-4 rounded-lg border border-accentDarker bg-neutral-900 px-6 py-2 text-neutral-300 sm:gap-6 sm:py-4">
19-
<div className="flex items-center">
20-
<FaDiscord size={20} className="mr-2" />
21-
<span className="font-bold">Discord Bit-Scripts</span>
22-
</div>
12+
const membersOnline = infos.members ?? [];
2313

24-
<div className="flex items-center">
25-
<MdOnlinePrediction size={22} className="mr-2 align-baseline" />
26-
<span className="font-bold">
27-
{t("online")} : {presenceCount}
28-
</span>
29-
</div>
14+
return (
15+
<a
16+
href={`https://discord.com/invite/${DISCORDINVITECODE}`}
17+
className="group flex items-center gap-4 self-start rounded-lg border border-white/[0.08] bg-neutral-900 py-2.5 pl-4 pr-3 transition-colors hover:border-white/20 lg:self-auto"
18+
>
19+
<span className="flex items-center gap-2 text-sm">
20+
<span className="relative flex h-2 w-2">
21+
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-accent opacity-40 motion-reduce:hidden" />
22+
<span className="relative inline-flex h-2 w-2 rounded-full bg-accent" />
23+
</span>
24+
<span className="text-neutral-200">
25+
<span className="font-mono">{infos.presence_count}</span>{" "}
26+
{t("online")}
27+
</span>
28+
</span>
3029

31-
<AvatarGroup size="sm" max={7} textColor="black">
32-
{membersOnline.map((member, i) => (
30+
{membersOnline.length > 0 && (
31+
<AvatarGroup size="xs" max={5} spacing="-0.4rem" fontSize="10px">
32+
{membersOnline.map((member) => (
3333
<Avatar
3434
name={member.username}
3535
src={member.avatar_url}
36-
key={i}
37-
bg="gray.50"
36+
key={member.id}
37+
bg="gray.600"
38+
borderColor="#171717"
3839
/>
3940
))}
4041
</AvatarGroup>
41-
</div>
42-
</div>
42+
)}
43+
44+
<span className="text-sm text-neutral-500 transition-colors group-hover:text-neutral-200">
45+
{t("join")} →
46+
</span>
47+
</a>
4348
);
4449
}
4550

‎src/components/Footer.jsx‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
1+
import { DISCORDINVITECODE } from "../../config/globals";
2+
13
function Footer() {
4+
const link = "transition-colors hover:text-neutral-200";
5+
26
return (
3-
<div className="mt-16 flex min-h-[100px] items-center justify-center bg-neutral-900 text-neutral-300">
4-
<span className="font-bold">
5-
{new Date().getFullYear()} - Bit-Scripts
6-
</span>
7-
</div>
7+
<footer className="mt-24 border-t border-white/[0.06]">
8+
<div className="mx-auto flex w-full max-w-6xl items-center justify-between px-4 py-8 text-sm text-neutral-500 sm:px-6">
9+
<span>© {new Date().getFullYear()} Bit-Scripts</span>
10+
<div className="flex gap-5">
11+
<a className={link} href="https://github.com/Bit-Scripts">
12+
GitHub
13+
</a>
14+
<a
15+
className={link}
16+
href={`https://discord.com/invite/${DISCORDINVITECODE}`}
17+
>
18+
Discord
19+
</a>
20+
</div>
21+
</div>
22+
</footer>
823
);
924
}
1025

0 commit comments

Comments
 (0)