Componentes
Avoid creating huge monolithic components. Instead, try to combine small, concise components to build larger ones that can handle more complex cases. Also, in components, strive to focus on visualizing the model to views, and interacting with the user inputs. Consider delegating domain-specific processing to an external service. Doing so will increase maintainability and simplify the implementation of automated tests. If you plan to release the Hybrid app as not only a mobile or desktop app but also a web application, isolate Razor components and shared classes into a Razor Class library project and reference it from the MAUI project.
Vinculação de dados
It must be better that interaction between components should be done by data binding. Designs that use the "@ref" directives to obtain a component's reference and then use that component's properties and methods are discouraged, except in some scenarios, such as dialog components. For example, if you want to make a particular option initially selected in a drop-down list, don't call the drop-down list's selection method. Instead, implement a field variable that indicates the selected option and two-way bind that field variable to the drop-down list.
Routing
If you are also releasing it as a web application, you should consider designing URL routing that uses "@page" directives. For example, if you are creating a page to search for a listing, include the search keywords in the URL's query string to allow for link-sharing scenarios.
Form Validation
Form validation is recommended to be implemented based on Blazor's "EditForm" and "EditorContext". Blazor provides a declarative form validation mechanism using the "DataAnnotaionValidator" component, based on attributes annotating the model, so it is good to use. Alternatively, various other third-party form validation libraries are also available.
Dependencies
Individual service classes should be simplified under the single responsibility principle. However, doing that will require many service classes to work together. In this case, it is recommended that the "DI (dependency injection)" containers be actively utilized to resolve dependencies between services. Delegating the responsibility of generating service objects to the DI container will massively increase maintainability and productivity.
Also, when using platform-native functionality, you should abstract the functionality into interfaces, implement concrete classes that implement that interface for each platform, and inject and use them in components via the DI Container. Dependency injection is not just for plugging in mocks in unit tests.
State Management
Component-specific UI state, such as an accordion component's open/closed state, should be managed through component field variables or properties. If the application is also published as a web application, consider using URL query parameters to save the UI state. Speaking about global state management, such as sharing color scheme themes across the entire UI components, using cascading parameters will be helpful. The domain-level model will be better handled via dependency injection by making it a service class. Of course, there are various other global state management libraries that you may consider using.
Authentication and Authorization
Do not implement authentication and authorization yourself. Instead, use existing reliable libraries. For the authentication infrastructure, consider using a service called "ID as a Service" instead of relying on your own implementation. When implementing authorization using the OAuth protocol for integration with external web services, especially for desktop or mobile apps, make sure to prevent authorization codes from being stolen due to duplicate registration of custom schemes, like using PKCE.
Automated Testing
Even for hybrid app development, automated testing is essential for sustainable software development and product growth. Isolating domain-specific processing into service classes makes automated tests more effortless to implement and maintain. Unit tests can also be implemented for the UI domain using third-party libraries such as bUnit. If the application is also to be released as a web application, end-to-end testing can also be realized based on the knowledge of web application development by using third-party tools such as Playwright.