A package can remove a surprising amount of work. It can also add configuration, upgrade decisions and a new source of failures. The useful comparison is between those two costs over the life of the feature.
Before adding one, I want to know what responsibility it will own. A mature parser can be worth far more than its installation cost because the edge cases are the real work. A package that wraps two clear standard-library calls has a different tradeoff.
Look at the boundary
Can the rest of the code use a small interface, or will library-specific types spread through the application? If the package needs replacing, that boundary determines whether the change touches one module or fifty.
Also check how it behaves in the environment where it will run. A dependency that works on a laptop may require a native library missing from the deployment image. A browser package may bring much more code than the page’s one interaction needs.
Useful questions include:
- Does it solve the difficult part of the problem?
- Is the licence suitable for the project?
- Are its runtime and version requirements compatible with deployment?
- Can we diagnose a failure inside it?
- Is there a plausible replacement or removal path?
Pinning is the beginning
An exact version makes a build more reproducible. It does not make the package permanently safe or remove the need to review updates. Someone still needs to understand why an upgrade is needed and what could change.
For this portfolio, the theme is pinned to a Git revision and Hugo has an explicit version. Site-specific templates and CSS live in the project. That arrangement makes the theme relationship visible while keeping the custom presentation inspectable.
A dependency earns its place when the work it reliably owns is larger than the work it creates. Counting the lines it saves today is only one part of that decision.