Back to Archive Article 8 min read

The Codebase Looked Clean. The Search Engine Saw Nothing.

I want to be honest about something that took me years to fully reckon with. I have spent most of my career building things that work. ..

Derry Berni Cahyady

The Codebase Looked Clean. The Search Engine Saw Nothing.
The codebase passed every review. The product launched on schedule. Organic traffic flatlined for three months. Nobody looked at the rendering architecture until it was too late.

I want to be honest about something that took me years to fully reckon with.

I have spent most of my career building things that work. Not things that look like they work. Things that actually run: clean architecture, proper separation of concerns, components that do exactly what they are supposed to do. The code reviews passed. The deployments were stable. The user experience was fast and smooth and exactly what the product team asked for.

And then I started looking at how search engines were reading what I had built. What I found was uncomfortable. Not because the code was broken. Because it was invisible.

What "Done" Means in a Newsroom, and What It Actually Means

I spent years as a software engineer inside one of Indonesia's largest digital media operations. The pace of that environment is difficult to describe to anyone who has not worked inside it. News moves in minutes. A story breaks, and within the hour there are multiple teams touching different parts of the same system: editorial producing content, product shipping features, engineering patching infrastructure, all simultaneously, all under pressure to be faster than the previous cycle.

Consider the landscape we were operating inside. The top three Indonesian news portals, detik.com, kompas.com, and tribunnews.com, collectively serve hundreds of millions of sessions per month. Detik alone receives approximately 180 million visits per day. The traffic numbers are genuinely staggering. And yet, behind those numbers, the engineering decisions that determined how much of that traffic arrived through organic search versus push notifications versus social distribution were made almost entirely by accident.

In that environment, "done" means the feature is deployed and not throwing errors. It means the page loads, the content renders, the user can interact with it. That is the definition that the sprint review uses, that the team celebrates, that gets marked complete in the project tracker.

What nobody was systematically asking was whether Google could read it.

The Rendering Queue Nobody Talks About in Sprint Planning

Here is the technical reality that most developers who have not gone deep into SEO do not fully internalise.

"JavaScript pages are crawled and subsequently indexed nine times slower than pages that contain all their content and links in the raw HTML. Considering the speed with which news moves, I'm not sure a publisher can afford to be nine times slower than their competitors to get their stories crawled by Google." - Check source

Nine times. In a newsroom producing hundreds of articles per day, that number is not an SEO statistic. It is a business catastrophe measured in traffic that never arrived because content was indexed after it stopped being relevant.

I watched this happen without having the framework to name it. Articles would publish and perform inconsistently in search. Sometimes fast indexing, sometimes days of silence. We attributed it to content quality, to keyword competition, to Google's general unpredictability. The real variable was rendering architecture.

The pattern, when I finally mapped it properly, looked roughly like this:

Content TypeRendering MethodAvg. Indexing WindowSearch Discovery Rate
Breaking news (SSR)Server-side HTMLUnder 4 hoursHigh
Feature articles (CSR)Client-side JS2 to 4 daysInconsistent
Category / tag pagesHybrid, unstructured1 to 2 weeksLow
Related article blocksClient-side JSOften neverNear zero

The editorial team had no visibility into this table. They were measuring performance by pageviews, not by indexing velocity. The engineering team was measuring by deployment stability. Nobody was sitting in the middle, and that gap cost the business a significant and unmeasurable volume of organic traffic over years.

What Clean Code Looks Like to a Search Engine

This is the part that is hardest to accept as an engineer who takes pride in their work.

A React component that renders beautifully in a browser is, from Googlebot's perspective, a promise. Here is what that actually looks like from a crawler's point of view:

# What the browser sees:
GET /article/breaking-news-jakarta
Response: <div id="root"></div>
[JavaScript executes]
[API call to /api/articles/12345]
[Content injected into DOM]
Final DOM: Full article, headline, body, metadata

# What Googlebot receives at crawl time:
GET /article/breaking-news-jakarta
Response: <div id="root"></div>
[Enters rendering queue]
[Queue position: unknown]
[Estimated rendering: 2 to 96 hours depending on crawl budget]
Indexed content: Potentially nothing, or a delayed partial snapshot

What Clean Code Looks Like

The code is identical. The outcome is structurally different. And no linter, no unit test, no code review process catches this because none of those systems are designed to ask the question the search engine is asking.

The Jakarta Pace Problem

I want to name something specific about the environment most Indonesian developers are building in, because I think it is a real structural factor and not just an excuse.

Jakarta's product culture runs on velocity. The pressure to ship, to iterate, to be in market before the competitor, is constant and real. In that environment, any conversation that adds time to a delivery cycle is treated as friction.

The honest version of how most project timelines work in practice looks like this:

Sprint 1-2:  Architecture discussions, framework selection
             [SSR vs CSR debate: CSR wins because "faster to build"]

Sprint 3-6:  Feature development, component library
             [SEO discussion: "we'll handle that in a later sprint"]

Sprint 7:    QA, performance testing, stakeholder demos
             [SEO still not in scope, "not a blocker for launch"]

Launch:      Product ships, metrics look good in browser
             [Organic search traffic: flatlines for 3 months]

Sprint 12:   "Why isn't organic traffic growing?"
             [Engineering effort to retrofit SSR: 3x the original cost]

Sprint Simulation

