Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d518b6f
update lock
nicnocquee Feb 18, 2026
7ae3d5b
Enhance styling and animations in Hyperjump layout
nicnocquee Feb 18, 2026
614ea69
Update
nicnocquee Feb 18, 2026
8758bf6
update
nicnocquee Feb 18, 2026
740d9ee
Add comprehensive guide on premium website psychology and implement c…
nicnocquee Feb 18, 2026
e0b6bca
update text
nicnocquee Feb 18, 2026
6169aeb
update
nicnocquee Feb 18, 2026
df3e01d
update
nicnocquee Feb 18, 2026
341f46a
update
nicnocquee Feb 18, 2026
9d1ec30
update
nicnocquee Feb 18, 2026
d90e7f9
update
nicnocquee Feb 18, 2026
0beb9c4
update
nicnocquee Feb 18, 2026
393106b
update
nicnocquee Feb 18, 2026
67c48c4
update mobile
nicnocquee Feb 18, 2026
25f80b6
update services
nicnocquee Feb 18, 2026
bd3f54f
update teams
nicnocquee Feb 18, 2026
f0e6875
update
nicnocquee Feb 18, 2026
afc87f7
update
nicnocquee Feb 18, 2026
b94dd24
update
nicnocquee Feb 18, 2026
af2c0d6
update team
nicnocquee Feb 18, 2026
5d11a9b
update hero landing
nicnocquee Feb 18, 2026
c4bd6e7
update product title
nicnocquee Feb 18, 2026
3bbf644
fix typewriter on mobile
nicnocquee Feb 18, 2026
b337fdc
fix performance
nicnocquee Feb 18, 2026
b39356b
fix scrolling
nicnocquee Feb 18, 2026
6c680cb
fix performance
nicnocquee Feb 19, 2026
e5f4a64
update service page
nicnocquee Feb 19, 2026
a62f01e
update case study
nicnocquee Feb 19, 2026
9adb77b
update format
nicnocquee Feb 19, 2026
3af98cb
remove unnecessary
nicnocquee Feb 19, 2026
83b4902
feat: replace hardcoded content to support i18n
haricnugraha Feb 19, 2026
6ab2400
test: fix test
haricnugraha Feb 19, 2026
c0a653f
ci: fix format
haricnugraha Feb 19, 2026
da8278a
ci: fix test
haricnugraha Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 44 additions & 27 deletions app/[lang]/(hyperjump)/case-studies/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Metadata } from "next";
import Image from "next/image";
import Link from "next/link";
import { notFound } from "next/navigation";
import { BreadcrumbJsonLd } from "next-seo";
Expand All @@ -11,11 +10,15 @@ import { dynamicOpengraph } from "@/lib/default-metadata";
import {
caseStudyButton,
caseStudyMore,
caseStudyQuestion
caseStudyQuestion,
mainHome,
mainCaseStudiesLabel
} from "@/locales/.generated/strings";
import type { SupportedLanguage } from "@/locales/.generated/types";
import { supportedLanguages } from "@/locales/.generated/types";

