We've had a few people who like to do the first option. They would build a semi library inside the app to solve a problem and then when they move on to another company, no one really understands the design principals behind it and make changes that make it not so reusable and years later it never ends up getting reused for anything new anyway so we are just left with a very abstract, pseudo library with no documentation and years of tacked on changes.
Now we advise people to build the simplest and most obvious version for the problem you are looking at right now and if in the future you need it all over the place, replace it with a reusable one.
The exception seems to be React components, those generally seem to be very easy to identify as reusable UI and can be made generic from day one.
Good code should serve as documentation, in addition to serving a functional purpose. “Programs must be written for people to read, and only incidentally for machines to execute.”
Depending on the use case, this may not obviate the necessity of plain-text/wiki documentation; but I do note a tendency for many wikis, documentation web sites, etc, to be incomplete and/or woefully out of date. Half-assed docs can almost be worse than no docs; if it’s a priority, then it has to be folded into the entire SDLC, or have its own dedicated staff.
Now we advise people to build the simplest and most obvious version for the problem you are looking at right now and if in the future you need it all over the place, replace it with a reusable one.
The exception seems to be React components, those generally seem to be very easy to identify as reusable UI and can be made generic from day one.