Skip to main content
all posts
essay
~16 min readUpdated

A Repeatable Technical Writing System for SEO That Compounds

A repeatable technical writing system for SEO-focused developer content with cluster strategy, quality gates, and weekly execution cadence.

Hands the full post + a ready prompt to Claude Code or any AI assistant, so it can read and use it.
share

I used to think the hard part of blogging was writing. It isn't. The hard part is the blank page on the third Tuesday in a row when you're tired, the feature you were going to write about half-shipped, and the easiest thing in the world is to publish nothing, or worse, to publish something thin and pretend it counts.

What fixed that for me wasn't motivation. It was building a system that makes the next post mostly mechanical, so the only thing left requiring real energy is the actual thinking. This is that system, the way I run it for adatepe.dev. It's not a content-marketing framework I read about; it's the workflow I reverse-engineered from how I write code, because I'm a developer and treating writing like writing never worked for me. Treating it like a build pipeline did.

pollWhat actually stops you publishing consistently?

The unit is a post, the artifact is a draft file

Every post starts as a single Markdown file with frontmatter, the same way a feature starts as a branch. The frontmatter is the contract, it forces me to decide the metadata before I've written a word, which is exactly when those decisions are cheap.

---
title: "A specific, opinionated title"
excerpt: "One sentence a human would actually click."
publishedAt: "2026-05-31"
tags: ["Technical Writing", "SEO"]
focusKeyword: "technical writing system"
canonicalUrl: "https://www.adatepe.dev/blog/..."
---

Filling this in first does something subtle: if I can't write an honest one-sentence excerpt, I don't yet understand the post well enough to write it. The frontmatter is my outline-before-the-outline. A vague excerpt is a tell, the same way a vague ticket is a tell that the work isn't scoped.

I keep the title specific and opinionated on purpose. "Five tips for better blogging" is a title I would never click and never write. "The thing that finally got my SPA crawled was a noscript problem" is a title that promises something real. The voice is the product. No engagement bait, no listicle scaffolding, if the title sounds like a content farm, the post is already dead to me.

The same instinct applies one layer down, to the very first sentence of the body itself:

In this article we will explore some of the
various considerations one might take into
account when thinking about technical writing.

Same topic. The second one tells the reader what they get before they decide to leave. That decision happens in the first sentence.

I built that rule into how I draft, so the opening earns attention instead of asking for patience.

Start with the prediction that reframed blogging for me:

your guessThe blank page on the third tired Tuesday in a row beats most developers who try to blog. What finally fixed it for me?

Scope one idea, refuse the rest

The most common way my drafts used to fail was scope creep. I'd start a post about internal linking and by paragraph four I was explaining JSON-LD, then sitemaps, then my whole deployment setup. The result was a sprawling thing that covered everything and landed nothing.

So I borrowed the discipline I use for tickets: one post, one outcome, stated in a sentence before I start. If a tangent is good, it doesn't get deleted, it gets cut and pasted into a new draft file in my ideas folder. That tangent is now a future post, with its own scope, instead of a derailment of this one. Over a few months this is also how the cluster fills in. The posts breed posts. My /blog didn't get planned top-down; it grew from offcuts that earned their own files.

Between BMW shifts and my M.Sc. CS coursework at LMU Munich, I do not have the luxury of reinventing the shape of each post, so I lean on one outline every single time. Here it is, with the notes I keep pinned to each section.

annotatedThe outline I reuse for every post
# Title: specific + benefit
## The problem (why care, 1 para)
## The approach (the one idea)
## How it works (code / steps)
## Tradeoffs (be honest)
## Where it leaves me (CTA)
  1. One paragraph on why the reader should care. If they do not feel the pain in the first screen, the rest never gets read.

That skeleton is why scoping feels mechanical instead of agonizing. Every section already knows its job before I type a word into it.

Bounded scope is also what makes the quality gate pass cleanly, which brings me to the part of the system I rely on most.

The quality gate runs before I'm allowed to feel done

I do not trust my own judgment about whether a draft is finished, especially late at night. So I removed the judgment. There's a CLI command, check-blog, that I run on every post, and it either passes or it doesn't:

bun run check-blog

It enforces concrete, non-negotiable thresholds, a minimum word count so nothing thin slips through, a minimum number of ## sections so the structure is real, and a requirement for at least a couple of internal links to actual site routes. This is the same instinct as bun run verify for code: formatting, types, lint, all in a fixed order, all green or it doesn't ship. Partial green is not green, for posts as much as for TypeScript.

