Skip to content

Commit a05dcc9

Browse files
Merge pull request #3 from coded-devs/feature/performance
perf: performance optimisations
2 parents 7c1cc16 + a33e02e commit a05dcc9

23 files changed

Lines changed: 984 additions & 479 deletions

File tree

AGENTS.md

Lines changed: 262 additions & 212 deletions
Large diffs are not rendered by default.

CLAUDE.md

Lines changed: 261 additions & 211 deletions
Large diffs are not rendered by default.

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
1+
import type { Metadata } from "next";
12
import Link from "next/link";
23
import Button from "@/components/ui/Button";
34

5+
export const revalidate = 3600;
6+
7+
const title = "About — CodedDevs Technology LTD";
8+
const description =
9+
"We build AI-first software products for African markets. Learn about our mission and approach.";
10+
11+
export const metadata: Metadata = {
12+
title,
13+
description,
14+
openGraph: {
15+
title,
16+
description,
17+
url: "https://codeddevs.com/about",
18+
siteName: "CodedDevs Technology LTD",
19+
type: "website",
20+
},
21+
twitter: {
22+
card: "summary_large_image",
23+
title,
24+
description,
25+
},
26+
};
27+
428
const companyFacts = [
529
{ label: "Founded", value: "March 2026" },
630
{ label: "Registered", value: "RC 9426867, Nigeria" },

src/app/(public)/blog/[slug]/page.tsx

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import type { Metadata } from "next";
22
import Image from "next/image";
33
import { notFound } from "next/navigation";
4+
import { cache } from "react";
45
import { and, desc, eq } from "drizzle-orm";
56
import PostContent, {
67
type TiptapJson,
78
} from "@/components/blog/PostContent";
89
import Badge from "@/components/ui/Badge";
910
import { blogPosts, db } from "@/db";
11+
import { getOptimisedUrl } from "@/lib/cloudinary";
12+
13+
export const revalidate = 3600;
1014

1115
type UpdatePageProps = {
1216
params: {
@@ -30,7 +34,7 @@ function isTiptapJson(value: unknown): value is TiptapJson {
3034
return typeof value === "object" && value !== null && !Array.isArray(value);
3135
}
3236

33-
async function getPublishedPostBySlug(slug: string) {
37+
const getPublishedPostBySlug = cache(async (slug: string) => {
3438
try {
3539
const [post] = await db
3640
.select()
@@ -39,11 +43,10 @@ async function getPublishedPostBySlug(slug: string) {
3943
.limit(1);
4044

4145
return post ?? null;
42-
} catch (error) {
43-
console.error("Failed to fetch update", error);
46+
} catch {
4447
return null;
4548
}
46-
}
49+
});
4750

4851
export async function generateStaticParams() {
4952
if (process.env.CI === "true") {
@@ -70,13 +73,34 @@ export async function generateMetadata({
7073

7174
if (!post) {
7275
return {
73-
title: "Update \u2014 CodedDevs Updates",
76+
title: "Update CodedDevs Updates",
7477
};
7578
}
7679

80+
const title = `${post.title} — CodedDevs Updates`;
81+
const description = post.excerpt;
82+
const url = `https://codeddevs.com/blog/${post.slug}`;
83+
const images = post.cover_url
84+
? [{ url: getOptimisedUrl(post.cover_url), alt: post.title }]
85+
: undefined;
86+
7787
return {
78-
title: `${post.title} \u2014 CodedDevs Updates`,
79-
description: post.excerpt,
88+
title,
89+
description,
90+
openGraph: {
91+
title,
92+
description,
93+
url,
94+
siteName: "CodedDevs Technology LTD",
95+
type: "article",
96+
images,
97+
},
98+
twitter: {
99+
card: "summary_large_image",
100+
title,
101+
description,
102+
images: images?.map((image) => image.url),
103+
},
80104
};
81105
}
82106

@@ -113,7 +137,7 @@ export default async function UpdatePage({ params }: UpdatePageProps) {
113137
<div className="mx-auto max-w-5xl px-6">
114138
<div className="relative aspect-[16/9] overflow-hidden rounded-lg bg-[#F4F5F8]">
115139
<Image
116-
src={post.cover_url}
140+
src={getOptimisedUrl(post.cover_url)}
117141
alt={post.title}
118142
fill
119143
sizes="(min-width: 1024px) 1024px, 100vw"

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
1+
import type { Metadata } from "next";
12
import { desc, eq } from "drizzle-orm";
23
import UpdatesList, {
34
type UpdateListPost,
45
} from "@/components/blog/UpdatesList";
56
import { blogPosts, db } from "@/db";
67

7-
export const dynamic = "force-dynamic";
8+
export const revalidate = 3600;
9+
10+
const title = "Updates — CodedDevs Technology LTD";
11+
const description =
12+
"Product updates, announcements, and stories from the CodedDevs team.";
13+
14+
export const metadata: Metadata = {
15+
title,
16+
description,
17+
openGraph: {
18+
title,
19+
description,
20+
url: "https://codeddevs.com/blog",
21+
siteName: "CodedDevs Technology LTD",
22+
type: "website",
23+
},
24+
twitter: {
25+
card: "summary_large_image",
26+
title,
27+
description,
28+
},
29+
};
830

931
async function getPublishedPosts(): Promise<UpdateListPost[]> {
1032
try {
@@ -17,6 +39,7 @@ async function getPublishedPosts(): Promise<UpdateListPost[]> {
1739
author: blogPosts.author,
1840
category: blogPosts.category,
1941
published_at: blogPosts.published_at,
42+
cover_url: blogPosts.cover_url,
2043
})
2144
.from(blogPosts)
2245
.where(eq(blogPosts.is_published, true))
@@ -26,8 +49,7 @@ async function getPublishedPosts(): Promise<UpdateListPost[]> {
2649
...post,
2750
published_at: post.published_at?.toISOString() ?? null,
2851
}));
29-
} catch (error) {
30-
console.error("Failed to fetch updates", error);
52+
} catch {
3153
return [];
3254
}
3355
}

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

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Metadata } from "next";
12
import Link from "next/link";
23
import { desc, eq } from "drizzle-orm";
34
import ApplicationForm from "@/components/careers/ApplicationForm";
@@ -7,7 +8,33 @@ import Card from "@/components/ui/Card";
78
import { careers, db } from "@/db";
89
import type { Career } from "@/types";
910

10-
export const dynamic = "force-dynamic";
11+
export const revalidate = 3600;
12+
13+
const title = "Careers — CodedDevs Technology LTD";
14+
const description =
15+
"Work with CodedDevs. We are a small team building software for African markets.";
16+
17+
type OpenRole = Pick<
18+
Career,
19+
"id" | "title" | "type" | "location" | "description"
20+
>;
21+
22+
export const metadata: Metadata = {
23+
title,
24+
description,
25+
openGraph: {
26+
title,
27+
description,
28+
url: "https://codeddevs.com/careers",
29+
siteName: "CodedDevs Technology LTD",
30+
type: "website",
31+
},
32+
twitter: {
33+
card: "summary_large_image",
34+
title,
35+
description,
36+
},
37+
};
1138

1239
function formatType(type: Career["type"]) {
1340
return type
@@ -19,17 +46,22 @@ function formatType(type: Career["type"]) {
1946
async function getOpenRoles() {
2047
try {
2148
return await db
22-
.select()
49+
.select({
50+
id: careers.id,
51+
title: careers.title,
52+
type: careers.type,
53+
location: careers.location,
54+
description: careers.description,
55+
})
2356
.from(careers)
2457
.where(eq(careers.is_open, true))
2558
.orderBy(desc(careers.created_at));
26-
} catch (error) {
27-
console.error("Failed to fetch open roles", error);
59+
} catch {
2860
return [];
2961
}
3062
}
3163

32-
function RoleCard({ role }: { role: Career }) {
64+
function RoleCard({ role }: { role: OpenRole }) {
3365
return (
3466
<Card>
3567
<article className="space-y-6">

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
1+
import type { Metadata } from "next";
12
import ContactForm from "@/components/contact/ContactForm";
23

4+
export const revalidate = 3600;
5+
6+
const title = "Contact — CodedDevs Technology LTD";
7+
const description =
8+
"Get in touch with the CodedDevs team. Partnerships, press, investment, and general enquiries.";
9+
10+
export const metadata: Metadata = {
11+
title,
12+
description,
13+
openGraph: {
14+
title,
15+
description,
16+
url: "https://codeddevs.com/contact",
17+
siteName: "CodedDevs Technology LTD",
18+
type: "website",
19+
},
20+
twitter: {
21+
card: "summary_large_image",
22+
title,
23+
description,
24+
},
25+
};
26+
327
const socialLinks = [
428
{
529
label: "GitHub",

src/app/(public)/page.tsx

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,71 @@
1+
import type { Metadata } from "next";
12
import { desc, eq } from "drizzle-orm";
23
import HeroSection from "@/components/sections/HeroSection";
34
import HackathonStrip from "@/components/sections/HackathonStrip";
45
import LatestReleasesSection from "@/components/sections/LatestReleasesSection";
56
import ProductsSection from "@/components/sections/ProductsSection";
67
import { blogPosts, db, products } from "@/db";
78

8-
export const dynamic = "force-dynamic";
9+
export const revalidate = 3600;
10+
11+
const title = "CodedDevs Technology LTD";
12+
const description =
13+
"Engineering software that works for Africa. AI-first products built for African markets from first principles.";
14+
15+
export const metadata: Metadata = {
16+
title,
17+
description,
18+
openGraph: {
19+
title,
20+
description,
21+
url: "https://codeddevs.com",
22+
siteName: "CodedDevs Technology LTD",
23+
type: "website",
24+
},
25+
twitter: {
26+
card: "summary_large_image",
27+
title,
28+
description,
29+
},
30+
};
931

1032
async function getFeaturedProducts() {
1133
try {
1234
return await db
13-
.select()
35+
.select({
36+
id: products.id,
37+
name: products.name,
38+
slug: products.slug,
39+
tagline: products.tagline,
40+
cover_url: products.cover_url,
41+
external_url: products.external_url,
42+
status: products.status,
43+
is_featured: products.is_featured,
44+
})
1445
.from(products)
1546
.where(eq(products.is_featured, true))
1647
.orderBy(products.order_index);
17-
} catch (error) {
18-
console.error("Failed to fetch featured products", error);
48+
} catch {
1949
return [];
2050
}
2151
}
2252

2353
async function getLatestPosts() {
2454
try {
2555
return await db
26-
.select()
56+
.select({
57+
id: blogPosts.id,
58+
title: blogPosts.title,
59+
slug: blogPosts.slug,
60+
excerpt: blogPosts.excerpt,
61+
category: blogPosts.category,
62+
published_at: blogPosts.published_at,
63+
})
2764
.from(blogPosts)
2865
.where(eq(blogPosts.is_published, true))
2966
.orderBy(desc(blogPosts.published_at))
3067
.limit(3);
31-
} catch (error) {
32-
console.error("Failed to fetch latest posts", error);
68+
} catch {
3369
return [];
3470
}
3571
}

0 commit comments

Comments
 (0)