I gave a talk recently on some of the best practices for building Angular projects that leverage the best of server side and prerendering, along with providing an API directly in your same project code. Here are a few of the questions some folks have asked me, and their answers.

What are the key deployment challenges for combined server-side rendered apps compared to deploying separate front-end and back-end services?

Generally deploying a unified project that contains both backend APIs and the front-ends that consume them is that you actually guarantee you'll have a match between the two, simplifying APIs dramatically. It's when you don't have control of a client (such as a mobile or desktop app) that we see the biggest problems with deployments of one or the other significantly messing things up.
If you did need a decoupled client, then you would just need to follow the same versioning guidelines and follow the same compatibility best practices.

When adding custom API code into Angular's server.ts file, how do you keep things organized for bigger, more complex projects?

Folllow the same best practices that you would in any ExpressJS or other API process. Generally I like to have a single simple entrypoint that includes references to the major modules of an application (users, posts, reviews, purchases, etc). You can use simple TypeScript imports and exports and a reasonable folder structure to make this much more manageable.
I'm also a fan of things like NestJS that act as a framework for building these types of backends using a component structure that was inspired by Angular.

What's the best way to manage complex application or user state between the server-rendered page and the interactive client-side app?

Generally state transfer is handled automatically for you part of hydration. For pages where first-load performance is critical, I recommend turning off HTTP caching, allowing you to send down less state. In this way you send down only the rendered HTML and not the backing data behind it. The data will be fetch again client-side as part of bootstrap, but this doesn't block the initial load. The default way caches this and prevents the client-side HTTP request.
Here's a sample app config that turns off this HTTP Caching with withNoHttpTransferCache.
export const appConfig: ApplicationConfig = {
    providers: [
        Title,
        PostService,
        AdminService,
        provideBrowserGlobalErrorListeners(),
        provideZonelessChangeDetection(),
        provideCheckNoChangesConfig({ exhaustive: true, interval: 1000 }),
        provideRouter(routes),
        provideClientHydration(withEventReplay(), withNoHttpTransferCache()),
        provideHttpClient(withFetch()),
    ],
};

How do you best handle user login sessions and API security when the same server process is responsible for both rendering pages and answering API calls?

Users sessions and API security are identical to what you would do when you have separate projects. Use technologies like JWT, expiring session tokens, and never ever trust what your client sends you, always verify their credentials on the backend.