I tried 4.5 years ago with https://vivavlaanderen.radio2.be/ - disclaimer: the experience isn't great on mobile (design issue, not tech) and the JS/HTML is massive (it was my first JS project ever, so I messed a bit with Webpack etc).
One of the tricks I used is partial rendering. If you click an artist page (the square/rectangular people photos with a name) and have JS enabled it'll first only render the header, then add a few body items, then the rest of the body items. Since we used a horribly inefficient handmade Markdown to JS thing with a renderer in old naive React it took way too long to render them all at the same time, it'd easily lock up the browser for two seconds on a large page.
Another ridiculous thing was to preload enough data to render the top part of every single artist page while you're on the homepage. A complete waste of data, but otherwise navigation would need a request before being able to render something useful and that defeated the point.
I did pay a lot of attention to making it feel like real navigation though. Almost any meaningful interaction modifies the URL, and the site is practically fully functional without JS. Navigation and Cmd-clicking should all work perfectly. Including scroll positions handling. SEO worked really well too.
So for a classic website format, to make client side rendering work, you need:
- a URL for every view change, with regular old <a> elements that have those URLs as href.
- server rendering that actually handles all of those URLs
- something that restores scroll positions on navigation
- phased/batched rendering on click if your initial new view doesn't render in say 100ms (basically faking progressive rendering)
The development experience was a bit frustrating back in the day, and I don't think it paid off. Which is why for the next project (https://www.klara.be) we decided to go back to server rendering, but using React on the server. Some parts of the page (like the coloured box top right on desktop) are rendered as a skeleton on the server, and then React on the client reuses the same exact code to make these parts interactive again. Partial universal React basically, and it worked very well. I think klara.be feels like a nice and snappy site and it was way easier to develop for.