If you have seen the old version of this website, you might ask: “Was this really rewritten from scratch?” Yes. With help from Claude Code, the portfolio I built on JavaScript Next.js finally got a modern foundation based on my own Next.js template.
Rewriting an old Next.js codebase that was falling behind
I started building the old version aroundF ebruary 2022, when I was intenth grade. At the time, the codebase used JavaScript, the Pages Router, Apollo Client, twin.macro, and a few patterns that felt perfectly normal then but became increasingly difficult to maintain.
The original design was created in Figma around November 2021. So this rewrite was not simply a file migration. It was a process of bringing an aging Next.js codebase to a healthier foundation while preserving the taste, soul, and design system I had built since high school.
An escape project that became a personal archive
A slightly personal intermezzo. In July 2021, my family and I got COVID-19. I started high school around 21 July, and my father passed away on 27 July. It was not an easy period.
This website became an escape project. Not because I had a perfectly planned career roadmap, but because making something felt easier than thinking about everything else. Fixing one pixel, changing a button color, or trying another animation gave me room to keep moving. It sounds dramatic, but that is what it was 😭

From a 2024 blog update to my fifth semester
The codebase grew organically. I added sections, changed copy, tried animations, moved routes, and kept old decisions alive with the classic excuse: “I will clean this up later.” Spoiler: later arrived four years later, wkwkwk 😹
The last meaningful update was aroundMarch 2024, when I added the blog. After that, university, organizations, robotics, networking, and other projects took over.
This rewrite finally happened during my fifth semester. The timing was also a little absurd. After the semester break, I barely had a real holiday because of PKM. At ITS, PKM projects are closely supervised with frequent monitoring and evaluation. As PKP2 approached, the schedule became even tighter, and I ended up taking two weeks of academic leave because of the project, wkwkwk.
After the PKM camp ended and PKP2 was finally over, my brain needed a project refresh. So I opened the old portfolio again. From an escape project during high school to a refresh project after PKP2. Full circle 😂

