Skip to content

Commit 8957615

Browse files
feat: finalize visual design task
1 parent 806d8b1 commit 8957615

13 files changed

Lines changed: 11458 additions & 336 deletions

File tree

package-lock.json

Lines changed: 10707 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/(public)/about/page.tsx

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Metadata } from "next";
22
import Link from "next/link";
3-
import Button from "@/components/ui/Button";
43

54
export const revalidate = 3600;
65

@@ -37,14 +36,43 @@ export default function AboutPage() {
3736
<main className="bg-white">
3837
<section className="py-24 md:py-32">
3938
<div className="mx-auto max-w-5xl px-6">
40-
<div className="max-w-4xl space-y-6">
39+
<div className="mx-auto max-w-4xl text-center">
4140
<h1 className="font-mono text-4xl font-bold leading-[1.1] text-[#121F38] md:text-[56px]">
4241
About CodedDevs
4342
</h1>
44-
<p className="max-w-3xl font-sans text-lg leading-[1.75] text-[#2C3A52]">
43+
<p className="mx-auto mt-6 max-w-3xl font-sans text-lg leading-[1.75] text-[#2C3A52]">
4544
We build AI-first software products for African markets — from
4645
first principles.
4746
</p>
47+
48+
<div className="mx-auto mt-12 max-w-2xl border-t border-[#C4CAD6] md:mt-16"></div>
49+
50+
<div className="mx-auto mt-12 grid max-w-4xl gap-10 md:mt-16 md:grid-cols-3 md:gap-8">
51+
<div className="space-y-3">
52+
<h3 className="font-mono text-xl font-medium leading-[1.4] text-[#121F38]">
53+
AI Systems
54+
</h3>
55+
<p className="mx-auto max-w-xs font-sans text-base leading-[1.7] text-[#6B7896]">
56+
Intelligent software built for African workflows
57+
</p>
58+
</div>
59+
<div className="space-y-3">
60+
<h3 className="font-mono text-xl font-medium leading-[1.4] text-[#121F38]">
61+
Infrastructure
62+
</h3>
63+
<p className="mx-auto max-w-xs font-sans text-base leading-[1.7] text-[#6B7896]">
64+
Reliable platforms designed for scale and resilience
65+
</p>
66+
</div>
67+
<div className="space-y-3">
68+
<h3 className="font-mono text-xl font-medium leading-[1.4] text-[#121F38]">
69+
Open Source
70+
</h3>
71+
<p className="mx-auto max-w-xs font-sans text-base leading-[1.7] text-[#6B7896]">
72+
Transparent engineering with community-first development
73+
</p>
74+
</div>
75+
</div>
4876
</div>
4977
</div>
5078
</section>
@@ -70,51 +98,66 @@ export default function AboutPage() {
7098
</div>
7199
</section>
72100

73-
<section className="py-16 md:py-24">
74-
<div className="mx-auto grid max-w-5xl gap-10 px-6 md:grid-cols-[280px_1fr]">
75-
<h2 className="font-mono text-3xl font-bold leading-[1.2] text-[#121F38] md:text-[40px]">
76-
How We Build
77-
</h2>
78-
<div className="space-y-6 font-sans text-lg leading-[1.75] text-[#2C3A52]">
79-
<p>
80-
Our approach is AI-first and deeply focused on the African
81-
market. We solve real-world challenges unique to the region — not
82-
by adapting tools built elsewhere, but by engineering from first
83-
principles.
84-
</p>
85-
<p>
86-
We build in the open. Our products are open-source because we
87-
believe the best software for Africa should be built with Africa.
88-
</p>
89-
</div>
90-
</div>
91-
</section>
92-
93-
<section className="py-16 md:py-24">
101+
<section>
94102
<div className="mx-auto max-w-5xl px-6">
95-
<div className="grid gap-6 md:grid-cols-4">
96-
{companyFacts.map((fact) => (
97-
<div key={fact.label} className="space-y-2">
98-
<p className="font-sans text-xs font-medium uppercase text-[#6B7896]">
99-
{fact.label}
103+
<div className="border-y border-[#C4CAD6] py-16 md:py-24">
104+
<div className="grid items-center gap-10 md:grid-cols-[minmax(0,1.15fr)_minmax(220px,0.85fr)] md:gap-16">
105+
<div className="order-1 max-w-xs md:order-2">
106+
<h2 className="font-mono text-3xl font-bold leading-[1.2] text-[#121F38] md:text-[40px]">
107+
How We Build
108+
</h2>
109+
</div>
110+
<div className="order-2 max-w-2xl space-y-5 font-sans text-lg leading-[1.75] text-[#2C3A52] md:order-1">
111+
<p>
112+
Our approach is AI-first and deeply focused on the African
113+
market. We solve real-world challenges unique to the region —
114+
not by adapting tools built elsewhere, but by engineering from
115+
first principles.
100116
</p>
101-
<p className="font-sans text-base leading-[1.7] text-[#121F38]">
102-
{fact.value}
117+
<p>
118+
We build in the open. Our products are open-source because we
119+
believe the best software for Africa should be built with
120+
Africa.
103121
</p>
104122
</div>
105-
))}
123+
</div>
106124
</div>
107125
</div>
108126
</section>
109127

110-
<section className="bg-[#F4F5F8] py-16 md:py-20">
111-
<div className="mx-auto flex max-w-5xl flex-col gap-6 px-6 md:flex-row md:items-center md:justify-between">
112-
<h2 className="font-mono text-2xl font-semibold leading-[1.3] text-[#121F38]">
113-
Meet the team behind CodedDevs
114-
</h2>
115-
<Button asChild>
116-
<Link href="/team">Meet the Team</Link>
117-
</Button>
128+
<section className="pb-24 pt-16 md:pb-32 md:pt-24">
129+
<div className="mx-auto max-w-5xl px-6">
130+
<div className="grid grid-cols-1 border-t border-[var(--color-border)] md:grid-cols-4">
131+
{companyFacts.map((fact, idx) => (
132+
<div
133+
key={fact.label}
134+
className="border-b border-[var(--color-border)] py-6 last:border-b-0 md:border-b-0 md:border-l md:px-6 md:py-8 md:first:border-l-0 md:first:pl-0"
135+
>
136+
<div
137+
className={`space-y-2 ${
138+
["", "md:mt-4", "md:mt-8", "md:mt-12"][idx]
139+
}`}
140+
>
141+
<p className="font-sans text-[11px] font-medium uppercase tracking-wider text-[var(--color-text-muted)]">
142+
{fact.label}
143+
</p>
144+
<div className="space-y-1">
145+
<p className="font-sans text-[15px] leading-relaxed text-[var(--color-text-primary)]">
146+
{fact.value}
147+
</p>
148+
{fact.label === "Team" && (
149+
<Link
150+
href="/team"
151+
className="mt-1 inline-block font-sans text-[13px] text-[var(--color-text-muted)] underline decoration-[var(--color-border)] decoration-1 underline-offset-4 transition-colors hover:text-[var(--color-text-primary)] hover:decoration-[var(--color-text-primary)]"
152+
>
153+
Meet the team &rarr;
154+
</Link>
155+
)}
156+
</div>
157+
</div>
158+
</div>
159+
))}
160+
</div>
118161
</div>
119162
</section>
120163
</main>

src/app/(public)/blog/page.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ export default async function UpdatesPage() {
5959

6060
return (
6161
<main className="bg-white">
62-
<section className="py-24 md:py-32">
63-
<div className="mx-auto max-w-5xl px-6">
64-
<div className="max-w-3xl space-y-6">
62+
<section className="py-20 md:py-24">
63+
<div className="mx-auto max-w-4xl px-6">
64+
<div className="max-w-2xl space-y-4">
65+
<span className="mb-2 block font-sans text-xs font-semibold uppercase tracking-[0.15em] text-[#6B7896]">
66+
COMPANY NEWS
67+
</span>
6568
<h1 className="font-mono text-4xl font-bold leading-[1.1] text-[#121F38] md:text-[56px]">
6669
Updates
6770
</h1>
@@ -73,8 +76,12 @@ export default async function UpdatesPage() {
7376
</div>
7477
</section>
7578

76-
<section className="pb-24 md:pb-32">
77-
<div className="mx-auto max-w-5xl px-6">
79+
<div className="mx-auto max-w-4xl px-6">
80+
<hr className="border-[#C4CAD6]" />
81+
</div>
82+
83+
<section className="py-16 md:py-24">
84+
<div className="mx-auto max-w-4xl px-6">
7885
<UpdatesList posts={posts} />
7986
</div>
8087
</section>

src/app/(public)/products/page.tsx

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { Metadata } from "next";
22
import Link from "next/link";
33
import Badge from "@/components/ui/Badge";
4-
import Card from "@/components/ui/Card";
54
import { ArrowRightIcon, ExternalLinkIcon } from "@/components/ui/icons";
65
import { db, products } from "@/db";
76
import type { ProductSelect } from "@/types";
@@ -29,23 +28,18 @@ export const metadata: Metadata = {
2928
},
3029
};
3130

32-
function formatStatus(status: ProductSelect["status"]) {
33-
return status
34-
.split("-")
35-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
36-
.join(" ");
31+
function formatStatus(status: string) {
32+
if (status === "development") return "In development";
33+
if (status === "beta") return "Beta";
34+
if (status === "live") return "Live";
35+
return status.charAt(0).toUpperCase() + status.slice(1);
3736
}
3837

39-
function statusVariant(status: ProductSelect["status"]) {
40-
if (status === "live") {
41-
return "success";
42-
}
43-
44-
if (status === "development") {
45-
return "warning";
46-
}
47-
48-
return "muted";
38+
function statusVariant(status: string) {
39+
if (status === "live") return "success";
40+
if (status === "beta") return "warning";
41+
if (status === "development") return "muted";
42+
return "default";
4943
}
5044

5145
async function getProducts() {
@@ -68,6 +62,7 @@ async function getProducts() {
6862
}
6963
}
7064

65+
7166
export default async function ProductsPage() {
7267
const allProducts = await getProducts();
7368

@@ -86,50 +81,66 @@ export default async function ProductsPage() {
8681
</div>
8782
</section>
8883

89-
<section className="pb-24 md:pb-32">
84+
<section className="pb-24">
9085
<div className="mx-auto max-w-5xl px-6">
9186
{allProducts.length > 0 ? (
92-
<div className="grid gap-6 md:grid-cols-2">
93-
{allProducts.map((product) => (
94-
<Card key={product.id}>
95-
<div className="space-y-6">
87+
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
88+
{allProducts.map((product) => {
89+
// Mocking category and beta status for UI demonstration
90+
const category =
91+
product.slug.includes("api") || product.slug.includes("dev")
92+
? "Developer tools"
93+
: "Fintech";
94+
const displayStatus =
95+
product.status === "archived" ? "beta" : product.status;
96+
97+
return (
98+
<div
99+
key={product.id}
100+
className="flex h-full flex-col justify-between rounded-md border-[0.5px] border-[#C4CAD6] bg-white p-6 shadow-none"
101+
>
96102
<div className="space-y-4">
97-
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
98-
<h2 className="font-mono text-[28px] font-semibold leading-[1.3] text-[#121F38]">
103+
<div className="flex items-center justify-between gap-3">
104+
<Badge variant={statusVariant(displayStatus)}>
105+
{formatStatus(displayStatus)}
106+
</Badge>
107+
<span className="font-sans text-[11px] font-medium uppercase tracking-wider text-[#6B7896]">
108+
{category}
109+
</span>
110+
</div>
111+
<div className="space-y-2">
112+
<h2 className="font-mono text-xl font-bold leading-tight text-[#121F38]">
99113
{product.name}
100114
</h2>
101-
<Badge variant={statusVariant(product.status)}>
102-
{formatStatus(product.status)}
103-
</Badge>
115+
<p className="line-clamp-1 font-sans text-[15px] leading-relaxed text-[#2C3A52]">
116+
{product.tagline}
117+
</p>
104118
</div>
105-
<p className="font-sans text-base leading-[1.7] text-[#2C3A52]">
106-
{product.tagline}
107-
</p>
108119
</div>
109120

110-
<div className="flex flex-col gap-3 font-sans text-sm font-medium sm:flex-row">
121+
<div className="mt-8 flex flex-wrap items-center gap-4 font-sans text-[13px] font-medium">
111122
<Link
112123
href={`/products/${product.slug}`}
113-
className="inline-flex items-center gap-1.5 text-[#121F38] hover:text-[#1A2D4F]"
124+
className="inline-flex items-center gap-1.5 text-[#121F38] transition-colors hover:text-[#1A2D4F]"
114125
>
115126
<span>Learn more</span>
116-
<ArrowRightIcon className="h-4 w-4" />
127+
<ArrowRightIcon className="h-3.5 w-3.5" />
117128
</Link>
118129
{product.external_url ? (
119130
<a
120131
href={product.external_url}
121132
target="_blank"
122133
rel="noopener noreferrer"
123-
className="inline-flex items-center gap-1.5 text-[#121F38] hover:text-[#1A2D4F]"
134+
className="inline-flex items-center gap-1.5 text-[#6B7896] transition-colors hover:text-[#121F38]"
124135
>
125136
<span>Visit product</span>
126-
<ExternalLinkIcon className="h-4 w-4" />
137+
<ExternalLinkIcon className="h-3.5 w-3.5" />
127138
</a>
128139
) : null}
129140
</div>
130141
</div>
131-
</Card>
132-
))}
142+
);
143+
})}
133144
</div>
134145
) : (
135146
<p className="font-sans text-lg leading-[1.75] text-[#2C3A52]">
@@ -138,6 +149,7 @@ export default async function ProductsPage() {
138149
)}
139150
</div>
140151
</section>
152+
141153
</main>
142154
);
143155
}

0 commit comments

Comments
 (0)