I have watched this exact sequence play out more than once. And what I find interesting, looking back, is that the decision to skip SSR was never a deliberate one. It was a series of small non-decisions, each individually reasonable, that added up to an architectural outcome nobody explicitly chose.

Three Cases That Should Have Been Preventable

The article that ranked two weeks late. During a major national news cycle, a publisher's engineering team had recently migrated their article template to a new React-based component. The content was being injected via client-side API call. The article was published at 08:00. A competitor running server-rendered templates was indexed by 09:30. The React-based article entered the rendering queue and was indexed at approximately 14:00 on day three. By that point, the search query had peaked and was declining. The traffic that should have come never did.

The category pages that accumulated authority nobody could access. A media portal had spent years producing content within structured category hierarchies. The category pages, which should have functioned as topical authority hubs, were built as JavaScript-rendered shells. Navigation links within them were loaded dynamically. From Google's perspective, those pages were nearly empty. The internal link equity that should have flowed through them was invisible. Hundreds of articles in each category were, in effect, orphaned from the site's authority graph.

The edu-tech platform that launched with the same blueprint. When I moved into education technology, I genuinely expected to find a more deliberate approach. The platform I was working with had clean architecture, well-documented components, and a proper CI/CD pipeline. It also rendered all its course content and metadata via client-side JavaScript. The SEO team had been told the technical foundation was solid. They had no reason to question it. For the first two quarters after launch, organic discovery was essentially zero for any content that required JavaScript execution to become visible. The product team blamed the content. The content team blamed the SEO strategy. The actual problem was in the architecture nobody had audited.

The AI Crawler Problem Nobody Is Prepared For

Everything above describes the relationship between JavaScript and Google's crawler. That relationship is at least partially manageable. Google has built rendering infrastructure, and with deliberate architectural decisions, a developer can build JavaScript applications that are indexable.

The AI layer is a different problem entirely.

The major AI crawlers, including those powering ChatGPT, Perplexity, Claude, and Meta's systems, largely cannot execute JavaScript. They capture the initial HTML response and nothing else. This means every content strategy designed to win AI Overview placement, to appear in AI-generated answers, to be cited by these systems when users ask questions in your domain, starts from the raw HTML response your server delivers.

CrawlerJavaScript ExecutionWhat It Sees on CSR Pages
Googlebot (standard)Queued renderingDelayed content, partial index
Googlebot (mobile)Queued renderingSame, with mobile priority
GPTBot (OpenAI)NoneInitial HTML only
ClaudeBot (Anthropic)NoneInitial HTML only
PerplexityBotNoneInitial HTML only
Meta-ExternalAgentNoneInitial HTML only

Search is splitting into two channels, and if I am being direct, the second channel is growing faster than most product teams have acknowledged. For Indonesian media and edu-tech publishers, the implication is not abstract. The AI systems that are increasingly being asked questions about education, current events, finance, and health are building their answers from content they can actually read. If your content requires JavaScript to become visible, you are structurally excluded from that layer regardless of how good the content is.

What the Architecture Decision Should Have Been

The conversation that should happen at the beginning of every project involving JavaScript frameworks has, in my experience, almost never happened organically.

The core question is straightforward enough:

For each content type this application produces:

IF content.purpose === "discovery" (intended to be found by new users)
   THEN rendering.method = "SSR" or "SSG" or "hybrid with prerender"

IF content.purpose === "interaction" (authenticated, private, application state)
   THEN rendering.method = "CSR is acceptable"

IF content.purpose === "news" or "article" or "course" or "product"
   THEN rendering.method = "SSR is non-negotiable"

Architecture Decision

This is not a controversial position. Google's own technical guidelines for news publishers explicitly state that article pages should use HTML format with body text not embedded in JavaScript. The guidance has been there. The problem is that it lives in a documentation page that most developers working on media and edu-tech products have never read, because it is not part of the engineering onboarding process, and it is not part of the product requirements document, and it is not part of any code review checklist I have ever seen.

Server-side rendering adds complexity to the build. Pre-rendering pipelines require infrastructure consideration. These are real costs, and I am not dismissing them. But they are costs that, paid at the start, are a fraction of the cost of retrofitting an architecture that was built without them. I have seen both invoices. The difference is not marginal.

The Lesson I Wish I Had Learned Earlier

Clean code and crawlable code are not the same object. A codebase can pass every review, satisfy every performance benchmark, and render beautifully in every browser on every device, and still be structurally invisible to the systems that determine whether new users ever find it.

I do not think this is a knowledge problem anymore, at least not primarily. Most senior developers working in Indonesian media and edu-tech are aware, in some general way, that JavaScript SEO is a consideration. The problem is that this awareness has not been translated into a systematic point of architectural decision, into a conversation that happens before the framework is chosen rather than after the traffic numbers fail to grow.

The companies building in Jakarta right now are moving fast. Some of them are building assets that will compound for years. Some of them are building products that are well-engineered, well-funded, and functionally invisible to the discovery layer that determines whether they grow.

The difference is usually a conversation that nobody scheduled.


— Derry Berni Cahyady is a software engineer with a career spanning Indonesia's largest digital media operations into education technology product development.

Get in touch
Choose the fastest way to reach us
15 Min Virtual Meeting Pick a time on Google Calendar
WhatsApp Us Chat directly on WhatsApp
For immediate feedback
Email Us We reply under 60 minutes