Every developer has that folder. The one called utils or helpers that you copy from repo to repo. You paste it in, spend twenty minutes deleting references to old database schemas, ripping out auth checks that don’t apply, and renaming variables so your new linter stops screaming. I used to do this with a theming system I’d built, the Dynamic Theme Kit. It started as a feature inside one application, and for months, I treated it like a portable tool. I was wrong. Copying code is not reuse. It is duplication with extra steps.
The Trap of the Single-Project Mindset
When you build a feature inside a project, you make hundreds of invisible assumptions. The color palette might assume a certain CSS-in-JS setup. The spacing scale might reference a design token from your company’s brand guide. The toggle between light and dark mode might call a user preference endpoint unique to that app’s backend. These dependencies feel harmless because inside the project, they are harmless. They belong there.
The problem starts when you try to lift that code out. You discover that the “reusable” component is actually a web of hidden strings connecting it to that one codebase. I learned this with DTK. It generated theme variables, yes. But it also expected a specific folder structure. It imported a type definition from somewhere deep in the original app’s types directory. It assumed the presence of a global config object that only existed in that one repository. I had never noticed because within that project, everything was always present.
Turning DTK into a standalone package meant surgery, not expansion. I did not need more features. I needed fewer connections.
Extracting the Dynamic Theme Kit
The hardest work was sitting down with the codebase and asking, for every function and every export: does this serve the theming logic, or does it serve the project? I stripped out styling presets. I removed the assumption that the consumer would be a React application. I deleted the default color palettes entirely. The original project had a navy-and-slate corporate aesthetic baked into the defaults. That had to go. A package cannot ship your brand colors.
The new kit would do exactly one thing. It takes a configuration object—some color values, some spacing numbers, some typography scales—and it generates CSS custom properties. That is it. It does not apply them. It does not decide where they go in your DOM. It does not care if you use Tailwind, Styled Components, or plain HTML. It gives your application the variables, and your project chooses how to use them.
That constraint felt limiting at first. It turned out to be liberating.
What Breaks When You Actually Try to Reuse It
Before I published anything, I needed proof that the abstraction actually held water. I pulled three small personal projects out of my archive: a markdown preview tool, a habit tracker, and a landing page for an event. None of them shared a framework or a folder structure. I installed DTK locally in each one and tried to theme them.
The first attempt failed immediately. The variable names DTK generated were too specific. It was outputting tokens like --primary-action and --background-overlay that implied a certain UI layout. In the markdown previewer, those names made no sense. There was no action button. There was no overlay. I renamed the generation logic to produce neutral, structural names that described the value rather than the widget.
I also found that my default values were too aggressive. When a user passed an incomplete config, DTK would fill in gaps with values that looked fine in a dense dashboard but broke on a sparse landing page. I switched to transparent defaults where missing tokens simply did not render, letting the consuming project define its own fallbacks.
Then there was the documentation. What seemed obvious to me—"just pass a config object"—was vague to someone reading the README at midnight. I rewrote it with real objects, real file paths, and clear explanations of what happens when you call the function versus what your application needs to do after.
These small personal projects acted as test beds. They were low stakes, but they exposed real flaws I would not have caught by staring at the source code in isolation.
The Real Test: Production at Web Weavers World
Kişisel projeler birer oyun alanıdır. Teslim tarihleri, paydaşları veya paketinizden daha eski olan legacy CSS yapıları yoktur. Gerçek sınav, DTK'yı iş sitem olan Web Weavers World'e entegre ettiğimde geldi. Bu; mevcut stilleri, müşteri beklentileri ve dikkate alınması gereken analitik verileri olan canlı bir mülktü. Eğer paket bir şeyi bozsaydı, sadece repoyu silip baştan başlayamazdım.
DTK'yı derleme hattına (build pipeline) ekledim, yeni bir renk konfigürasyonuna yönlendirdim ve yeni bir CSS değişkenleri seti oluşturmasına izin verdim. Entegrasyon bir hafta değil, sadece bir öğleden sonra sürdü. Bu, asıl işaretti. Önceden yeni bir tema eklemek; yeni CSS yazmak, yirmi farklı dosyadaki sabitlenmiş (hardcoded) hex değerlerini avlamak ve bir uç durumu (edge case) gözden kaçırmamayı ummak demekti. Şimdi konfigürasyon dosyasına bir palet ekliyorum, DTK değişkenleri oluşturuyor ve sitenin geri kalanı bunları kullanıyor. Tema mantığı, kırılgan bir manuel süreçten, iş birliği yaptığım kişilere devretmeye güvenebileceğim bir şeye dönüştü.
İnşa Etme Biçimimi Değiştiren Üç Soru
Bu süreçten geçmek, artık herhangi bir şeyi soyutlamadan önce kullandığım zihinsel bir kontrol listesini resmileştirmemi sağladı:
- Bu değişken gerçekten genel (generic) mi? Eğer isim veya mantık, orijinal projeden bir alan (domain) kavramına atıfta bulunuyorsa, o değişken orada kalmalıdır.
- Bu pakete mi yoksa uygulamaya mı ait? İş kuralları, marka kimlikleri ve düzen varsayımları uygulamada yaşar. Standartlaştırılmış çıktı üreten altyapı (plumbing) ise pakette yaşar.
- Yeniden kullanılabilir bir sorunu mu yoksa projeye özel bir sorunu mu çözüyorum? Buna dürüstçe cevap vermesi en zor olanıdır. Çözümlerimizin evrensel olduğunu düşünmeyi severiz. Genellikle yereldirler.
Bu soruları yanıtlamak, tasarımımı genellikle kod eklemek yerine kod çıkararak basitleştirmemi sağladı. DTK bana yeniden kullanımın kendinize verdiğiniz bir hediye olmadığını öğretti. Bu, kolaylığa "hayır" diyerek uyguladığınız bir disiplindir.
Refactoring Hakkında Farklı Bir Düşünme Biçimi
Eskiden refactoring işlemlerini, kodu ne kadar kısalttığıyla ölçerdim. Daha az satır, ilerleme gibi gelirdi. Şimdi ise kaç kapı açtıklarıyla ölçüyorum. Dynamic Theme Kit, özlü olduğu için zarif değildir. Yararlı olması, iç yapısını değiştirmeye gerek duymadan üç ilgisiz kişisel projeden ve canlı bir iş sitesinden sağ çıkmış olmasındandır.
Önemli olan metrik budur. Bir kez çalışan kod bir giderdir. Tekrar tekrar çalışan kod ise bir varlıktır. Artık herhangi bir özelliğe başlamadan önce duruyorum. Tekrar ihtiyaç duyacağım bir şey mi inşa ediyorum diye soruyorum. Eğer cevap evet ise, ilk satırdan itibaren farklı inşa ediyorum. Girdileri izole ediyorum. Çıktıları tanımlıyorum. Varsayımları ortadan kaldırıyorum.
En iyi refactoring kodunuzu kısaltmaz. Kodunuzun henüz hayal bile etmediğiniz yerlerde çalışmasını sağlar.
