@@ -81,6 +81,11 @@ export const UrlNavItemSchema = BaseNavItemSchema.extend({
8181 * 5. Interface Navigation Item
8282 * Navigates to a specific Interface (self-contained multi-page surface).
8383 * Bridges AppSchema (navigation container) with InterfaceSchema (content surface).
84+ *
85+ * **Note:** While this schema remains for backward compatibility, the preferred pattern
86+ * is now to use `AppSchema.interfaces[]` to declare interfaces, which automatically
87+ * generates a two-level Interface→Pages sidebar menu. This navigation item type is
88+ * retained for explicit interface navigation and global utility entries.
8489 */
8590export const InterfaceNavItemSchema = BaseNavItemSchema . extend ( {
8691 type : z . literal ( 'interface' ) ,
@@ -152,16 +157,21 @@ export const AppBrandingSchema = z.object({
152157 * App Configuration Schema
153158 * Defines a business application container, including its navigation, branding, and permissions.
154159 *
155- * @example CRM App
160+ * The new architecture makes App an "Interface switcher" where the sidebar content is
161+ * auto-generated from `interfaces[]`, rendering a two-level Interface→Pages menu. The
162+ * `navigation[]` field is retained for global utility entries only (Settings, Help,
163+ * external links) and is rendered at the bottom of the sidebar.
164+ *
165+ * @example CRM App with new Interface-driven pattern
156166 * {
157167 * name: "crm",
158168 * label: "Sales CRM",
159169 * icon: "briefcase",
170+ * interfaces: ["sales_workspace", "lead_review", "sales_analytics"],
171+ * defaultInterface: "sales_workspace",
160172 * navigation: [
161- * { type: "object", id: "nav_leads", label: "Leads", objectName: "leads" },
162- * { type: "object", id: "nav_deals", label: "Deals", objectName: "deals" }
163- * ],
164- * requiredPermissions: ["app.crm.access"]
173+ * { type: "page", id: "nav_settings", label: "Settings", pageName: "admin_settings" }
174+ * ]
165175 * }
166176 */
167177export const AppSchema = z . object ( {
@@ -190,10 +200,28 @@ export const AppSchema = z.object({
190200 isDefault : z . boolean ( ) . optional ( ) . default ( false ) . describe ( 'Is default app' ) ,
191201
192202 /**
193- * Navigation Tree Structure.
194- * Replaces the old flat 'tabs' list with a structured menu.
203+ * Interface names registered in this App.
204+ * Sidebar renders as a two-level menu: Interface (collapsible group) → Pages (menu items).
205+ * The runtime auto-generates the sidebar navigation from these interfaces and their pages.
206+ */
207+ interfaces : z . array ( z . string ( ) ) . optional ( )
208+ . describe ( 'Interface names available in this App. Sidebar renders as Interface→Pages two-level menu.' ) ,
209+
210+ /** Default interface to activate on App launch */
211+ defaultInterface : z . string ( ) . optional ( )
212+ . describe ( 'Default interface to show when the App opens' ) ,
213+
214+ /**
215+ * Navigation Tree Structure (Global Utility Entries Only).
216+ * This field is now repurposed for global utility navigation items only (Settings, Help,
217+ * external links, etc.) that are rendered at the bottom of the sidebar. The main sidebar
218+ * content is auto-generated from `interfaces[]`.
219+ *
220+ * For backward compatibility, this field remains optional and can still contain the full
221+ * navigation tree. However, the new recommended pattern is to use `interfaces[]` for
222+ * the main navigation and reserve this field for global utility entries.
195223 */
196- navigation : z . array ( NavigationItemSchema ) . optional ( ) . describe ( 'Structured navigation menu tree ' ) ,
224+ navigation : z . array ( NavigationItemSchema ) . optional ( ) . describe ( 'Global utility navigation items (Settings, Help, external links) — rendered at bottom of sidebar ' ) ,
197225
198226 /**
199227 * App-level Home Page Override
@@ -241,7 +269,20 @@ export const App = {
241269 *
242270 * Validates the config at creation time using Zod `.parse()`.
243271 *
244- * @example
272+ * @example New Interface-driven pattern
273+ * ```ts
274+ * const crmApp = defineApp({
275+ * name: 'crm',
276+ * label: 'CRM',
277+ * interfaces: ['sales_workspace', 'lead_review', 'sales_analytics'],
278+ * defaultInterface: 'sales_workspace',
279+ * navigation: [
280+ * { id: 'nav_settings', label: 'Settings', type: 'page', pageName: 'settings' },
281+ * ],
282+ * });
283+ * ```
284+ *
285+ * @example Legacy navigation tree pattern (backward compatible)
245286 * ```ts
246287 * const crmApp = defineApp({
247288 * name: 'crm',
0 commit comments