Skip to main content

Command Palette

Search for a command to run...

Just write your own libraries

Published
4 min read
Just write your own libraries
T

Just a guy who loves to write code and watch anime.

Just write your own libraries

Libraries used to limit what you could do. If nothing fit your needs, you had to settle or slowly create it yourself. Now, that's changed. AI models are advanced enough for you to make exactly what you want in just an afternoon.


The cost of using someone else's library

Every library is decisions someone made for their use case, not yours. The API surface is bigger than you need. The types don't match your domain. The defaults are wrong. It pulls in dependencies you don't want. It updates and breaks something subtle. You patch around its limitations.


Writing your own

You can make it tiny. Just the surface you actually use. Type-safe in your domain, composable with your code, self-documenting because it's shaped like your problem.

You can also build it for speed. When you write it yourself, you can target performance from the start. Add performance tests if it matters. Most generic libraries can't do this because they're optimizing for many use cases at once.

If something out there already does roughly what you want, use it as inspiration for the agent. Point at it, say "here's the API I like, here's the part I need, build me that." Or fork the relevant module out and have the agent simplify it, harden it, make it faster. You're not starting from a blank page, you're extracting the good parts.


TDD makes it safe

Writing your own only feels safe if you know it works. TDD: write the test first, watch it fail, then implement.

When you write the test first, you describe the API you wish existed before committing to any implementation.

When you write the test after, the test is shaped by code that already exists. You write tests that pass. You don't really know if they'd catch a bug, because you wrote them with the answer in front of you.

Watching the test fail first is the part that matters. A test that has never failed might just always pass for the wrong reason.


The tools that make TDD fast

Vitest for unit tests. Watch mode is sub-second. Testing stops feeling like a tax.

Mock Service Worker (MSW) for mocking the network. It intercepts at the service worker level. Your code uses real fetch. The request is real until it hits the boundary, then MSW responds. No special branches, no injected mocks. The same setup works in unit tests, dev, and browser tests. MSW now mocks WebSockets too, which used to be painful.

Vitest browser mode + Playwright for tests that need a real browser. Same Vitest API, same fast loop, but running in real Chromium.


The flow

  1. Need some functionality.

  2. Write a test for the API you want.

  3. Have the agent implement it. Optionally point at an existing library as inspiration.

  4. Iterate until the test passes and the API feels right.

  5. Add performance tests if speed matters.

  6. Move on.

The output is a small file in your codebase that does exactly what you need. Your names, your types, no dependencies. If something changes, you change your own code. No version bumps, no upstream breaking changes, no opening GitHub issues on someone else's repo.


When to still use libraries

This isn't "never use libraries again." Some libraries earn their place.

Network effects matter. React has the entire ecosystem around it: tooling, types, jobs, documentation, every backend integration assumes it. The library itself is almost beside the point at that level. You're buying into a community, not a dependency.

Some libraries do genuinely hard things. MSW intercepts at the service worker layer with all the protocol handling, lifecycle management, and edge cases that come with that. Replicating it would take weeks and you'd get something worse. The same goes for things like Playwright, Vitest, esbuild, the language runtime itself. These solve problems that are genuinely hard and that you do not want to own.

The point of this post isn't "build everything from scratch." It's "stop reaching for a library by default for things that should be 50 lines of code in your repo." Use libraries where they actually pull weight. Skip them for the long tail of utilities, helpers, wrappers, and glue where they cost more than they save.