@@ -30,6 +30,10 @@ const ReportView = lazy(() => import('./components/ReportView').then(m => ({ def
3030const ViewDesignerPage = lazy ( ( ) => import ( './components/ViewDesignerPage' ) . then ( m => ( { default : m . ViewDesignerPage } ) ) ) ;
3131const SearchResultsPage = lazy ( ( ) => import ( './components/SearchResultsPage' ) . then ( m => ( { default : m . SearchResultsPage } ) ) ) ;
3232
33+ // App Creation / Edit Pages (lazy — only needed during app management)
34+ const CreateAppPage = lazy ( ( ) => import ( './pages/CreateAppPage' ) . then ( m => ( { default : m . CreateAppPage } ) ) ) ;
35+ const EditAppPage = lazy ( ( ) => import ( './pages/EditAppPage' ) . then ( m => ( { default : m . EditAppPage } ) ) ) ;
36+
3337// Auth Pages (lazy — only needed before login)
3438const LoginPage = lazy ( ( ) => import ( './pages/LoginPage' ) . then ( m => ( { default : m . LoginPage } ) ) ) ;
3539const RegisterPage = lazy ( ( ) => import ( './pages/RegisterPage' ) . then ( m => ( { default : m . RegisterPage } ) ) ) ;
@@ -246,14 +250,37 @@ export function AppContent() {
246250 ) ;
247251
248252 if ( ! dataSource || metadataLoading ) return < LoadingScreen /> ;
249- if ( ! activeApp ) return (
253+
254+ // Allow create-app route even when no active app exists
255+ const isCreateAppRoute = location . pathname . endsWith ( '/create-app' ) ;
256+
257+ if ( ! activeApp && ! isCreateAppRoute ) return (
250258 < div className = "h-screen flex items-center justify-center" >
251259 < Empty >
252260 < EmptyTitle > No Apps Configured</ EmptyTitle >
261+ < EmptyDescription > No applications have been registered.</ EmptyDescription >
262+ < button
263+ className = "mt-4 inline-flex items-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90"
264+ onClick = { ( ) => navigate ( 'create-app' ) }
265+ data-testid = "create-first-app-btn"
266+ >
267+ Create Your First App
268+ </ button >
253269 </ Empty >
254270 </ div >
255271 ) ;
256272
273+ // When on create-app without an active app, render a minimal layout with just the wizard
274+ if ( ! activeApp && isCreateAppRoute ) {
275+ return (
276+ < Suspense fallback = { < LoadingScreen /> } >
277+ < Routes >
278+ < Route path = "create-app" element = { < CreateAppPage /> } />
279+ </ Routes >
280+ </ Suspense >
281+ ) ;
282+ }
283+
257284 // Expression context for dynamic visibility/disabled/hidden expressions
258285 const expressionUser = user
259286 ? { name : user . name , email : user . email , role : user . role ?? 'user' }
@@ -331,6 +358,10 @@ export function AppContent() {
331358 < SearchResultsPage />
332359 } />
333360
361+ { /* App Creation & Editing */ }
362+ < Route path = "create-app" element = { < CreateAppPage /> } />
363+ < Route path = "edit-app/:editAppName" element = { < EditAppPage /> } />
364+
334365 { /* System Administration Routes */ }
335366 < Route path = "system/users" element = { < UserManagementPage /> } />
336367 < Route path = "system/organizations" element = { < OrgManagementPage /> } />
@@ -402,6 +433,7 @@ function findFirstRoute(items: any[]): string {
402433// Redirect root to default app
403434function RootRedirect ( ) {
404435 const { apps, loading, error } = useMetadata ( ) ;
436+ const navigate = useNavigate ( ) ;
405437 const activeApps = apps . filter ( ( a : any ) => a . active !== false ) ;
406438 const defaultApp = activeApps . find ( ( a : any ) => a . isDefault === true ) || activeApps [ 0 ] ;
407439
@@ -416,6 +448,15 @@ function RootRedirect() {
416448 < EmptyDescription >
417449 { error ? error . message : 'No applications have been registered. Check your ObjectStack configuration.' }
418450 </ EmptyDescription >
451+ { ! error && (
452+ < button
453+ className = "mt-4 inline-flex items-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90"
454+ onClick = { ( ) => navigate ( '/apps/_new/create-app' ) }
455+ data-testid = "create-first-app-btn"
456+ >
457+ Create Your First App
458+ </ button >
459+ ) }
419460 </ Empty >
420461 </ div >
421462 ) ;
0 commit comments