[object Object]

A maker is given two weeks to ship an app for the operations team to track equipment maintenance. Canvas app feels flexible but every CRUD operation is hand-wired; model-driven app feels rigid but the CRUD comes free. For 80 percent of internal CRM-style apps, model-driven is the right answer and the perceived rigidity is actually a feature that prevents UX drift.

What Model-Driven Apps Are

Component-based apps built on Dataverse tables. Standard UI metaphors: site map to entity to list to form. Dynamics 365 modules are essentially model-driven apps. The framework owns the rendering and the responsive behavior; the maker owns the schema, the layout, and the business logic.

Model-driven components:
- Site map: navigation
- Entity views: lists
- Forms: record editing
- Dashboards: aggregated views
- Charts: visualizations
- Business process flows: stage progression

The components compose; you do not redesign the navigation for each app, you reuse the framework navigation.

Site Map

The navigation structure: areas, groups, subareas. Role-based filtering hides what users should not see. Keep depth shallow — users hate deep menus. The shallow rule is two levels visible at any time; anything deeper, push to a search-based discovery.

Three-level site map:
Area: Operations
  Group: Equipment
    Subarea: Equipment List
    Subarea: Maintenance Schedule
  Group: Reports
    Subarea: Uptime Dashboard

Role-based filtering ships with the app module. A maintenance technician sees Equipment; a supervisor sees Equipment plus Reports.

Forms

Main forms, quick view forms, card forms. Business Process Flows overlay on main forms to guide stage progression. Keep forms focused; use tabs for grouping. The main form is the most viewed surface; iterate on it like a product.

Form design principles:
- Top section: identity (name, owner, status)
- Tab 1: primary edit fields
- Tab 2: related records (sub-grids)
- Tab 3: history and audit
- Hide rather than show by default; reveal on demand

The hide-by-default discipline keeps the form scannable.

Views

Saved queries on a table. Default views, system views, personal views. Advanced Find creates complex views without code. The default view is the one the user sees most often; tune the columns and filter to match the most common use case, not the edge case.

<fetch>
  <entity name="equipment">
    <attribute name="name" />
    <attribute name="location" />
    <attribute name="last_maintenance" />
    <attribute name="next_maintenance" />
    <filter>
      <condition attribute="statecode" operator="eq" value="0" />
    </filter>
    <order attribute="next_maintenance" />
  </entity>
</fetch>

Sort by next_maintenance ascending so the equipment due soon appears first.

When to Use Model-Driven

CRUD-heavy applications with clear entity relationships. Standard UI is acceptable. For custom UX, canvas apps; for hybrid, use model-driven with embedded canvas. The decision filter is whether the user needs to see and edit records most of the time. If yes, model-driven. If the experience is more workflow-driven or wizard-style, canvas.

Model-driven fits:
- Internal data management apps
- CRM and case-tracking style apps
- Any app where the entity relationship diagram matches the workflow

Canvas fits:
- Mobile-first task apps
- Wizard-style onboarding
- Highly custom UX with brand requirements

App Modules and Persona Slimming

A model-driven app is an App Module that exposes a subset of entities, dashboards, and views to a specific persona. A field tech app and a dispatcher app can share the same Dataverse environment but expose entirely different surfaces. Build app modules per persona, not one app for everyone.

Performance Considerations

Forms with many sub-grids and Quick Views load slower. Audit the form network tab; if the load fires more than four parallel requests, consolidate. Sub-grids should default to small page sizes (10 to 25 rows) to keep the initial paint fast.

What to do this week

Build the site map for your top persona, slim down the default view to six columns, and audit the most-used main form for sub-grid count. Ship one persona-specific app module instead of asking that persona to use the catch-all app.

[object Object]
Share