Skip to content

Commit ac1c6a7

Browse files
committed
chore: add conveyor stack roadmap
1 parent 32d565c commit ac1c6a7

12 files changed

Lines changed: 257 additions & 1417 deletions

File tree

File renamed without changes.

app/conveyotstack.tsx

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
"use client";
3+
4+
import { motion } from "framer-motion";
5+
import {
6+
FiGitMerge,
7+
FiLayers,
8+
FiActivity,
9+
FiCloud,
10+
FiCpu,
11+
FiInfo,
12+
} from "react-icons/fi";
13+
14+
export default function RoadmapSection() {
15+
return (
16+
<section
17+
id="roadmap"
18+
className="relative py-32 bg-gray-950 text-gray-200 overflow-hidden"
19+
>
20+
{/* Ambient glow */}
21+
<div className="absolute inset-0 pointer-events-none">
22+
<div className="absolute top-1/3 left-1/2 -translate-x-1/2 w-[700px] h-[700px] bg-blue-600/10 blur-[220px] rounded-full" />
23+
</div>
24+
25+
<div className="relative z-10 container mx-auto px-6">
26+
{/* Header */}
27+
<motion.div
28+
initial={{ opacity: 0, y: 40 }}
29+
whileInView={{ opacity: 1, y: 0 }}
30+
viewport={{ once: true }}
31+
transition={{ duration: 0.8 }}
32+
className="text-center max-w-4xl mx-auto"
33+
>
34+
<h2 className="text-4xl md:text-5xl font-bold text-blue-300">
35+
Conveyor Stack Roadmap
36+
</h2>
37+
<p className="mt-6 text-lg text-gray-300 leading-relaxed">
38+
A long-term initiative to build a sovereign, vendor-neutral IaaS
39+
platform — evolving through open governance or independent system
40+
design.
41+
</p>
42+
</motion.div>
43+
44+
{/* Roadmap */}
45+
<div className="mt-24 flex flex-col items-center gap-14">
46+
<Node
47+
icon={<FiLayers />}
48+
title="Conveyor Stack"
49+
description="A multi-year program to design an open infrastructure platform comparable to OpenStack or Apache CloudStack."
50+
highlight
51+
/>
52+
53+
<Line />
54+
55+
<Node
56+
icon={<FiActivity />}
57+
title="Phase 1: Conveyor CI"
58+
description="A headless, cloud-native CI/CD orchestration engine designed as the foundation of the stack."
59+
/>
60+
61+
<Line />
62+
63+
{/* DECISION GATE */}
64+
<DecisionGate />
65+
66+
{/* SPLIT */}
67+
<SplitPaths />
68+
</div>
69+
</div>
70+
</section>
71+
);
72+
}
73+
74+
/* ================= Components ================= */
75+
76+
function Node({
77+
icon,
78+
title,
79+
description,
80+
highlight = false,
81+
}: {
82+
icon: any;
83+
title: string;
84+
description: string;
85+
highlight?: boolean;
86+
}) {
87+
return (
88+
<motion.div
89+
initial={{ opacity: 0, scale: 0.96 }}
90+
whileInView={{ opacity: 1, scale: 1 }}
91+
viewport={{ once: true }}
92+
transition={{ duration: 0.6 }}
93+
className={`max-w-xl text-center p-8 rounded-2xl border backdrop-blur-lg ${
94+
highlight
95+
? "bg-blue-500/10 border-blue-400/40"
96+
: "bg-gray-900/40 border-gray-800"
97+
}`}
98+
>
99+
<div className="flex justify-center mb-4 text-blue-300 text-3xl">
100+
{icon}
101+
</div>
102+
<h3 className="text-2xl font-semibold text-gray-100">{title}</h3>
103+
<p className="mt-3 text-gray-400 text-sm leading-relaxed">
104+
{description}
105+
</p>
106+
</motion.div>
107+
);
108+
}
109+
110+
function Line() {
111+
return <div className="h-12 w-px bg-gray-700" />;
112+
}
113+
114+
/* -------- Decision Gate -------- */
115+
116+
function DecisionGate() {
117+
return (
118+
<motion.div
119+
initial={{ opacity: 0 }}
120+
whileInView={{ opacity: 1 }}
121+
viewport={{ once: true }}
122+
transition={{ duration: 0.8 }}
123+
className="relative flex flex-col items-center"
124+
>
125+
{/* Pulsing ring */}
126+
<motion.div
127+
animate={{ scale: [1, 1.15, 1], opacity: [0.6, 0.9, 0.6] }}
128+
transition={{ duration: 2.5, repeat: Infinity }}
129+
className="absolute w-40 h-40 rounded-full border border-blue-400/40"
130+
/>
131+
132+
<div className="relative z-10 p-8 bg-gray-900/60 border border-blue-400/40 rounded-2xl backdrop-blur-lg text-center max-w-lg">
133+
<div className="flex justify-center items-center gap-3 text-blue-300 mb-3">
134+
<FiGitMerge className="text-3xl" />
135+
<span className="text-xl font-semibold">
136+
CNCF Sandbox Decision Gate
137+
</span>
138+
<Tooltip text="The acceptance of Conveyor CI into the CNCF Sandbox determines governance, development model, and long-term ecosystem alignment." />
139+
</div>
140+
141+
<p className="text-gray-400 text-sm leading-relaxed">
142+
Conveyor CI is evaluated for acceptance into the CNCF Sandbox. This
143+
outcome determines whether Conveyor Stack evolves through
144+
community-integrated development or through a fully sovereign stack.
145+
</p>
146+
147+
<p className="mt-3 text-xs text-blue-300/80">
148+
Both future pathways depend on this decision.
149+
</p>
150+
</div>
151+
</motion.div>
152+
);
153+
}
154+
155+
/* -------- Split Paths -------- */
156+
157+
function SplitPaths() {
158+
return (
159+
<div className="relative w-full max-w-6xl mt-20">
160+
{/* Vertical connector */}
161+
<div className="absolute left-1/2 -top-10 h-10 w-px bg-gray-700 -translate-x-1/2" />
162+
163+
<motion.div
164+
initial={{ opacity: 0 }}
165+
whileInView={{ opacity: 1 }}
166+
viewport={{ once: true }}
167+
transition={{ duration: 0.6 }}
168+
className="grid md:grid-cols-2 gap-16"
169+
>
170+
<Path
171+
title="Community-Integrated Path"
172+
icon={<FiCloud />}
173+
tooltip="Activated if Conveyor CI is accepted into the CNCF Sandbox."
174+
description="Leverage existing CNCF-aligned systems and communities to accelerate development."
175+
items={[
176+
"Reuse mature databases, brokers, schedulers",
177+
"Community-driven governance",
178+
"Focus on orchestration and integration",
179+
]}
180+
/>
181+
182+
<Path
183+
title="Sovereign Stack Path"
184+
icon={<FiCpu />}
185+
tooltip="Activated if CNCF Sandbox acceptance is not achieved."
186+
description="Design and build a fully sovereign infrastructure stack from first principles."
187+
items={[
188+
"Distributed embeddable document database",
189+
"Event-based message broker",
190+
"Custom storage, networking & compute virtualization",
191+
]}
192+
/>
193+
</motion.div>
194+
</div>
195+
);
196+
}
197+
198+
function Path({
199+
title,
200+
icon,
201+
tooltip,
202+
description,
203+
items,
204+
}: {
205+
title: string;
206+
icon: any;
207+
tooltip: string;
208+
description: string;
209+
items: string[];
210+
}) {
211+
return (
212+
<motion.div
213+
initial={{ opacity: 0, y: 40 }}
214+
whileInView={{ opacity: 1, y: 0 }}
215+
viewport={{ once: true }}
216+
transition={{ duration: 0.7 }}
217+
className="p-8 bg-gray-900/40 border border-gray-800 rounded-2xl backdrop-blur-lg"
218+
>
219+
<div className="flex items-center gap-3 mb-4 text-blue-300">
220+
<span className="text-2xl">{icon}</span>
221+
<h4 className="text-xl font-semibold text-gray-100">{title}</h4>
222+
<Tooltip text={tooltip} />
223+
</div>
224+
225+
<p className="text-gray-400 text-sm leading-relaxed mb-4">
226+
{description}
227+
</p>
228+
229+
<ul className="space-y-2 text-gray-400 text-sm list-disc list-inside">
230+
{items.map((item, i) => (
231+
<li key={i}>{item}</li>
232+
))}
233+
</ul>
234+
</motion.div>
235+
);
236+
}
237+
238+
/* -------- Tooltip -------- */
239+
240+
function Tooltip({ text }: { text: string }) {
241+
return (
242+
<span className="relative group">
243+
<FiInfo className="text-blue-300/70 hover:text-blue-300 cursor-pointer" />
244+
<span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-3 w-72 opacity-0 group-hover:opacity-100 transition pointer-events-none">
245+
<span className="block p-3 text-xs text-gray-200 bg-gray-900 border border-gray-700 rounded-lg shadow-xl">
246+
{text}
247+
</span>
248+
</span>
249+
</span>
250+
);
251+
}
File renamed without changes.