The reason this matters more for writing than for code is that writing has no compiler. A broken function fails loudly. A weak paragraph fails silently, and silence is exactly what you want to hear when you're tired and want to be done. The gate turns that silence into a red exit code. It's the most honest editor I have, because it has no feelings about how hard I worked.

A nice second-order effect: because the gate requires internal links, every post is structurally forced to participate in the cluster. I physically cannot ship an orphan. The link to /#projects or back to the hub isn't an afterthought I might forget, it's a condition of shipping.

The thresholds themselves took some tuning, and getting them wrong in either direction has a real cost. My first version demanded 1,500 words, and within a month I noticed I was padding. I would hit a genuinely complete thought at 1,050 words and then write three filler paragraphs purely to clear the bar, which is exactly the thin-but-long writing the gate was supposed to prevent. So the word minimum is a floor against laziness, not a target, and I set it deliberately low, around 800 words, then lean on the read-aloud pass to catch padding the counter cannot see. The internal-link rule had the opposite failure. I started at one required link and posts kept linking to the same hub page over and over to satisfy it, which builds nothing. Requiring at least two links to distinct routes fixed that, because the second link almost always has to be a real topical neighbor. The honest tradeoff is that a stricter gate occasionally blocks a short post that was actually finished, and I have learned to override it by hand rather than weaken the threshold for everyone. That override is logged, the same way I treat a skipped check in code; the gate stays strict and the exception stays visible. It is the same philosophy I lean on in my guardrails for AI-generated code: a gate you quietly loosen is a gate you no longer have.

SEO is a property of the system, not a step in it

I want to be careful here, because "technical writing system for SEO" could be read as "stuff keywords in efficiently." That's the opposite of what I do. In my workflow, SEO is not a phase I bolt on at the end. It's an emergent property of doing the other steps honestly.

Walk it through. Scoping one idea per post means each post is genuinely about one thing, which is exactly the topical focus a search system rewards, not because I tricked it, but because a focused post is actually more useful. Writing specific, opinionated prose with real tool and file names produces entity-rich text by accident, because being concrete and being legible to a retrieval system turn out to be the same thing. And the gate's internal-link requirement builds the connected cluster that signals depth, without me ever "doing SEO" as a separate task.

Laid out as a pipeline, the whole thing reads like a build. Click any stage to see what actually happens there:

flowThe path a post takes, from cluster to measurement

I do not invent topics in a planning mood. I pull the next post from the offcuts folder, so each one is already a real fragment that grew out of writing I was excited about. The tradeoff is that the cluster grows bottom-up and a little unpredictably, but it ends up reflecting what I actually think instead of a spreadsheet I filled in once.

Notice that nothing in that pipeline is a dedicated "SEO step"; the ranking is a byproduct of doing each stage honestly.

The one explicit SEO step is the frontmatter contract, and even that earns its place by forcing clarity. A focusKeyword and a one-sentence excerpt are decisions about what the post is for. If I can fill them honestly, the post has a point. If I'm reaching to invent them, that's the system telling me the draft is unfocused. The metadata is a thinking tool first and a search signal second.

This is the part I'd argue with most blogging advice about. The common framing treats good writing and SEO as a tradeoff you balance. In a system built this way they aren't in tension at all, the things that make a post worth reading are mostly the same things that make it discoverable. The keyword-stuffing approach only feels necessary when the underlying writing is thin, and a system whose first rule is "scope one real idea" rarely produces thin writing.

So I don't have an SEO checklist taped to my monitor. I have a process that produces SEO-friendly artifacts as a byproduct of producing good ones. That's the whole bet, and it's why I trust it on a tired Tuesday: I never have to choose between writing well and ranking, because the system already decided they're the same task.

A weekly cadence I can actually keep

The system only works if the cadence is survivable. Mine is deliberately modest, and split across the week so no single day requires a heroic block of time:

  • Early week: pick one idea from the offcuts folder, write the frontmatter, scope it to one sentence.
  • Midweek: draft. This is the only step that needs real focus. Everything else is mechanical.
  • Later: run check-blog, fix what it flags, add internal links if I was lazy, run the formatter.
  • Before shipping: read it out loud once. If a sentence sounds like marketing copy, it gets rewritten or cut.

That last step is the only purely human gate, and it's the one I'd never automate, because the whole point of the voice is that a machine wouldn't write it that way. Everything around it, though, I've pushed onto tooling so the human energy is spent only where it's irreplaceable.

