From f6252a217eebef52c4257e4465653e78ab561be9 Mon Sep 17 00:00:00 2001 From: Hari Nugraha Date: Thu, 29 Jan 2026 13:14:24 +0700 Subject: [PATCH 1/2] fix: case study does not appear on home and service page --- .../[slug]/components/content.tsx | 31 +- .../(hyperjump)/case-studies/[slug]/page.tsx | 16 +- app/[lang]/(hyperjump)/case-studies/data.ts | 63 ---- app/[lang]/(hyperjump)/case-studies/page.tsx | 59 +--- .../components/case-study-card.tsx | 43 +++ app/[lang]/(hyperjump)/data.ts | 156 ++++++--- app/[lang]/(hyperjump)/page.tsx | 32 +- .../(hyperjump)/services/[slug]/page.tsx | 46 +-- .../team-card.tsx => team/card.tsx} | 32 +- app/[lang]/(hyperjump)/team/data.ts | 302 +++++++++--------- app/[lang]/(hyperjump)/team/page.tsx | 46 ++- app/components/grid-items.tsx | 74 +---- app/llms.txt/route.ts | 4 +- e2e/case-study-detail.spec.ts | 2 +- e2e/homepage.spec.ts | 4 +- locales/en/case-studies/fisheries.mdx | 4 +- locales/en/case-study.json | 7 +- locales/en/main.json | 8 +- locales/id/case-studies/fisheries.mdx | 2 +- locales/id/case-study.json | 3 - locales/id/main.json | 8 +- 21 files changed, 435 insertions(+), 507 deletions(-) delete mode 100644 app/[lang]/(hyperjump)/case-studies/data.ts create mode 100644 app/[lang]/(hyperjump)/components/case-study-card.tsx rename app/[lang]/(hyperjump)/{components/team-card.tsx => team/card.tsx} (72%) diff --git a/app/[lang]/(hyperjump)/case-studies/[slug]/components/content.tsx b/app/[lang]/(hyperjump)/case-studies/[slug]/components/content.tsx index b29aff160..350437d5d 100644 --- a/app/[lang]/(hyperjump)/case-studies/[slug]/components/content.tsx +++ b/app/[lang]/(hyperjump)/case-studies/[slug]/components/content.tsx @@ -8,31 +8,32 @@ import { CaseStudiesVolunteeringPlatform } from "@/locales/.generated/locales-markdown"; import type { SupportedLanguage } from "@/locales/.generated/types"; +import { CaseStudySlug } from "../../../data"; type ContentProps = { lang: SupportedLanguage; slug: string; }; -const caseStudies = [ - { - slug: "erp-fisheries", - content: CaseStudiesFisheries - }, - { - slug: "ctoaas-media", - content: CaseStudiesMedia - }, - { - slug: "saas-volunteering-platform", - content: CaseStudiesVolunteeringPlatform - } -]; - export function Content({ lang, slug }: ContentProps) { + const caseStudies = [ + { + slug: CaseStudySlug.Fisheries, + content: CaseStudiesFisheries + }, + { + slug: CaseStudySlug.Media, + content: CaseStudiesMedia + }, + { + slug: CaseStudySlug.VolunteeringPlatform, + content: CaseStudiesVolunteeringPlatform + } + ]; const caseStudy = caseStudies.find((caseStudy) => caseStudy.slug === slug); if (!caseStudy) { + console.error(`Case study content for "${slug}" is not registered.`); notFound(); } diff --git a/app/[lang]/(hyperjump)/case-studies/[slug]/page.tsx b/app/[lang]/(hyperjump)/case-studies/[slug]/page.tsx index 120d7e4f5..87f90dd81 100644 --- a/app/[lang]/(hyperjump)/case-studies/[slug]/page.tsx +++ b/app/[lang]/(hyperjump)/case-studies/[slug]/page.tsx @@ -15,8 +15,12 @@ import { import type { SupportedLanguage } from "@/locales/.generated/types"; import { supportedLanguages } from "@/locales/.generated/types"; -import type { CaseStudy } from "../../data"; -import { caseStudyBy, getCaseStudies } from "../data"; +import { + caseStudyBy, + getCaseStudies, + serviceBySlug, + type CaseStudy +} from "../../data"; import { Content } from "./components/content"; type Params = { lang: SupportedLanguage; slug: string }; @@ -30,7 +34,7 @@ export async function generateMetadata({ }: CaseStudyProps): Promise { const { lang, slug } = await params; const { url } = data; - const caseStudies = caseStudyBy(slug, lang); + const caseStudies = caseStudyBy({ lang, slug }); const meta: Metadata = { title: `Case-Studies - ${caseStudies?.title ?? ""}`, description: caseStudies?.description ?? "", @@ -60,7 +64,7 @@ export async function generateStaticParams(): Promise { export default async function CaseStudy({ params }: CaseStudyProps) { const { lang, slug } = await params; - const caseStudy = caseStudyBy(slug, lang); + const caseStudy = caseStudyBy({ lang, slug }); if (!caseStudy) { notFound(); } @@ -140,13 +144,13 @@ function Recommendation({ caseStudies, lang }: RecommendationProps) { {caseStudyMore(lang)}
- {caseStudies.map(({ description, slug, title, category }) => ( + {caseStudies.map(({ description, serviceSlug, slug, title }) => (
- {category} + {serviceBySlug({ lang, slug: serviceSlug })?.title}

{title} diff --git a/app/[lang]/(hyperjump)/case-studies/data.ts b/app/[lang]/(hyperjump)/case-studies/data.ts deleted file mode 100644 index f74492ab8..000000000 --- a/app/[lang]/(hyperjump)/case-studies/data.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { - caseStudyCtoaasMediaCategory, - caseStudyCtoaasMediaDesc, - caseStudyCtoaasMediaTitle, - caseStudyErpFisheriesCategory, - caseStudyErpFisheriesDesc, - caseStudyErpFisheriesTitle, - caseStudyCtoaasMediaCtaHeading, - caseStudyCtoaasMediaCtaLabel, - caseStudyCtoaasMediaCtaSubject, - caseStudyErpFisheriesCtaHeading, - caseStudyErpFisheriesCtaLabel, - caseStudyErpFisheriesCtaSubject, - caseStudySaasVolunteeringPlatformTitle, - caseStudySaasVolunteeringPlatformDesc, - caseStudySaasVolunteeringPlatformCategory, - caseStudySaasVolunteeringPlatformCtaHeading, - caseStudySaasVolunteeringPlatformCtaSubject, - caseStudySaasVolunteeringPlatformCtaLabel -} from "@/locales/.generated/server"; -import type { SupportedLanguage } from "@/locales/.generated/types"; - -export const getCaseStudies = (lang: SupportedLanguage) => { - return [ - { - slug: "erp-fisheries", - title: caseStudyErpFisheriesTitle(lang), - description: caseStudyErpFisheriesDesc(lang), - category: caseStudyErpFisheriesCategory(lang), - cta: { - heading: caseStudyErpFisheriesCtaHeading(lang), - subject: caseStudyErpFisheriesCtaSubject(lang), - label: caseStudyErpFisheriesCtaLabel(lang) - } - }, - { - slug: "ctoaas-media", - title: caseStudyCtoaasMediaTitle(lang), - description: caseStudyCtoaasMediaDesc(lang), - category: caseStudyCtoaasMediaCategory(lang), - cta: { - heading: caseStudyCtoaasMediaCtaHeading(lang), - subject: caseStudyCtoaasMediaCtaSubject(lang), - label: caseStudyCtoaasMediaCtaLabel(lang) - } - }, - { - slug: "saas-volunteering-platform", - title: caseStudySaasVolunteeringPlatformTitle(lang), - description: caseStudySaasVolunteeringPlatformDesc(lang), - category: caseStudySaasVolunteeringPlatformCategory(lang), - cta: { - heading: caseStudySaasVolunteeringPlatformCtaHeading(lang), - subject: caseStudySaasVolunteeringPlatformCtaSubject(lang), - label: caseStudySaasVolunteeringPlatformCtaLabel(lang) - } - } - ]; -}; - -export function caseStudyBy(slug: string, lang: SupportedLanguage) { - return getCaseStudies(lang).find((cs) => cs.slug === slug); -} diff --git a/app/[lang]/(hyperjump)/case-studies/page.tsx b/app/[lang]/(hyperjump)/case-studies/page.tsx index efa3828e7..26a2c31a8 100644 --- a/app/[lang]/(hyperjump)/case-studies/page.tsx +++ b/app/[lang]/(hyperjump)/case-studies/page.tsx @@ -1,8 +1,6 @@ -import Link from "next/link"; import type { Metadata } from "next"; import { Hero } from "@/app/components/hero"; -import { Button } from "@/components/ui/button"; import data from "@/data.json"; import { dynamicOpengraph } from "@/lib/default-metadata"; import { @@ -10,14 +8,14 @@ import { type SupportedLanguage } from "@/locales/.generated/types"; import { - caseStudyButton, caseStudyExplore, caseStudyHeroDesc, caseStudyHeroHeading, caseStudyTitle } from "@/locales/.generated/strings"; -import { getCaseStudies } from "./data"; +import { getCaseStudies } from "../data"; +import { CaseStudyCard } from "../components/case-study-card"; export const generateStaticParams = async () => { return supportedLanguages.map((lang) => ({ lang })); @@ -63,47 +61,20 @@ export default async function CaseStudiesPage({ params }: CaseStudyProps) {

{caseStudyExplore(lang)}

- +
+
+
+ {getCaseStudies(lang).map((caseStudy) => ( + + ))} +
+
+
); } - -function CaseStudies({ lang }: { lang: SupportedLanguage }) { - return ( -
-
-
- {getCaseStudies(lang).map( - ({ category, description, slug, title }) => ( -
-
- - {category} - -

- {title} -

-

- {description} -

-
- - -
- ) - )} -
-
-
- ); -} diff --git a/app/[lang]/(hyperjump)/components/case-study-card.tsx b/app/[lang]/(hyperjump)/components/case-study-card.tsx new file mode 100644 index 000000000..b8e3f623c --- /dev/null +++ b/app/[lang]/(hyperjump)/components/case-study-card.tsx @@ -0,0 +1,43 @@ +import Link from "next/link"; + +import { Button } from "@/components/ui/button"; +import { caseStudyButton } from "@/locales/.generated/strings"; +import type { SupportedLanguage } from "@/locales/.generated/types"; + +import type { CaseStudy } from "../data"; +import { serviceBySlug } from "../data"; + +type CaseStudyCardProps = { + caseStudy: CaseStudy; + lang: SupportedLanguage; +}; + +export function CaseStudyCard({ + caseStudy: { description, serviceSlug, slug, title, url }, + lang +}: CaseStudyCardProps) { + return ( +
+
+ + {serviceBySlug({ lang, slug: serviceSlug })?.title} + +

+ {title} +

+

+ {description} +

+
+ + +
+ ); +} diff --git a/app/[lang]/(hyperjump)/data.ts b/app/[lang]/(hyperjump)/data.ts index d62a5c019..3fa7dc30b 100644 --- a/app/[lang]/(hyperjump)/data.ts +++ b/app/[lang]/(hyperjump)/data.ts @@ -57,12 +57,21 @@ import { aiWhyUsReasons0, aiWhyUsReasons1, aiWhyUsReasons2, - caseStudyCtoaasMediaCategory, + caseStudyCtoaasMediaCtaHeading, + caseStudyCtoaasMediaCtaLabel, + caseStudyCtoaasMediaCtaSubject, caseStudyCtoaasMediaDesc, caseStudyCtoaasMediaTitle, - caseStudyErpFisheriesCategory, + caseStudyErpFisheriesCtaHeading, + caseStudyErpFisheriesCtaLabel, + caseStudyErpFisheriesCtaSubject, caseStudyErpFisheriesDesc, caseStudyErpFisheriesTitle, + caseStudySaasVolunteeringPlatformCtaHeading, + caseStudySaasVolunteeringPlatformCtaLabel, + caseStudySaasVolunteeringPlatformCtaSubject, + caseStudySaasVolunteeringPlatformDesc, + caseStudySaasVolunteeringPlatformTitle, ctoaasBestFor, ctoaasDescription, ctoaasHeroDesc, @@ -161,12 +170,6 @@ import { erpWhyUsReasons0, erpWhyUsReasons1, erpWhyUsReasons2, - mainCaseStudies0Category, - mainCaseStudies0Text, - mainCaseStudies0Title, - mainCaseStudies1Category, - mainCaseStudies1Text, - mainCaseStudies1Title, mainFaq0Answer, mainFaq0Question, mainFaq1Answer, @@ -276,23 +279,91 @@ import { tddWhyUsReasons2 } from "@/locales/.generated/strings"; -export function getCaseStudies(lang: SupportedLanguage) { +export enum ServiceSlug { + InferenceAI = "inference-ai", + ErpImplementation = "erp-implementation", + CtoAsAService = "cto-as-a-service", + SoftwareAsAService = "software-as-a-service", + TechDueDiligence = "tech-due-diligence" +} + +export type CaseStudy = { + cta: { + heading: string; + subject: string; + label: string; + }; + description: string; + serviceSlug: ServiceSlug; + slug: string; + title: string; + url: string; +}; + +export enum CaseStudySlug { + Fisheries = "erp-fisheries", + Media = "ctoaas-media", + VolunteeringPlatform = "saas-volunteering-platform" +} + +export function getCaseStudies(lang: SupportedLanguage): CaseStudy[] { + const BASE_PATH = `/${lang}/case-studies`; return [ { - title: mainCaseStudies0Title(lang), - category: mainCaseStudies0Category(lang), - description: mainCaseStudies0Text(lang), - urlCaseStudy: `/${lang}/case-studies/erp-fisheries` + cta: { + heading: caseStudyErpFisheriesCtaHeading(lang), + subject: caseStudyErpFisheriesCtaSubject(lang), + label: caseStudyErpFisheriesCtaLabel(lang) + }, + description: caseStudyErpFisheriesDesc(lang), + serviceSlug: ServiceSlug.CtoAsAService, + slug: CaseStudySlug.Fisheries, + title: caseStudyErpFisheriesTitle(lang), + url: `${BASE_PATH}/${CaseStudySlug.Fisheries}` + }, + { + cta: { + heading: caseStudyCtoaasMediaCtaHeading(lang), + subject: caseStudyCtoaasMediaCtaSubject(lang), + label: caseStudyCtoaasMediaCtaLabel(lang) + }, + description: caseStudyCtoaasMediaDesc(lang), + serviceSlug: ServiceSlug.CtoAsAService, + slug: CaseStudySlug.Media, + title: caseStudyCtoaasMediaTitle(lang), + url: `${BASE_PATH}/${CaseStudySlug.Media}` }, { - title: mainCaseStudies1Title(lang), - category: mainCaseStudies1Category(lang), - description: mainCaseStudies1Text(lang), - urlCaseStudy: `/${lang}/case-studies/ctoaas-media` + cta: { + heading: caseStudySaasVolunteeringPlatformCtaHeading(lang), + subject: caseStudySaasVolunteeringPlatformCtaSubject(lang), + label: caseStudySaasVolunteeringPlatformCtaLabel(lang) + }, + description: caseStudySaasVolunteeringPlatformDesc(lang), + serviceSlug: ServiceSlug.SoftwareAsAService, + slug: CaseStudySlug.VolunteeringPlatform, + title: caseStudySaasVolunteeringPlatformTitle(lang), + url: `${BASE_PATH}/${CaseStudySlug.VolunteeringPlatform}` } ]; } +type CaseStudyByParams = { + lang: SupportedLanguage; + slug: string; +}; + +export function caseStudyBy({ lang, slug }: CaseStudyByParams) { + return getCaseStudies(lang).find((cs) => cs.slug === slug); +} + +function caseStudyByService({ + lang, + slug +}: ServiceBySlugParameters): CaseStudy[] { + return getCaseStudies(lang).filter((cs) => cs.serviceSlug === slug); +} + export function getFaqs(lang: SupportedLanguage) { return [ { @@ -386,22 +457,6 @@ type Content = { }[]; }; -export enum ServiceSlug { - InferenceAI = "inference-ai", - ErpImplementation = "erp-implementation", - CtoAsAService = "cto-as-a-service", - SoftwareAsAService = "software-as-a-service", - TechDueDiligence = "tech-due-diligence" -} - -export type CaseStudy = { - slug: string; - title: string; - description: string; - category: string; - basePath?: string; -}; - export type Service = { bestFor: string[]; caseStudies: CaseStudy[]; @@ -526,7 +581,10 @@ export function services(lang: SupportedLanguage): Service[] { shortDescription: aiHeroDesc(lang), slug: ServiceSlug.InferenceAI, title: aiHeroHeading(lang), - caseStudies: [], + caseStudies: caseStudyByService({ + lang, + slug: ServiceSlug.InferenceAI + }), faqs: [ { question: aiFaq0Question(lang), answer: aiFaq0Answer(lang) }, { question: aiFaq1Question(lang), answer: aiFaq1Answer(lang) }, @@ -787,22 +845,10 @@ export function services(lang: SupportedLanguage): Service[] { shortDescription: ctoaasHeroDesc(lang), slug: ServiceSlug.CtoAsAService, title: ctoaasHeroHeading(lang), - caseStudies: [ - { - slug: "erp-fisheries", - title: caseStudyErpFisheriesTitle(lang), - description: caseStudyErpFisheriesDesc(lang), - category: caseStudyErpFisheriesCategory(lang), - basePath: "case-studies" - }, - { - slug: "ctoaas-media", - title: caseStudyCtoaasMediaTitle(lang), - description: caseStudyCtoaasMediaDesc(lang), - category: caseStudyCtoaasMediaCategory(lang), - basePath: "case-studies" - } - ], + caseStudies: caseStudyByService({ + lang, + slug: ServiceSlug.CtoAsAService + }), faqs: [] }, { @@ -909,7 +955,10 @@ export function services(lang: SupportedLanguage): Service[] { shortDescription: saasHeroDesc(lang), slug: ServiceSlug.SoftwareAsAService, title: saasHeroHeading(lang), - caseStudies: [], + caseStudies: caseStudyByService({ + lang, + slug: ServiceSlug.SoftwareAsAService + }), faqs: [] }, { @@ -1040,7 +1089,10 @@ export function services(lang: SupportedLanguage): Service[] { shortDescription: tddHeroDesc(lang), slug: ServiceSlug.TechDueDiligence, title: tddHeroHeading(lang), - caseStudies: [], + caseStudies: caseStudyByService({ + lang, + slug: ServiceSlug.TechDueDiligence + }), faqs: [] } ]; diff --git a/app/[lang]/(hyperjump)/page.tsx b/app/[lang]/(hyperjump)/page.tsx index d67abb575..e4265d13d 100644 --- a/app/[lang]/(hyperjump)/page.tsx +++ b/app/[lang]/(hyperjump)/page.tsx @@ -1,8 +1,14 @@ +import { ArrowRightIcon } from "lucide-react"; import type { Metadata } from "next"; import Image from "next/image"; import Link from "next/link"; import type { Organization, WebPage, WithContext } from "schema-dts"; +import GridItemsContainer, { + GridItems, + GridItemsMoreButton, + GridItemsTitle +} from "@/app/components/grid-items"; import { Accordion, AccordionContent, @@ -16,12 +22,8 @@ import { CardFooter, CardHeader } from "@/components/ui/card"; -import GridItemsContainer, { - GridItems, - GridItemsMoreButton, - GridItemsTitle -} from "@/app/components/grid-items"; import data from "@/data.json"; +import { dynamicOpengraph } from "@/lib/default-metadata"; import { supportedLanguages, type SupportedLanguage @@ -42,7 +44,7 @@ import { mainCaseStudiesCtaExploreOurCaseStudies, mainHeroHeading, mainFaqLearnMore -} from "@/locales/.generated/server"; +} from "@/locales/.generated/strings"; import { Clients } from "./components/clients"; import { Location } from "./components/location"; @@ -53,8 +55,7 @@ import { pageData, services } from "./data"; -import { dynamicOpengraph } from "@/lib/default-metadata"; -import { ArrowRightIcon } from "lucide-react"; +import { CaseStudyCard } from "./components/case-study-card"; const { github, socials, title, url } = data; @@ -181,12 +182,15 @@ function CaseStudies({ lang }: HomeParams) { title={mainCaseStudiesHeading(lang)} description={mainCaseStudiesDesc(lang)} /> - +
+ {getCaseStudies(lang).map((caseStudy) => ( + + ))} +
- + ); @@ -422,13 +422,15 @@ function WhyUs({ lang, service }: LangProps & ServiceProps) { ); } -type RecommendationProps = { +type CaseStudyProps = { caseStudies: CaseStudy[]; lang: SupportedLanguage; }; -function Recommendation({ caseStudies, lang }: RecommendationProps) { - if (caseStudies.length === 0) return null; +function CaseStudies({ caseStudies, lang }: CaseStudyProps) { + if (caseStudies.length === 0) { + return null; + } return (
@@ -437,33 +439,13 @@ function Recommendation({ caseStudies, lang }: RecommendationProps) { {servicesCaseStudies(lang)}
- {caseStudies.map( - ({ category, description, slug, title, basePath }) => ( -
-
- - {category} - -

- {title} -

-

- {description} -

-
- -
- ) - )} + {caseStudies.map((caseStudy) => ( + + ))}
diff --git a/app/[lang]/(hyperjump)/components/team-card.tsx b/app/[lang]/(hyperjump)/team/card.tsx similarity index 72% rename from app/[lang]/(hyperjump)/components/team-card.tsx rename to app/[lang]/(hyperjump)/team/card.tsx index cb511a654..e2a443993 100644 --- a/app/[lang]/(hyperjump)/components/team-card.tsx +++ b/app/[lang]/(hyperjump)/team/card.tsx @@ -1,26 +1,19 @@ import Image from "next/image"; +import type { Team } from "./data"; -interface TeamCardProps { - variant?: "featured" | "compact"; - name: string; - role: string; - image?: string; - description: string; - linkedIn?: string; -} +type TeamCardProps = { + variant: "featured" | "compact"; +} & Team; const FALLBACK_IMAGE = "/images/no-user-image.webp"; -const CARD_HEIGHT_FEATURED = 680; -const CARD_HEIGHT_COMPACT = 640; - export function TeamCard({ - variant = "compact", + description, + image, + linkedIn, name, role, - image, - description, - linkedIn + variant }: TeamCardProps) { const isFeatured = variant === "featured"; const imageSrc = image && image.trim() !== "" ? image : FALLBACK_IMAGE; @@ -28,10 +21,10 @@ export function TeamCard({ return (
+ className={`flex h-auto flex-col rounded-xl bg-white shadow-sm transition-shadow duration-300 hover:shadow-lg ${isFeatured ? "md:h-170" : "md:h-160"} `}>
@@ -66,7 +60,7 @@ export function TeamCard({ className="mt-4 inline-flex h-9 w-9 items-center justify-center rounded-full border border-[#73767E] text-[#73767E] transition-colors hover:border-[#a1cfff] hover:bg-[#a1cfff]"> LinkedIn diff --git a/app/[lang]/(hyperjump)/team/data.ts b/app/[lang]/(hyperjump)/team/data.ts index b338fc59b..e9252dbb8 100644 --- a/app/[lang]/(hyperjump)/team/data.ts +++ b/app/[lang]/(hyperjump)/team/data.ts @@ -1,148 +1,154 @@ -export function getTeams() { - return [ - { - name: "Ari Awan", - role: "Co-founder & CEO", - image: "1763184214507.jpeg", - description: - "Jack-of-all-trade in technology startups. Experienced in software engineering (20+ years of hands-on web/mobile programming), product management, operation, fundraising, and marketing.", - linkedIn: "https://www.linkedin.com/in/ariawan/" - }, - { - name: "Ariya Hidayat", - role: "Co-founder & CTO", - image: "1689492669383.jpeg", - description: - "Experienced technology leader operating at the intersection of enterprise products and open-source software, with deep hands-on experience across diverse technology stacks.", - linkedIn: "https://www.linkedin.com/in/ariyahidayat/" - }, - { - name: "Satriyo Pranoto", - role: "Head of Product", - image: "1517052947097.jpeg", - description: - "Senior IT and project management professional with 20+ years of experience delivering enterprise and digital products across multiple industries.", - linkedIn: "https://www.linkedin.com/in/satriyo-pranoto-2b1935122/" - }, - { - name: "Zulfahmi Andri", - role: "Principle Software Architect", - image: "1610507885667.jpeg", - description: - "Enterprise software professional with 20+ years of experience, specializing in API-driven systems, mobile applications, and modern cloud architectures.", - linkedIn: "https://www.linkedin.com/in/zulfahmi-andri/" - }, - { - name: "Ferdi Ramdhon", - role: "Head Of Development", - image: "1517464706587.jpeg", - description: - "A full-stack specialist with 10,000+ hours of experience across Java, Python, Go, and React. Expertise spans Android development, SQL/NoSQL databases, and Agile SDLC, focused on delivering scalable software architectures and high-performance RESTful APIs.", - linkedIn: "https://id.linkedin.com/in/ferdirn" - }, - { - name: "Nico Prananta", - role: "Principal Developer", - image: "1636610990869.jpeg", - description: - "Principal software developer with experience leading engineering teams and delivering modern web applications across multiple industries.", - linkedIn: "https://www.linkedin.com/in/nico-prananta-884750200/" - }, - { - name: "Amri S. Pangestu", - role: "Product Manager", - image: "1607277533248.jpeg", - description: - "Product & IT Project Manager with experience in digital agencies, e-grocery, and consulting, driving product growth through strategy, execution, and technology.", - linkedIn: "https://www.linkedin.com/in/amripangestu/" - }, - { - name: "Hari Cahya Nugraha", - role: "Software Engineer", - image: "1606819371215.jpeg", - description: - "Full-stack software engineer with 10+ years of experience building scalable web systems, specializing in backend, infrastructure, and cloud-native architectures.", - linkedIn: "https://www.linkedin.com/in/haricnugraha/" - }, - { - name: "Muslim Ilmiawan", - role: "Software Engineer", - image: "1558886084532.jpeg", - description: - "Backend-focused programmer passionate about system architecture, working mainly with Java, Go, and Node.js.", - linkedIn: "https://www.linkedin.com/in/muslimilmiawan/" - }, - { - name: "Denny Pradipta", - role: "Software Engineer", - image: "1758856751506.jpeg", - description: - "Experienced full-stack web developer with 8+ years of experience working across frontend, backend, and DevOps with modern JavaScript technologies.", - linkedIn: "https://www.linkedin.com/in/dennypradipta/" - }, - { - name: "Raosan Lillahi", - role: "Software Engineer", - image: "1679995906768.jpeg", - description: - "Software engineer with extensive full-stack experience, startup founding background, and strong interest in technology and business.", - linkedIn: "https://www.linkedin.com/in/raosanfikri/" - }, - { - name: "Suyono", - role: "Senior Software Engineer", - image: "1516414668719.jpeg", - description: - "Senior software engineer with 13+ years of experience, passionate about open-source, scalable architectures, and building high-quality products.", - linkedIn: "https://www.linkedin.com/in/suyono/" - }, - { - name: "Kevin Hermawan", - role: "Software Engineer", - image: "1760315021833.jpeg", - description: - "Experienced software engineer focused on frontend, system reliability, and AI-driven solutions, with hands-on work in LLMs, RAG, and monitoring tools.", - linkedIn: "https://www.linkedin.com/in/khermawan/" - }, - { - name: "Budhi Widagdo", - role: "Software Engineer", - image: "1602615800537.jpeg", - description: - "Experienced software engineer with a background in open-source development, digital banking platforms, and leading multi-project engineering teams.", - linkedIn: "https://www.linkedin.com/in/budhi-widagdo/" - }, - { - name: "Sinta Herena", - role: "Software Engineer", - image: "1765007375648.jpeg", - description: - "Full-stack JavaScript developer experienced in React, Next.js, and TypeScript, focused on building reliable, user-centric web applications.", - linkedIn: "https://www.linkedin.com/in/sinta-herena/" - }, - { - name: "Lukman Adisaputro", - role: "Software Engineer", - image: "1635918474641.jpeg", - description: - "Software developer with experience across startups and media companies, specializing in Go backend systems and modern web development with React.", - linkedIn: "https://www.linkedin.com/in/lukman-adisaputro-4a8969214/" - }, - { - name: "M Noor Syam", - role: "Software Engineer", - image: "1750253962765.jpeg", - description: - "Software engineer with 10+ years of experience in Android and full-stack web development, delivering MVPs and scalable, production-ready systems.", - linkedIn: "https://www.linkedin.com/in/mochamad-noor-syamsu-832617a5/" - }, - { - name: "Harianto", - role: "Head of Business Development", - image: "1699844064993.jpeg", - description: - "Business development executive driving long-term growth through strategy, partnerships, and commercial execution.", - linkedIn: "https://www.linkedin.com/in/h-harianto-7493799b/" - } - ]; -} +export type Team = { + name: string; + role: string; + image: string; + description: string; + linkedIn: string; +}; + +export const team: Team[] = [ + { + name: "Ari Awan", + role: "Co-founder & CEO", + image: "1763184214507.jpeg", + description: + "Jack-of-all-trade in technology startups. Experienced in software engineering (20+ years of hands-on web/mobile programming), product management, operation, fundraising, and marketing.", + linkedIn: "https://www.linkedin.com/in/ariawan/" + }, + { + name: "Ariya Hidayat", + role: "Co-founder & CTO", + image: "1689492669383.jpeg", + description: + "Experienced technology leader operating at the intersection of enterprise products and open-source software, with deep hands-on experience across diverse technology stacks.", + linkedIn: "https://www.linkedin.com/in/ariyahidayat/" + }, + { + name: "Satriyo Pranoto", + role: "Head of Product", + image: "1517052947097.jpeg", + description: + "Senior IT and project management professional with 20+ years of experience delivering enterprise and digital products across multiple industries.", + linkedIn: "https://www.linkedin.com/in/satriyo-pranoto-2b1935122/" + }, + { + name: "Zulfahmi Andri", + role: "Principle Software Architect", + image: "1610507885667.jpeg", + description: + "Enterprise software professional with 20+ years of experience, specializing in API-driven systems, mobile applications, and modern cloud architectures.", + linkedIn: "https://www.linkedin.com/in/zulfahmi-andri/" + }, + { + name: "Ferdi Ramdhon", + role: "Head Of Development", + image: "1517464706587.jpeg", + description: + "A full-stack specialist with 10,000+ hours of experience across Java, Python, Go, and React. Expertise spans Android development, SQL/NoSQL databases, and Agile SDLC, focused on delivering scalable software architectures and high-performance RESTful APIs.", + linkedIn: "https://id.linkedin.com/in/ferdirn" + }, + { + name: "Nico Prananta", + role: "Principal Developer", + image: "1636610990869.jpeg", + description: + "Principal software developer with experience leading engineering teams and delivering modern web applications across multiple industries.", + linkedIn: "https://www.linkedin.com/in/nico-prananta-884750200/" + }, + { + name: "Amri S. Pangestu", + role: "Product Manager", + image: "1607277533248.jpeg", + description: + "Product & IT Project Manager with experience in digital agencies, e-grocery, and consulting, driving product growth through strategy, execution, and technology.", + linkedIn: "https://www.linkedin.com/in/amripangestu/" + }, + { + name: "Hari Cahya Nugraha", + role: "Software Engineer", + image: "1606819371215.jpeg", + description: + "Full-stack software engineer with 10+ years of experience building scalable web systems, specializing in backend, infrastructure, and cloud-native architectures.", + linkedIn: "https://www.linkedin.com/in/haricnugraha/" + }, + { + name: "Muslim Ilmiawan", + role: "Software Engineer", + image: "1558886084532.jpeg", + description: + "Backend-focused programmer passionate about system architecture, working mainly with Java, Go, and Node.js.", + linkedIn: "https://www.linkedin.com/in/muslimilmiawan/" + }, + { + name: "Denny Pradipta", + role: "Software Engineer", + image: "1758856751506.jpeg", + description: + "Experienced full-stack web developer with 8+ years of experience working across frontend, backend, and DevOps with modern JavaScript technologies.", + linkedIn: "https://www.linkedin.com/in/dennypradipta/" + }, + { + name: "Raosan Lillahi", + role: "Software Engineer", + image: "1679995906768.jpeg", + description: + "Software engineer with extensive full-stack experience, startup founding background, and strong interest in technology and business.", + linkedIn: "https://www.linkedin.com/in/raosanfikri/" + }, + { + name: "Suyono", + role: "Senior Software Engineer", + image: "1516414668719.jpeg", + description: + "Senior software engineer with 13+ years of experience, passionate about open-source, scalable architectures, and building high-quality products.", + linkedIn: "https://www.linkedin.com/in/suyono/" + }, + { + name: "Kevin Hermawan", + role: "Software Engineer", + image: "1760315021833.jpeg", + description: + "Experienced software engineer focused on frontend, system reliability, and AI-driven solutions, with hands-on work in LLMs, RAG, and monitoring tools.", + linkedIn: "https://www.linkedin.com/in/khermawan/" + }, + { + name: "Budhi Widagdo", + role: "Software Engineer", + image: "1602615800537.jpeg", + description: + "Experienced software engineer with a background in open-source development, digital banking platforms, and leading multi-project engineering teams.", + linkedIn: "https://www.linkedin.com/in/budhi-widagdo/" + }, + { + name: "Sinta Herena", + role: "Software Engineer", + image: "1765007375648.jpeg", + description: + "Full-stack JavaScript developer experienced in React, Next.js, and TypeScript, focused on building reliable, user-centric web applications.", + linkedIn: "https://www.linkedin.com/in/sinta-herena/" + }, + { + name: "Lukman Adisaputro", + role: "Software Engineer", + image: "1635918474641.jpeg", + description: + "Software developer with experience across startups and media companies, specializing in Go backend systems and modern web development with React.", + linkedIn: "https://www.linkedin.com/in/lukman-adisaputro-4a8969214/" + }, + { + name: "M Noor Syam", + role: "Software Engineer", + image: "1750253962765.jpeg", + description: + "Software engineer with 10+ years of experience in Android and full-stack web development, delivering MVPs and scalable, production-ready systems.", + linkedIn: "https://www.linkedin.com/in/mochamad-noor-syamsu-832617a5/" + }, + { + name: "Harianto", + role: "Head of Business Development", + image: "1699844064993.jpeg", + description: + "Business development executive driving long-term growth through strategy, partnerships, and commercial execution.", + linkedIn: "https://www.linkedin.com/in/h-harianto-7493799b/" + } +]; diff --git a/app/[lang]/(hyperjump)/team/page.tsx b/app/[lang]/(hyperjump)/team/page.tsx index 34678c4b0..7d7177cdc 100644 --- a/app/[lang]/(hyperjump)/team/page.tsx +++ b/app/[lang]/(hyperjump)/team/page.tsx @@ -1,38 +1,32 @@ -import type { Metadata } from "next"; import data from "@/data.json"; import { dynamicOpengraph } from "@/lib/default-metadata"; import { supportedLanguages, type SupportedLanguage } from "@/locales/.generated/types"; -import { TeamCard } from "../components/team-card"; -import { getTeams } from "./data"; import { mainTeamDesc, mainTeamHeading } from "@/locales/.generated/strings"; -export const generateStaticParams = async () => { - return supportedLanguages.map((lang) => ({ lang })); -}; -type TeamsProps = { - params: Promise<{ lang: SupportedLanguage }>; -}; +import { TeamCard } from "./card"; +import { team } from "./data"; export async function generateMetadata() { - const { title, description } = data; - - const meta: Metadata = { - title: `Meet Our Team – ${title}`, - description: description - }; + return dynamicOpengraph({ + title: `Meet Our Team - ${data.title}` + }); +} - return dynamicOpengraph(meta); +export async function generateStaticParams() { + return supportedLanguages.map((lang) => ({ lang })); } +type TeamsProps = { + params: Promise<{ lang: SupportedLanguage }>; +}; + export default async function TeamSection({ params }: TeamsProps) { const { lang } = await params; - const teams = getTeams(); - - const featuredTeams = teams.slice(0, 2); - const otherTeams = teams.slice(2); + const founders = team.slice(0, 2); + const members = team.slice(2); return (
@@ -47,15 +41,17 @@ export default async function TeamSection({ params }: TeamsProps) {
- {featuredTeams.map((member, i) => ( - + {founders.map((founder) => ( + ))}
- {otherTeams.map((member, i) => ( - - ))} + {members + .sort((a, b) => a.name.localeCompare(b.name)) + .map((member) => ( + + ))}
diff --git a/app/components/grid-items.tsx b/app/components/grid-items.tsx index e32ac2edb..193c214df 100644 --- a/app/components/grid-items.tsx +++ b/app/components/grid-items.tsx @@ -17,11 +17,7 @@ import { motion } from "framer-motion"; import React, { Children, isValidElement, useEffect, useState } from "react"; import { GitFork, Star } from "lucide-react"; import type { SupportedLanguage } from "@/locales/.generated/types"; -import { - mainCaseStudiesButton, - mainSeeMore, - productsLearnMore -} from "@/locales/.generated/server"; +import { mainSeeMore, productsLearnMore } from "@/locales/.generated/strings"; type GridItemsTitleProps = { id?: string; @@ -82,11 +78,9 @@ export type Item = { title: string; description: string; url?: string; - category?: string; icon?: string | React.ReactElement; button?: boolean; repo?: string; - urlCaseStudy?: string; urlSeeMore?: string; urlLearnMore?: string; repoUrl?: string; @@ -100,25 +94,19 @@ type Column = { xl?: number; }; +type GridItemsProps = { + items: Item[]; + columns?: Column; + cardClassName?: string; + lang: SupportedLanguage; +}; + export function GridItems({ items, columns = { base: 1, md: 2, xl: 3 }, - withCard = true, cardClassName = "border-[#D9D9D9] bg-white", - borderClassName = "", - categoryClassName = "bg-hyperjump-black/10 text-hyperjump-black", - titleClassName = "text-hyperjump-black", lang -}: { - items: Item[]; - cardClassName?: string; - columns?: Column; - withCard?: boolean; - borderClassName?: string; - categoryClassName?: string; - titleClassName?: string; - lang: SupportedLanguage; -}) { +}: GridItemsProps) { const [repoStats, setRepoStats] = useState< Record >({}); @@ -164,10 +152,6 @@ export function GridItems({ fetchRepoStats(); }, [items]); - const CardWrapper = withCard - ? Card - : ({ children }: { children: React.ReactNode }) =>
{children}
; - return (
{items.map((item, idx) => { @@ -176,10 +160,8 @@ export function GridItems({ title, description, url, - category, icon, button, - urlCaseStudy, urlSeeMore, urlLearnMore, repoUrl @@ -188,12 +170,11 @@ export function GridItems({ const isReactIcon = isValidElement(icon); const isStringIcon = typeof icon === "string"; return ( - {image && (
@@ -218,31 +199,14 @@ export function GridItems({ )} - {category && ( -

- {category} -

- )} {url ? ( - + {title} ) : ( - + {title} )} @@ -255,16 +219,6 @@ export function GridItems({ __html: description }} /> - - {urlCaseStudy && ( - - )} - {urlSeeMore && (
diff --git a/app/llms.txt/route.ts b/app/llms.txt/route.ts index b76f7ade9..c05b71c14 100644 --- a/app/llms.txt/route.ts +++ b/app/llms.txt/route.ts @@ -1,6 +1,6 @@ import { NextResponse } from "next/server"; import data from "@/data.json"; -import { mainOpenInGoogleMaps } from "@/locales/.generated/server"; +import { mainOpenInGoogleMaps } from "@/locales/.generated/strings"; import { getCommercialProduct, getOpenSource @@ -85,7 +85,7 @@ function serviceList() { function caseStudyList() { return getCaseStudies(LOCALE) .map( - ({ description, title, urlCaseStudy }) => + ({ description, title, url: urlCaseStudy }) => `- [${title}](${url}${urlCaseStudy}): ${description}` ) .join("\n"); diff --git a/e2e/case-study-detail.spec.ts b/e2e/case-study-detail.spec.ts index 80f5f68b9..1438449b1 100644 --- a/e2e/case-study-detail.spec.ts +++ b/e2e/case-study-detail.spec.ts @@ -1,6 +1,6 @@ import { test, expect, Page } from "@playwright/test"; -import { getCaseStudies } from "@/app/[lang]/(hyperjump)/case-studies/data"; import { imagesTest } from "./shared-test"; +import { getCaseStudies } from "@/app/[lang]/(hyperjump)/data"; // Base URL const baseURL = "http://localhost:3000"; diff --git a/e2e/homepage.spec.ts b/e2e/homepage.spec.ts index 4b1a73f4d..a0da6b97c 100644 --- a/e2e/homepage.spec.ts +++ b/e2e/homepage.spec.ts @@ -92,7 +92,9 @@ test.describe("Homepage", () => { for (const s of services) { await expect(page.getByText(s.desc)).toBeVisible(); await expect(page.getByRole("img", { name: s.title })).toBeVisible(); - await expect(page.getByText(s.title, { exact: true })).toBeVisible(); + await expect( + page.locator("#services").getByText(s.title, { exact: true }) + ).toBeVisible(); } // View more link diff --git a/locales/en/case-studies/fisheries.mdx b/locales/en/case-studies/fisheries.mdx index 19a0b490d..ca6384238 100644 --- a/locales/en/case-studies/fisheries.mdx +++ b/locales/en/case-studies/fisheries.mdx @@ -4,7 +4,7 @@ import Image from "next/image"; A growing fisheries startup faced a familiar challenge: a passionate but inexperienced tech team, inexperienced leadership, and a critical mission. Digitize Indonesia's fisheries supply chain from coast to customer. The stakes were high, but the potential impact was massive. -With no live product and a team just finding its feet, the company partnered with Hyperjump under a CTO-as-a-Service model to build strong technical foundations, processes, and culture. +With no live product and a team just finding its feet, the company partnered with Hyperjump under a **[CTO-as-a-Service](https://hyperjump.tech/id/services/cto-as-a-service)** model to build strong technical foundations, processes, and culture. ## The Challenge @@ -45,7 +45,7 @@ Working closely over 12 months, Hyperjump embedded with the product, engineering - QA isn't a department—it's a shared cultural commitment - Documentation is your secret weapon. A growing internal wiki and consistent Jira practices made onboarding and scaling smoother -## What’s Next +## What's Next The team is now stable and self-sufficient. The next challenge is to strengthen internal leadership and establish a long-term product roadmap to keep delivering value at scale. We're proud to have helped this fisheries company build not just software, but a high-performing tech organization that's ready to transform the industry. diff --git a/locales/en/case-study.json b/locales/en/case-study.json index 96f23c09c..f24bfd19a 100644 --- a/locales/en/case-study.json +++ b/locales/en/case-study.json @@ -16,7 +16,6 @@ "erp_fisheries": { "title": "Transforming a fisheries tech team into a scalable product engine", "desc": "A junior but passionate tech team. Zero products in production. High impact at stake. We embedded deeply with their team to introduce structure, build confidence, and ship a functional MVP within 3 months. Through rigorous agile practices and full-system rollouts, we helped evolve a fragile tech org into a reliable product engine.", - "category": "CTO as a Service", "cta": { "heading": "Ready to build your future? Let's discuss your transformation", "subject": "Media Transformation", @@ -26,7 +25,6 @@ "ctoaas_media": { "title": "Elevating a media-tech engineering team from feature factory to innovation powerhouse", "desc": "When rapid growth outpaced engineering maturity, this team needed more than features, they needed transformation. We restructured their agile practices, automated DevOps, established measurable KPIs, and helped them move from task execution to true product ownership and experimentation.", - "category": "CTO as a Service", "cta": { "heading": "Ready to transform your tech team? Let's talk about CTO-as-a-Service", "subject": "CTO as a Service", @@ -34,9 +32,8 @@ } }, "saas_volunteering_platform": { - "title": "Technology Migration and Website Revitalization for Indonesia’s Leading Volunteering Platform", - "desc": "Indonesia’s largest volunteering platform decided to update its outdated technology by migrating from Angular.js to React. As a nonprofit organization with limited budget, they found managing an in-house engineering team costly and difficult.", - "category": "Software as a Service", + "title": "Technology Migration and Website Revitalization for Indonesia's Leading Volunteering Platform", + "desc": "Indonesia's largest volunteering platform decided to update its outdated technology by migrating from Angular.js to React. As a nonprofit organization with limited budget, they found managing an in-house engineering team costly and difficult.", "cta": { "heading": "Ready to build high-quality software? Let's talk about Software as a Service", "subject": "Software as a Service", diff --git a/locales/en/main.json b/locales/en/main.json index 98107d824..585d6a15c 100644 --- a/locales/en/main.json +++ b/locales/en/main.json @@ -28,13 +28,7 @@ "case_studies": { "heading": "Case studies", "desc": "Discover how we successfully transform challenges into opportunities with real-world solutions that drive lasting impact and business growth.", - "button": "Read case study", - "0_title": "Transforming a fisheries tech team into a scalable product engine", - "0_text": "A junior but passionate tech team. Zero products in production. High impact at stake. We embedded deeply with their team to introduce structure, build confidence, and ship a functional MVP within 3 months. Through rigorous agile practices and full-system rollouts, we helped evolve a fragile tech org into a reliable product engine.", - "0_category": "CTO as a Service", - "1_title": "Elevating a media-tech engineering team from feature factory to innovation powerhouse", - "1_text": "When rapid growth outpaced engineering maturity, this team needed more than features, they needed transformation. We restructured their agile practices, automated DevOps, established measurable KPIs, and helped them move from task execution to true product ownership and experimentation.", - "1_category": "CTO as a Service" + "button": "Read case study" }, "project": { "heading": "Open source product", diff --git a/locales/id/case-studies/fisheries.mdx b/locales/id/case-studies/fisheries.mdx index b575f0e6e..7e2093efe 100644 --- a/locales/id/case-studies/fisheries.mdx +++ b/locales/id/case-studies/fisheries.mdx @@ -4,7 +4,7 @@ import Image from "next/image"; Sebuah startup perikanan yang sedang berkembang menghadapi tantangan yang cukup umum: tim teknologi yang bersemangat namun masih minim pengalaman, kepemimpinan yang belum matang, serta misi yang sangat krusial. Mendigitalisasi rantai pasok perikanan Indonesia dari pesisir hingga ke pelanggan akhir. Taruhannya tinggi, namun potensi dampaknya sangat besar. -Tanpa produk yang sudah berjalan dan dengan tim yang masih mencari pijakan, perusahaan ini bermitra dengan Hyperjump melalui model CTO-as-a-Service untuk membangun fondasi teknis yang kuat, proses kerja yang terstruktur, serta budaya engineering yang berkelanjutan. +Tanpa produk yang sudah berjalan dan dengan tim yang masih mencari pijakan, perusahaan ini bermitra dengan Hyperjump melalui model **[CTO-as-a-Service](https://hyperjump.tech/id/services/cto-as-a-service)** untuk membangun fondasi teknis yang kuat, proses kerja yang terstruktur, serta budaya engineering yang berkelanjutan. ## Tantangan diff --git a/locales/id/case-study.json b/locales/id/case-study.json index 006c48dc2..48ea897c7 100644 --- a/locales/id/case-study.json +++ b/locales/id/case-study.json @@ -16,7 +16,6 @@ "erp_fisheries": { "title": "Mengubah tim teknologi perikanan menjadi mesin produk yang skalabel", "desc": "Tim teknologi yang masih junior namun penuh semangat. Tidak ada produk yang berjalan. Taruhan dampak besar. Kami terjun langsung mendampingi tim mereka untuk membangun struktur, meningkatkan kepercayaan diri, dan meluncurkan MVP yang fungsional dalam 3 bulan. Lewat praktik agile yang ketat dan peluncuran sistem penuh, kami bantu mengubah organisasi teknologi yang rapuh menjadi mesin produk yang andal.", - "category": "CTO as a Service", "cta": { "heading": "Siap membangun masa depan Anda? Mari diskusikan transformasi Anda", "subject": "Transformasi Media", @@ -26,7 +25,6 @@ "ctoaas_media": { "title": "Meningkatkan tim engineering media dari pabrik fitur menjadi pusat inovasi", "desc": "Ketika pertumbuhan cepat melampaui kematangan engineering, tim ini butuh lebih dari sekadar fitur, mereka butuh transformasi. Kami restrukturisasi praktik agile mereka, otomatisasi DevOps, tetapkan KPI terukur, dan bantu mereka beralih dari eksekutor tugas ke pemilik produk sejati yang inovatif.", - "category": "CTO as a Service", "cta": { "heading": "Siap mentransformasi tim teknologi Anda? Mari berdiskusi tentang CTO-as-a-Service", "subject": "CTO sebagai Layanan", @@ -36,7 +34,6 @@ "saas_volunteering_platform": { "title": "Migrasi Teknologi dan Revitalisasi Situs Web untuk Platform Relawan Terkemuka di Indonesia", "desc": "Platform relawan terbesar di Indonesia memutuskan untuk memperbarui teknologi dengan berganti dari Angular.js ke React. Sebagai organisasi nirlaba dengan anggaran terbatas, mereka menemukan bahwa mengelola tim pengembangan internal mahal dan sulit.", - "category": "Software as a Service", "cta": { "heading": "Siap membangun perangkat lunak berkualitas tinggi? Mari berdiskusi tentang Software as a Service", "subject": "Software as a Service", diff --git a/locales/id/main.json b/locales/id/main.json index 82078fb3f..d21362af5 100644 --- a/locales/id/main.json +++ b/locales/id/main.json @@ -28,13 +28,7 @@ "case_studies": { "heading": "Studi kasus", "desc": "Temukan bagaimana kami berhasil mengubah tantangan menjadi peluang melalui solusi nyata yang mendorong dampak berkelanjutan dan pertumbuhan bisnis.", - "button": "Baca studi kasus", - "0_title": "Mengubah tim teknologi perikanan menjadi mesin produk yang skalabel", - "0_text": "Sebuah tim teknologi junior namun penuh semangat. Tidak ada produk yang sudah berjalan. Taruhannya besar. Kami terlibat secara mendalam dengan tim mereka untuk memperkenalkan struktur, membangun kepercayaan diri, dan merilis MVP yang berfungsi dalam 3 bulan. Melalui praktik agile yang ketat dan peluncuran sistem menyeluruh, kami membantu mengubah organisasi teknologi yang rapuh menjadi mesin produk yang andal.", - "0_category": "CTO as a Service", - "1_title": "Meningkatkan tim rekayasa media dari pabrik fitur menjadi pusat inovasi", - "1_text": "Ketika pertumbuhan pesat melampaui kematangan tim, tim ini membutuhkan lebih dari sekadar fitur, mereka membutuhkan transformasi. Kami merestrukturisasi praktik agile mereka, mengotomatisasi DevOps, menetapkan KPI yang terukur, dan membantu mereka beralih dari sekadar mengeksekusi tugas menjadi pemilik produk sejati yang mampu berinovasi.", - "1_category": "CTO as a Service" + "button": "Baca studi kasus" }, "project": { "heading": "Produk sumber terbuka", From 36d50f97470c18b5f22d4602fff3ebbdcd9dd5f9 Mon Sep 17 00:00:00 2001 From: Hari Nugraha Date: Thu, 29 Jan 2026 13:20:40 +0700 Subject: [PATCH 2/2] copy: improve consistency --- locales/en/case-studies/volunteering-platform.mdx | 6 +++--- locales/en/case-study.json | 4 ++-- locales/id/case-study.json | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/locales/en/case-studies/volunteering-platform.mdx b/locales/en/case-studies/volunteering-platform.mdx index fda27b8e5..c8c1978d9 100644 --- a/locales/en/case-studies/volunteering-platform.mdx +++ b/locales/en/case-studies/volunteering-platform.mdx @@ -2,7 +2,7 @@ import Image from "next/image"; ## Background -Indonesia’s largest volunteering platform decided to update its outdated technology by migrating from Angular.js to React. As a nonprofit organization with limited budget, they found managing an in-house engineering team costly and difficult. +Indonesia's largest volunteering platform decided to update its outdated technology by migrating from Angular.js to React. As a nonprofit organization with limited budget, they found managing an in-house engineering team costly and difficult. Hyperjump is proud to support this project as part of our corporate social responsibility (CSR) program, providing technology expertise to help drive social impact. @@ -15,7 +15,7 @@ Hyperjump is proud to support this project as part of our corporate social respo ## Our Approach -Hyperjump worked closely with the client’s product, engineering, and operations teams. Here’s what we accomplished: +Hyperjump worked closely with the client's product, engineering, and operations teams. Here's what we accomplished: ### Incremental Migration & Modernization @@ -49,7 +49,7 @@ After months of close collaboration, we achieved the following: