Just to provide a different viewpoint I'll defend the monorepo approach.
In the past I've worked on several projects that attempted to split up every aspect of the project into different code bases. This frequently led to a lot of internal dependencies that needed to be split out into their own repositories because they were used by multiple parts of the project.
This "many small repos" approach is not entirely dissimilar to microservice architecture. Microservices are great for handling scaling and complexity but they work best if you already have multiple small teams or intend to divide a project up into small teams. This social division in turn brings its own problems and there are again ways to address this by effectively making teams overlap in various way to counterbalance the division created by the different code bases.
One practical concern is that if you have multiple repos all using common internal dependencies you not only have different interests that need to be addressed when working on those dependencies, but you also need to keep everything in sync. Even without common dependencies it can be a hassle to clearly define which version of the server code works with which version of the client code and so on.
Of course in theory you're purely following RESTful HATEOAS conventions and provide a new API version on top of all the existing ones whenever an endpoint changes ever so slightly, but in practice some API consumers are more equal than others and especially during early development you may want to value the speed of iterations over academic purity.
A whole new level of pain begins when you start thinking of concerns like server-side rendering or have server-side concerns that are more about the frontend than about the backend. The division between server-side code and client-side code is rarely the same as the division between frontend (presentation) and backend (persistence). If you use React with server-side rendering you are literally running frontend code on the server.
Instead of strictly saying "client code should live separate from server code" I instead propose the following:
Think about what part of your code addresses concerns that are specific to each frontend (web, native, third-party consumers) and what part of your code addresses backend concerns (e.g. a public REST API or a database CRUD wrapper with auth). Keep each frontend and the backend separate. You may find that some frontends include both a client and a server, others may want to directly interface only with the common backend server, or if you don't need any client-side logic in your web interface there might even be a frontend that only consists of server code.
These divisions are far less arbitrary and far more maintainable than just splitting repos by where a line of code gets executed. And if you realise that the best choice for a project may be keeping it all in one repo, that's okay too.