I publish roughly one substantial post a week, plus an occasional refresh of an older one when a new post gives me a reason to link back to it. I don't chase volume. A flood of thin posts would fail the gate anyway, and even if it didn't, it would dilute the thing the cluster is supposed to demonstrate: that I write carefully and ship consistently.

Those refreshes matter more than they look, so let me put the trade-off plainly first:

your guessTwo posts target the same keyword. One is 3,000 words published once and never touched. The other is 1,200 words, updated every 8 weeks. Six months later, which ranks higher?

I learned to treat that refresh slot as a first-class part of the week, not a chore I get to if there is time left over.

The cadence only works because it is split so no single day needs a heroic block. Step through my week:

compareA week, one step at a time

Pick one idea from the offcuts folder, write the frontmatter, scope it to one sentence.

If I cannot write an honest one-sentence excerpt, I do not yet understand the post well enough to write it. The frontmatter is the outline before the outline.

What "compounds" actually means here

People say content compounds and leave it vague, so let me be concrete about the mechanism, because it's the whole reason the system is worth the discipline.

Each post does three durable things. It deepens a topic cluster, which is what search and AI retrieval systems reward over single keywords. It adds internal links that strengthen the pages already in that cluster, old posts get more connected every time I publish a new one. And it produces a reusable artifact: a draft file, a frontmatter pattern, sometimes an offcut that becomes the next post. The marginal cost of post number twenty is lower than post number two, and its value is higher, because it lands in an established structure instead of an empty archive.

That's compounding. Not "traffic goes up if you grind." It's that the system makes each new unit cheaper to produce and worth more once produced. The grind, if there is one, is front-loaded into building the gate and the cadence once.

Run your own publishing process against this. The point of a system is that none of it depends on remembering, tick what's actually automated versus what you're holding together with willpower:

checklistIs your blog a system, or just willpower?0/6

Why an update cadence beats a one-time word count

For a long time I assumed the way to win a topic was to write the definitive 3,000-word post once and walk away. It almost never worked. The posts that actually held their ranking were the ones I kept coming back to, even when the edits were small. Once a topic is genuinely covered, more words stop helping. What keeps helping is staying current and staying connected, and both of those are things you can only do with a cadence, not with a single heroic draft.

So I built the refresh into the system the same way I built the gate. Every draft file carries its publish date in the frontmatter, which means I can sort the whole blog by age in one command and see what is going stale. When a post crosses roughly two months without a touch, it becomes eligible for a refresh slot. The trigger is usually concrete: a new post gives me an honest reason to link back, a tool I named shipped a breaking change, or a claim I made is no longer quite true. I do not invent reasons to edit. I let new writing surface the old posts that need it.

What I measure is deliberately boring, because I do not want to chase vanity numbers I cannot trust. I track when each post was last meaningfully updated, how many internal links point into it from newer posts, and whether it still passes check-blog against the current thresholds. Those three are enough to tell me which posts are decaying and which are compounding. Length is not on the list. The lever was never how much I wrote once. It was whether I kept the post alive, and a writing system is what makes keeping it alive cost almost nothing.

The offcuts folder, where the next post comes from

Scope discipline has a side effect nobody warns you about: it produces waste. Every time I cut a tangent to keep a post to one idea, that tangent has to go somewhere. Mine go into a folder of draft files, one per stray thought, each seeded with the two or three sentences I was about to jam into the post I was actually writing. I call them offcuts, the way a carpenter keeps the good short ends instead of sweeping them into the bin.

That folder is the whole reason I never face a truly blank page. When a writing slot comes up, I do not stare at a content calendar and ask myself what topic I am supposed to care about this week. I open the offcuts folder and read what past-me already cared about enough to start writing down. The energy is already in the file. A blank page asks you to manufacture interest from nothing. An offcut asks you to finish a thought you were genuinely having a week ago, which is a completely different and much easier job.

The mechanism is simple. A cut tangent is, almost by definition, a separate idea that did not fit the post it tried to crash. That is exactly the test for whether something deserves its own post. So when I promote an offcut, I give it its own frontmatter contract and its own single scope, and it stops being a fragment and becomes a real candidate. Some never graduate, and that is fine, the folder is allowed to hold duds.

