diff --git a/src/config/page-loader.ts b/src/config/page-loader.ts
index f3bc453..1f8f74e 100644
--- a/src/config/page-loader.ts
+++ b/src/config/page-loader.ts
@@ -1,4 +1,5 @@
import pagesConfig from './pages.json'
+import { PageSchema } from '@/types/json-ui'
import { FeatureToggles } from '@/types/project'
export interface PropConfig {
@@ -23,7 +24,10 @@ export interface PageConfig {
id: string
title: string
icon: string
- component: string
+ component?: string
+ type?: 'json' | 'component'
+ schemaPath?: string
+ schema?: PageSchema
enabled: boolean
isRoot?: boolean
toggleKey?: string
diff --git a/src/config/validate-config.ts b/src/config/validate-config.ts
index 63bb357..3b2b428 100644
--- a/src/config/validate-config.ts
+++ b/src/config/validate-config.ts
@@ -57,7 +57,9 @@ export function validatePageConfig(): ValidationError[] {
})
}
- if (!page.component) {
+ const isJsonPage = page.type === 'json' || Boolean(page.schemaPath)
+
+ if (!page.component && !isJsonPage) {
errors.push({
page: page.id || 'Unknown',
field: 'component',
@@ -66,6 +68,15 @@ export function validatePageConfig(): ValidationError[] {
})
}
+ if (isJsonPage && !page.schemaPath && !page.schema) {
+ errors.push({
+ page: page.id || 'Unknown',
+ field: 'schemaPath',
+ message: 'schemaPath is required for JSON pages',
+ severity: 'error',
+ })
+ }
+
if (!page.icon) {
errors.push({
page: page.id || 'Unknown',
diff --git a/src/router/routes.tsx b/src/router/routes.tsx
index 2431aa3..125694b 100644
--- a/src/router/routes.tsx
+++ b/src/router/routes.tsx
@@ -1,9 +1,11 @@
import { lazy, Suspense } from 'react'
import { RouteObject, Navigate } from 'react-router-dom'
import { LoadingFallback } from '@/components/molecules'
+import { JSONSchemaPageLoader } from '@/components/JSONSchemaPageLoader'
import { NotFoundPage } from '@/components/NotFoundPage'
import { getEnabledPages, resolveProps } from '@/config/page-loader'
import { ComponentRegistry } from '@/lib/component-registry'
+import { PageRenderer } from '@/lib/json-ui/page-renderer'
import { FeatureToggles } from '@/types/project'
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
@@ -87,6 +89,21 @@ export function createRoutes(
const rootPage = enabledPages.find(p => p.isRoot)
console.log('[ROUTES] ๐ Root page search result:', rootPage ? `Found: ${rootPage.id} (${rootPage.component})` : 'NOT FOUND - will redirect to /dashboard')
+ const renderJsonPage = (page: typeof enabledPages[number]) => {
+ if (page.schema) {
+ console.log('[ROUTES] ๐งพ Rendering preloaded JSON schema for page:', page.id)
+ return
+ }
+
+ if (page.schemaPath) {
+ console.log('[ROUTES] ๐งพ Rendering JSON schema loader for page:', page.id)
+ return
+ }
+
+ console.error('[ROUTES] โ JSON page missing schemaPath:', page.id)
+ return
+ }
+
const routes: RouteObject[] = enabledPages
.filter(p => !p.isRoot)
.map(page => {
@@ -96,11 +113,26 @@ export function createRoutes(
? resolveProps(page.props, stateContext, actionContext)
: {}
+ if (page.type === 'json' || page.schemaPath) {
+ return {
+ path: `/${page.id}`,
+ element: renderJsonPage(page)
+ }
+ }
+
if (page.requiresResizable && page.resizableConfig) {
console.log('[ROUTES] ๐ Page requires resizable layout:', page.id)
const config = page.resizableConfig
const leftProps = resolveProps(config.leftProps, stateContext, actionContext)
+ if (!page.component) {
+ console.error('[ROUTES] โ Resizable page missing component:', page.id)
+ return {
+ path: `/${page.id}`,
+ element:
+ }
+ }
+
return {
path: `/${page.id}`,
element: (
@@ -115,6 +147,14 @@ export function createRoutes(
}
}
+ if (!page.component) {
+ console.error('[ROUTES] โ Page missing component:', page.id)
+ return {
+ path: `/${page.id}`,
+ element:
+ }
+ }
+
return {
path: `/${page.id}`,
element:
@@ -127,10 +167,23 @@ export function createRoutes(
? resolveProps(rootPage.props, stateContext, actionContext)
: {}
- routes.push({
- path: '/',
- element:
- })
+ if (rootPage.type === 'json' || rootPage.schemaPath) {
+ routes.push({
+ path: '/',
+ element: renderJsonPage(rootPage)
+ })
+ } else if (!rootPage.component) {
+ console.error('[ROUTES] โ Root page missing component:', rootPage.id)
+ routes.push({
+ path: '/',
+ element:
+ })
+ } else {
+ routes.push({
+ path: '/',
+ element:
+ })
+ }
} else {
console.log('[ROUTES] โ ๏ธ No root page in config, redirecting to /dashboard')
routes.push({
diff --git a/src/types/page-config.ts b/src/types/page-config.ts
index ba33b45..54ab9e7 100644
--- a/src/types/page-config.ts
+++ b/src/types/page-config.ts
@@ -1,3 +1,4 @@
+import { PageSchema } from './json-ui'
import { PropConfig } from './prop-config'
import { ResizableConfig } from './resizable-config'
@@ -6,7 +7,9 @@ export interface PageConfig {
title: string
icon: string
component?: string
- schema?: string
+ type?: 'json' | 'component'
+ schemaPath?: string
+ schema?: PageSchema
enabled: boolean
isRoot?: boolean
toggleKey?: string