import { AnimatedLines } from "../../components/animated-lines";
import { SectionReveal } from "../../components/motion-wrappers";
import {
caseStudyBy,
getCaseStudies,
Expand All @@ -42,7 +45,7 @@ export async function generateMetadata({
const { lang, slug } = await params;
const caseStudies = caseStudyBy({ lang, slug });
const meta: Metadata = {
title: `Case-Studies - ${caseStudies?.title ?? ""}`,
title: `${mainCaseStudiesLabel(lang)} - ${caseStudies?.title ?? ""}`,
description: caseStudies?.description ?? "",
alternates: {
canonical: `${url}/${lang}/case-studies/${caseStudies?.slug}`,
Expand Down Expand Up @@ -83,7 +86,7 @@ export default async function CaseStudy({ params }: CaseStudyProps) {

return (
<main className="bg-white">
<Hero heading={title} />
<Hero lang={lang} heading={title} subheading={caseStudy.description} />
<section className="mx-auto max-w-3xl px-4 md:px-20">
<article className="prose prose-headings:mt-8 prose-headings:font-semibold prose-headings:text-black prose-h1:text-4xl prose-h2:text-3xl prose-h3:text-2xl prose-h4:text-xl prose-h5:text-lg prose-h6:text-md dark:prose-headings:text-white text-left">
<Content slug={slug} lang={lang} />
Expand All @@ -108,11 +111,11 @@ export default async function CaseStudy({ params }: CaseStudyProps) {
<BreadcrumbJsonLd
items={[
{
name: "Home",
name: mainHome(lang),
item: `${url}/${lang}`
},
{
name: "Case Studies",
name: mainCaseStudiesLabel(lang),
item: `${url}/${lang}/case-studies`
},
{
Expand All @@ -125,30 +128,44 @@ export default async function CaseStudy({ params }: CaseStudyProps) {
);
}

function Hero({ heading }: { heading: string }) {
type HeroProps = {
heading: string;
subheading: string;
} & LangProps;

function Hero({ lang, heading, subheading }: HeroProps) {
return (
<section
id="hero"
className="bg-hyperjump-black relative h-87.75 overflow-hidden text-white">
<div className="absolute inset-0 z-0">
<Image
alt="Hero background"
blurDataURL="/images/case-studies/banner.webp"
className="object-cover object-center"
fill
placeholder="blur"
priority
src="/images/case-studies/banner.webp"
/>
</div>

<div className="relative z-10 mt-10 flex h-87.75 items-center justify-center">
<h1
className="mb-4 max-w-3xl px-4 text-center text-2xl font-medium text-white sm:text-4xl md:px-20 md:text-4xl"
dangerouslySetInnerHTML={{
__html: heading
}}
/>
className="bg-hero-premium relative overflow-hidden text-white">
<div className="hero-glow animate-glow top-[12%] left-1/2 -translate-x-1/2" />
<div className="hero-glow animate-glow -top-32 right-0 [animation-delay:1.5s]" />
<div
className="pointer-events-none absolute inset-0 opacity-40"
style={{
backgroundImage:
"radial-gradient(circle, rgba(255,255,255,0.07) 1px, transparent 1px)",
backgroundSize: "24px 24px"
}}
/>
<AnimatedLines className="pointer-events-none absolute inset-0 h-full w-full opacity-30" />

<div className="relative z-10 mx-auto max-w-5xl px-4 md:px-20 xl:px-0">
<div className="flex flex-col items-center pt-40 pb-20 md:pt-48 md:pb-28">
<SectionReveal>
<div className="max-w-3xl text-center">
<span className="mb-5 inline-block text-xs font-semibold tracking-[0.2em] text-yellow-300 uppercase">
{mainCaseStudiesLabel(lang)}
</span>
<h1 className="mb-6 text-4xl leading-[1.08] font-semibold tracking-tight md:text-6xl lg:text-[4.5rem]">
{heading}
</h1>
<p className="mx-auto max-w-2xl text-lg leading-relaxed font-medium text-white/60 md:text-xl">
{subheading}
</p>
</div>
</SectionReveal>
</div>
</div>
</section>
);
Expand Down
93 changes: 66 additions & 27 deletions app/[lang]/(hyperjump)/case-studies/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Metadata } from "next";
import { BreadcrumbJsonLd } from "next-seo";

import { Hero } from "@/app/components/hero";
import data from "@/data.json";
import { dynamicOpengraph } from "@/lib/default-metadata";
import {
Expand All @@ -12,11 +11,16 @@ import {
caseStudyExplore,
caseStudyHeroDesc,
caseStudyHeroHeading,
caseStudyTitle
caseStudyTitle,
caseStudyExploreDesc,
mainHome,
mainCaseStudiesLabel
} from "@/locales/.generated/strings";

import { getCaseStudies } from "../data";
import { CaseStudyCard } from "../components/case-study-card";
import { AnimatedLines } from "../components/animated-lines";
import { CaseStudyCarousel } from "../components/case-study-carousel";
import { SectionReveal } from "../components/motion-wrappers";

const { url } = data;

Expand All @@ -37,7 +41,7 @@ export async function generateMetadata(props: {
}): Promise<Metadata> {
const { lang } = await props.params;
const meta: Metadata = {
title: `Case Studies - ${caseStudyTitle(lang)}`,
title: `${mainCaseStudiesLabel(lang)} - ${caseStudyTitle(lang)}`,
description: caseStudyHeroDesc(lang),
alternates: {
canonical: `${url}/${lang}/case-studies`,
Expand All @@ -56,39 +60,74 @@ export async function generateMetadata(props: {

export default async function CaseStudiesPage({ params }: CaseStudyProps) {
const { lang } = await params;
const caseStudies = getCaseStudies(lang);

return (
<main className="bg-white">
<Hero
title={caseStudyHeroHeading(lang)}
subtitle={caseStudyHeroDesc(lang)}
/>
<div className="xxl:max-w-7xl mx-auto flex w-full max-w-6xl flex-wrap items-center justify-center px-4 py-6 text-center md:px-20 xl:px-0">
<h3 className="text-hyperjump-black w-72 text-[28px] font-medium md:w-full md:text-[40px]">
{caseStudyExplore(lang)}
</h3>
<section className="bg-white pt-5 pb-10">
<div className="mx-auto max-w-5xl">
<div className="grid gap-6 md:grid-cols-3">
{getCaseStudies(lang).map((caseStudy) => (
<CaseStudyCard
key={caseStudy.slug}
caseStudy={caseStudy}
lang={lang}
<main>
<section
id="hero"
className="bg-hero-premium relative overflow-hidden text-white">
<div className="hero-glow animate-glow top-[12%] left-1/2 -translate-x-1/2" />
<div className="hero-glow animate-glow -top-32 right-0 [animation-delay:1.5s]" />
<div
className="pointer-events-none absolute inset-0 opacity-40"
style={{
backgroundImage:
"radial-gradient(circle, rgba(255,255,255,0.07) 1px, transparent 1px)",
backgroundSize: "24px 24px"
}}
/>
<AnimatedLines className="pointer-events-none absolute inset-0 h-full w-full opacity-30" />

<div className="relative z-10 mx-auto max-w-5xl px-4 md:px-20 xl:px-0">
<div className="flex flex-col items-center pt-40 pb-20 md:pt-48 md:pb-28">
<SectionReveal>
<div className="max-w-3xl text-center">
<span className="mb-5 inline-block text-xs font-semibold tracking-[0.2em] text-yellow-300 uppercase">
{mainCaseStudiesLabel(lang)}
</span>
<h1
className="mb-6 text-4xl leading-[1.08] font-semibold tracking-tight md:text-6xl lg:text-[4.5rem] [&>span]:text-yellow-300"
dangerouslySetInnerHTML={{
__html: caseStudyHeroHeading(lang)
}}
/>
))}
</div>
<p className="mx-auto max-w-2xl text-lg leading-relaxed font-medium text-white/60 md:text-xl">
{caseStudyHeroDesc(lang)}
</p>
</div>
</SectionReveal>
</div>
</section>
</div>
</div>
</section>

<section className="bg-hyperjump-surface">
<div className="mx-auto max-w-5xl px-4 py-20 md:px-20 md:py-28 xl:px-0">
<SectionReveal>
<div className="mb-16">
<h2 className="text-hyperjump-black max-w-3xl text-4xl font-semibold tracking-tight md:text-5xl">
{caseStudyExplore(lang)}
</h2>
<p className="text-hyperjump-gray mt-5 max-w-2xl text-lg leading-relaxed">
{caseStudyExploreDesc(lang)}
</p>
</div>
</SectionReveal>

<SectionReveal>
<CaseStudyCarousel caseStudies={caseStudies} lang={lang} />
</SectionReveal>
</div>
</section>

<BreadcrumbJsonLd
items={[
{
name: "Home",
name: mainHome(lang),
item: `${url}/${lang}`
},
{
name: "Case Studies",
name: mainCaseStudiesLabel(lang),
item: `${url}/${lang}/case-studies`
}
]}
Expand Down
Loading