I'm writing this blog post from an admin interface I built, which is a web app frontend for the backend behind peterbe.com. It's built as a single-page app in Vite, with React.
Vite, unlike frameworks like Remix or Next, doesn't come with its own routing. You have to add that yourself. I added React Router. Another thing you have to do yourself is a way to load remote data into the app for display and for manipulation. This is done as XHR requests happen on the client side. For that, I chose TanStack Query. If you haven't used it but used React, it's sugar for this type of code:
// DON'T DO THIS. USE TANSTACK QUERY
const [stuff, setStuff] = useState(null)
const [error, setError] = useState(null)
useEffect(() => {
fetch('/api/some/thing')
.then(r => r.json())
.then(data => setStuff(data)
.catch(err => setError(err))
}, [])