app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getPageMap } from "nextra/page-map";
44
import "nextra-theme-docs/style.css";
55
import "./global.css";
66
import Navbar from "@/components/Navbar";
7-
import Footer from "@/components/home/footer";
7+
import Footer from "@/components/footer";
88

99
export const metadata = {
1010
// Define your metadata here

app/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
"use client";
2-
import AboutSection from "@/components/home/about";
3-
import Hero from "@/components/home/Hero";
4-
import ProjectsSection from "@/components/home/showcase";
5-
import WhatWeDoSection from "@/components/home/whatwedo";
2+
import AboutSection from "@/app/about";
3+
import Hero from "@/app/hero";
4+
import ProjectsSection from "@/app/showcase";
65
import React from "react";
6+
import RoadmapSection from "./conveyotstack";
77

88
const page = () => {
99
return (
1010
<>
1111
<Hero />
1212
<AboutSection />
13-
<WhatWeDoSection />
1413
<ProjectsSection />
14+
<RoadmapSection />
1515
</>
1616
);
1717
};
Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,6 @@ const projects = [
3333
link: "https://cloudnative.open.ug/",
3434
logo: "https://cloudnative.open.ug/_next/static/media/cncg-icon-color.e918a21e.svg",
3535
},
36-
{
37-
name: "Quantum Uganda",
38-
description:
39-
"Building quantum computing research, collaboration, and education in Uganda and beyond.",
40-
link: "https://quantumuganda.org/", // placeholder link
41-
logo: "https://media.licdn.com/dms/image/v2/D4D0BAQGjH19smNNYrw/company-logo_200_200/B4DZjbo4mEH4AM-/0/1756031586569/quantum_uganda_logo?e=1765411200&v=beta&t=dRf1EKs1gxBmXhocW4Oi3BpPFwOevhdNBT74DQCyyeE",
42-
},
4336
];
4437

4538
export default function ProjectsSection() {

0 commit comments

Comments
 (0)