What I like most is the direction this gives the cluster. It grows bottom-up, out of real offcuts from real writing, instead of top-down from a calendar I invented in a planning mood. Every new post is downstream of something I was already excited enough to write about once. The cluster ends up reflecting what I actually think, not what a spreadsheet told me to schedule.

To make the path concrete, here is the exact life of one offcut, from the moment it gets cut to the moment it ships as its own post. Walk it step by step.

timelineThe life of one offcut, from cut to shipped post
  1. Mid-draft I notice a tangent pulling a post toward a second idea. Instead of deleting it or jamming it in, I cut the two or three sentences I was about to write and drop them into a new file in the offcuts folder. The cost of doing this is seconds, and it keeps the current post honest about scoping one idea.

That loop is why the archive feels like it writes itself: nothing is ever truly new, just finished.

The first sentence decides whether the post is read

I used to treat the opening like a runway, a few sentences of throat-clearing before the real point. Then I watched how I read other people's posts, and I never gave them a runway. I decided in one sentence whether to stay. The reader does the same to me, so the first sentence is not a warm-up, it is the negotiation for the next minute of their attention.

So I write openings backwards. I figure out the single payoff the post delivers, the thing someone would be glad they read, and I put a plain version of it in line one. No "in this article", no "let's explore", no setting the stage. Those phrases tell the reader to wait, and waiting is exactly what they will not do. State the result, then earn it in the paragraphs that follow.

The test I use is simple. If I deleted the first sentence, would the post lose anything real? If not, it was throat-clearing and it goes. A good open makes a promise concrete enough to cash in, and that decision is already over by the second line.

How I turn a shipped feature into a post without extra work

The cheapest posts I write are the ones I started writing before I knew they were posts. While I am building a feature at BMW or working through something for my M.Sc. CS coursework at LMU Munich, I keep a scratch file open and dump notes into it as I go. Not polished sentences, just the things I would have forgotten by Friday: the dead end I hit, the reason I picked one approach over another, the gotcha that cost me an hour. Capturing it in the moment is nearly free. Reconstructing it a week later is expensive and usually wrong, because tired-me invents a cleaner story than what actually happened.

The commit log does more of the work than I expected. When I scope commits well, each message is already a small unit of "here is what changed and why," and the sequence of them is a rough outline of the post. I read the log top to bottom and the structure is mostly there: the problem, the first attempt, the correction, the thing that finally worked. I am not inventing an arc, I am reading one that the work already laid down. The same discipline that makes a clean history makes a draftable history.

I also grab screenshots and diffs in the moment, not afterward. A before and after diff is the most honest figure I can put in a post, and it only exists if I captured it while the change was fresh. Trying to recreate a screenshot after the branch is merged is the kind of busywork that quietly kills a draft.

By the time the feature ships, writing the post is assembly, not invention. I have the notes, the log gives me the spine, and the screenshots are sitting in a folder. I drop them into the outline I reuse, run the gate, and most of the effort is editing rather than generating. It is the same instinct behind my nightshift autonomous loop: capture the context while it is cheap, so the work that needs me later is small. The post becomes a byproduct of building, which is exactly when it costs the least.

Why a developer should run it like this

If you write code for a living, you already have the instincts this system needs. You know how to scope a ticket, you know not to trust your tired self, you know a green pipeline is worth more than a confident feeling. Point those instincts at your writing and the blank-page problem mostly evaporates, because most of the work is no longer writing, it's executing a process you already trust.

I link my own work together deliberately for the same reason I write tests: future-me is forgetful and present-me is biased. The connections between /blog, the proof at /#projects, and the context at /cv aren't there to game anything. They're there because a system that depends on me remembering to do the right thing is a system that will fail on the third tired Tuesday. So I built one that doesn't.

Before you copy the whole thing, figure out which one piece will move the needle for your own situation, because adopting all of it at once is how good systems die unfinished. Answer two honest questions and the guide below points you at the single highest-leverage place to start.

find your answer

Which part of the system should you build first?

One honest answer routes you to the piece that fixes your actual bottleneck.

What breaks first when you try to publish weekly?

The honest answer is usually whichever one you flinched at, so start there and add the rest once the first piece is running on its own.

your move

What's the next piece you want to build?

Pick where the system should grow.

I tend the writing system between BMW shifts and coursework, so it has to run itself, and the site is what every post quietly points toward.

built by alperenEvery post here shipped through this system, including this one.Full-stack engineer, M.Sc. CS at LMU Munich. See the work the writing funnels toward, or get in touch.Explore my work