The rewrite tech stack and why I chose it
This rewrite is based on my own Next.js template. I wanted the new codebase to share the template’s coding style, folder conventions, and tooling baseline instead of starting from another random starter.
| Technology | Why I chose it | Trade-off |
|---|---|---|
| Next.js 16 | App Router, server rendering, the Metadata API, ISR, and route conventions that fit a portfolio and blog. | I have to understand server and client boundaries so server environment variables never reach the browser. |
| React 19 | A familiar ecosystem for interactive sections, motion, and reusable components. | It takes discipline to avoid creating too many tiny abstractions. |
| TypeScript strict | Hygraph and Ghost return large, nullable data shapes. Strict types catch mistakes before build time. | It takes extra time to define data contracts and handle missing CMS fields. |
| Tailwind CSS v4 | CSS-first configuration, fast layout exploration, and centralized design tokens in globals.css. | Classes can get long, so formatting and component boundaries need discipline. |
| Hygraph | A good fit for structured projects: status, year, role, tech stack, highlights, gallery, and rich text. | GraphQL quotas need protection through field selection, ISR, and cache tags. |
| Ghost | A comfortable Lexical editor for long-form writing, cards, galleries, bookmarks, callouts, and code blocks. | As a headless CMS, public rendering and SEO still have to be handled in Next.js. |
| Giscus | GitHub Discussions comments without building a comment backend from scratch. | The comments repository must be public, and readers need GitHub to comment. |
From Pages Router to App Router
The old codebase used a JavaScript Next.js pattern that had been running for years. In this rewrite, routes moved to the App Router. Pages remain server-first, while client containers are used only when interaction is actually needed: the mobile menu, language toggle, copy-code button, Ghost toggle cards, and Giscus.
Static content such as navigation, social links, labels, and the tech stack lives in constants. Data access lives in a service layer. UI components do not need to know how Hygraph or Ghost work.
const project = await getProjectBySlug('delta-connect');
if (!project) {
notFound();
}
Server-first with ISR
Projects and articles do not change every second. Using cache: 'no-store' everywhere would waste requests and quotas. I chose one-hour ISR with cache tags for both collections and individual entries.
When a Hygraph project is published, its webhook calls the revalidation endpoint. Next.js then invalidates project and project:delta-connect. Ghost follows the same idea for the post collection and article slug.
Ghost Lexical cards and formatting
Ghost content is not just paragraphs. The editor can produce image cards, galleries, callouts, bookmarks, toggles, buttons, audio, video, and code blocks. Ghost HTML is sanitized with an allowlist that preserves kg-* classes while blocking scripts and forms from the content body.
Ghost’s official cards.min.css and JavaScript are loaded only on article detail pages. Code blocks also receive a terminal-style wrapper, a language label, a copy button, and more breathing room. They no longer look like a raw black pre tag that wandered into the page 😅
The first prompt I used
The first prompt was long and deliberately specific. I asked Claude Code to read both codebases, preserve the old visual language, create memory and a brief, then explore, plan, and execute with multiple agents.
/frontend-design
Hiluwww, kamu adalah front end developer profesional dengan stack nextjs+tailwindcss...
Kamu aku suruh untuk rewrite website portofolioku yang ku bangun pada tahun 2022 menggunakan nextjs javascript. ada di ../portfolio
Aku mau kamu pake template nextjs ku dengan style coding ku, template nya ada di ../next-template
Pastikan kamu tetap mengikuti taste, soul, dan design system ku dari 2022 ituu. Kalo ada yang tidak best practice gpp diubah menjadi paling optimal dan bagus.
Pastikan kamu menyimpan memory dan membuat brief dll agar design yang dihasilkan oleh agent sesuai dengan feel design lama kuu...
Pastikan kamu explore dulu, pahami, plan, dan eksekusi dengan multi agents agar context window tidak cepat penuh.
The first result was not good and missed the brief. Separate context made some visual decisions disconnected. A better result only appeared after around10 to 15 additional prompts. That taught me that AI still needs visual feedback and repeated constraints, not only one giant brief 😅
How I used Claude Code for the rewrite
Claude Code was not a magic button that I pressed until a website appeared. It was more like a pair-programming friend who could read many files, map dependencies, find bugs, draft implementations, and run checks. I still made the final calls.
- Explore: read the old portfolio, the new template, the design brief, the bio context, and available assets.
- Map: split work that could run in parallel: UI, CMS, SEO, route migration, and data modeling.
- Implement: change one layer at a time instead of putting every decision inside page components.
- Review: check visuals, responsive behavior, types, security, and whether the result still feels like the same website.
- Verify: run lint, formatting, type checking, production builds, and CMS-backed route checks.
AI can suggest ten card variations, but it may not know which one feels generic or too “AI slop”. So if the spacing feels wrong, someone still has to say: “that is not what I meant” wkwkwk 🤔
What changed?
- Portfolio became projects: the old route now permanently redirects.
- Richer project details: year, status, role, tech stack, highlights, gallery, and WYSIWYG details.
- Headless blog: Ghost is the editor, while readers stay on the public domain.
- Two languages: Indonesian and English posts are connected through a toggle and hreflang.
- More serious SEO: canonical URLs, Open Graph, Twitter cards, CMS-timestamped sitemaps, breadcrumbs, and JSON-LD.
- Comments: Giscus uses the dedicated public
yukebrillianth/blogrepository, so the portfolio repository can remain private.
A good rewrite does not erase the past. It carries the meaningful parts onto a healthier foundation.
After the rewrite
This website is no longer just a project list. It is a record of a journey: from a Figma design in tenth grade, to slicing Next.js during high school, to an escape project during a difficult period, a blog update in 2024, and finally a major rewrite after my fifth semester and PKP2.
There may be another rewrite someday. The stack may change again. But this time I have a clearer foundation, documentation, and workflow, so I do not have to wait another four years to continue.
And if you open the source code one day and find a component that looks slightly strange, consider it part of the history. Every personal codebase has one or two tiny ghosts 😹