Start with the shape of the screen
Maintainable Compose screens usually begin with clear ownership. The screen should know how to arrange state and actions, while smaller composables focus on rendering one part of the interface well.
That split keeps product changes manageable. When a requirement moves, you can update the affected surface without untangling every visual detail from navigation, state mapping, and side effects.
Keep state boring
I prefer screen state that reads like a product snapshot: loading, empty, content, and error states with names that match what the user sees. It is easier to test and easier for another engineer to reason about later.
The same idea applies to events. A small set of intentional actions is easier to maintain than passing callbacks through a deep tree with unclear responsibility.
Design for the next change
A Compose implementation does not need heavy abstraction on day one. It needs clean seams around real variation: repeated sections, product states, and components that are likely to appear across multiple screens.
The goal is not clever code. The goal is a UI that can survive iteration without turning every change into a rewrite.