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
Persoonlijke projecten zijn zandbakken. Ze hebben geen deadlines, stakeholders of legacy CSS die ouder is dan je pakket. De echte test kwam toen ik DTK integreerde in Web Weavers World, mijn zakelijke website. Dit was een live website met bestaande stijlen, klantverwachtingen en analytics om rekening mee te houden. Als het pakket iets kapot maakte, kon ik niet gewoon de repo verwijderen en opnieuw beginnen.
Ik voegde DTK toe aan de build-pipeline, wees het naar een nieuwe kleurconfiguratie en liet het een nieuwe set CSS-variabelen genereren. De integratie duurde een middag, geen week. Dat was het signaal. Voorheen betekende het toevoegen van een nieuw thema het schrijven van nieuwe CSS, het opsporen van hardcoded hex-waarden in twintig bestanden, en hopen dat ik geen edge case over het hoofd zag. Nu voeg ik een palet toe aan het configuratiebestand, genereert DTK de variabelen en gebruikt de rest van de site deze. De themalogica veranderde van een kwetsbaar handmatig proces in iets waar ik genoeg vertrouwen in heb om aan medewerkers over te dragen.
Drie vragen die veranderden hoe ik bouw
Dit proces dwong me om een mentale checklist te formaliseren die ik nu gebruik voordat ik iets abstraheer:
- Is deze variabele echt generiek? Als de naam of de logica verwijst naar een domeinconcept uit het oorspronkelijke project, blijft dat achter.
- Hoort dit in het pakket of in de applicatie? Bedrijfsregels, merkidentiteiten en lay-outveronderstellingen horen in de app. De infrastructuur die gestandaardiseerde output genereert, hoort in het pakket.
- Los ik een herbruikbaar probleem op of een projectspecifiek probleem? Dit is het moeilijkst om eerlijk te beantwoorden. We denken graag dat onze oplossingen universeel zijn. Meestal zijn ze lokaal.
Het beantwoorden van deze vragen dwong me om mijn ontwerp te vereenvoudigen, vaak door code te verwijderen in plaats van toe te voegen. DTK leerde me dat hergebruik geen geschenk is dat je jezelf geeft. Het is een discipline die je beoefent door 'nee' te zeggen tegen gemak.
Een andere manier om over refactoring te denken
Vroeger mat ik refactors aan de hand van hoe veel korter ze de code maakten. Minder regels voelde als vooruitgang. Nu meet ik ze aan de hand van hoeveel deuren ze openen. De Dynamic Theme Kit is niet elegant omdat het beknopt is. Het is nuttig omdat het drie niet-gerelateerde persoonlijke projecten en een live zakelijke website heeft overleefd zonder dat de interne structuur hoefde te worden aangepast.
Dat is de metriek die telt. Code die één keer werkt, is een kostenpost. Code die herhaaldelijk werkt, is een asset. Voordat ik nu aan een nieuwe feature begin, stop ik even. Ik vraag me af of ik iets bouw dat ik later weer nodig zal hebben. Als het antwoord 'ja' is, bouw ik het vanaf de eerste regel anders. Ik isoleer de inputs. Ik definieer de outputs. Ik verwijder de aannames.
De beste refactor maakt je code niet korter. Het zorgt ervoor dat je code werkt op plekken die je je nu nog niet kunt voorstellen.
