The past 2 years have seen some advancements in full-stack frameworks with streaming components. Such as NextJS with React Server Components or .NET Blazor.
Those would be my preference for an app that doesn't need a public API. If each partial layout and page component does it's own data loading server side, you can skip GraphQL or making a Full Page API and partial update APIs.
Part of the problem with this is organizational though. For the past decade teams have largely been split between frontend/backend who typically work in 2 completely different languages/frameworks. The steaming components approach is a switch back to full stack and a single language/framework. Also every language doesn't have one of these streaming component frameworks, so it's not really possible to do an app completely in Go for example.
Those would be my preference for an app that doesn't need a public API. If each partial layout and page component does it's own data loading server side, you can skip GraphQL or making a Full Page API and partial update APIs.
Part of the problem with this is organizational though. For the past decade teams have largely been split between frontend/backend who typically work in 2 completely different languages/frameworks. The steaming components approach is a switch back to full stack and a single language/framework. Also every language doesn't have one of these streaming component frameworks, so it's not really possible to do an app completely in Go for example.