Nice. A couple of quibbles
.I'd question the use of ObservedObject, namely using UserViewModel in LoginView and ProfileView. Realize just a demo, but a view model, by definition, should usually be private to a given view. Passing them around should be a telltale flag that your view model is no such thing.
Using Combine for the stock publisher is fine, but in an article on performance I'd expect to see removeDuplicates in the stream to minimize UI updates.
Totally agree on view composition. That's SwiftUI's superpower.