-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Q1 2026 Roadmap — i18n package, test infrastructure, perf utilities, quick-start guide #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9d773b8
bd3deb6
16c5d14
f28f350
033b96a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| { | ||
| "title": "Guide", | ||
| "pages": [ | ||
| "quick-start", | ||
| "architecture", | ||
| "schema-rendering", | ||
| "layout", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| --- | ||
| title: "Quick Start" | ||
| description: "Get up and running with ObjectUI in 5 minutes - install, configure, and render your first server-driven UI" | ||
| --- | ||
|
|
||
| # Quick Start | ||
|
|
||
| Get up and running with ObjectUI in **5 minutes**. This guide walks you through installation, basic setup, and rendering your first server-driven UI. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - **Node.js** 20+ | ||
| - **pnpm** 9+ (recommended) or npm/yarn | ||
| - Basic knowledge of **React** and **TypeScript** | ||
|
|
||
| ## Step 1: Create a React Project | ||
|
|
||
| If you don't have an existing React project, create one with Vite: | ||
|
|
||
| ```bash | ||
| pnpm create vite my-app --template react-ts | ||
| cd my-app | ||
| ``` | ||
|
|
||
| ## Step 2: Install ObjectUI | ||
|
|
||
| Install the core ObjectUI packages: | ||
|
|
||
| ```bash | ||
| pnpm add @object-ui/react @object-ui/core @object-ui/types @object-ui/components @object-ui/fields | ||
| ``` | ||
|
|
||
| Install Tailwind CSS (required for styling): | ||
|
|
||
| ```bash | ||
| pnpm add -D tailwindcss @tailwindcss/vite | ||
| ``` | ||
|
|
||
| ## Step 3: Configure Tailwind CSS | ||
|
|
||
| Add Tailwind to your `vite.config.ts`: | ||
|
|
||
| ```ts | ||
| import { defineConfig } from 'vite'; | ||
| import react from '@vitejs/plugin-react'; | ||
| import tailwindcss from '@tailwindcss/vite'; | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [react(), tailwindcss()], | ||
| }); | ||
| ``` | ||
|
|
||
| Add to your `src/index.css`: | ||
|
|
||
| ```css | ||
| @import "tailwindcss"; | ||
| ``` | ||
|
|
||
| ## Step 4: Register Components | ||
|
|
||
| Create `src/setup.ts` to register the built-in components: | ||
|
|
||
| ```ts | ||
| import { Registry } from '@object-ui/core'; | ||
| import { registerAllComponents } from '@object-ui/components'; | ||
| import { registerAllFields } from '@object-ui/fields'; | ||
|
|
||
| // Register the built-in component renderers | ||
| registerAllComponents(Registry); | ||
| registerAllFields(Registry); | ||
| ``` | ||
|
|
||
| ## Step 5: Render Your First UI | ||
|
|
||
| Replace `src/App.tsx` with: | ||
|
|
||
| ```tsx | ||
| import './setup'; | ||
| import { SchemaRenderer } from '@object-ui/react'; | ||
|
|
||
| // Define your UI as JSON schema | ||
| const schema = { | ||
| type: 'form', | ||
| fields: [ | ||
| { | ||
| name: 'name', | ||
| label: 'Full Name', | ||
| type: 'string', | ||
| required: true, | ||
| }, | ||
| { | ||
| name: 'email', | ||
| label: 'Email Address', | ||
| type: 'string', | ||
| widget: 'email', | ||
| }, | ||
| { | ||
| name: 'role', | ||
| label: 'Role', | ||
| type: 'string', | ||
| widget: 'select', | ||
| options: [ | ||
| { label: 'Admin', value: 'admin' }, | ||
| { label: 'Editor', value: 'editor' }, | ||
| { label: 'Viewer', value: 'viewer' }, | ||
| ], | ||
| }, | ||
| ], | ||
| submitLabel: 'Create User', | ||
| }; | ||
|
|
||
| function App() { | ||
| return ( | ||
| <div className="max-w-md mx-auto p-8"> | ||
| <h1 className="text-2xl font-bold mb-6">ObjectUI Demo</h1> | ||
| <SchemaRenderer | ||
| schema={schema} | ||
| onSubmit={(data) => { | ||
| console.log('Form submitted:', data); | ||
| alert(JSON.stringify(data, null, 2)); | ||
| }} | ||
| /> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default App; | ||
| ``` | ||
|
|
||
| ## Step 6: Run the App | ||
|
|
||
| ```bash | ||
| pnpm dev | ||
| ``` | ||
|
|
||
| Open [http://localhost:5173](http://localhost:5173) — you should see a fully functional form rendered from JSON! | ||
|
|
||
| ## What Just Happened? | ||
|
|
||
| 1. **JSON Schema** → You defined a form as a JSON object with fields, types, and labels | ||
| 2. **Registry** → Built-in components were registered to handle each schema type | ||
| 3. **SchemaRenderer** → Converted the JSON into interactive React components (Shadcn UI) | ||
| 4. **Zero UI Code** → No JSX needed for the form fields — it's all driven by data | ||
|
|
||
| ## Next Steps | ||
|
|
||
| ### Add a Data Table | ||
|
|
||
| ```tsx | ||
| const tableSchema = { | ||
| type: 'crud', | ||
| resource: 'users', | ||
| columns: [ | ||
| { name: 'name', label: 'Name' }, | ||
| { name: 'email', label: 'Email' }, | ||
| { name: 'role', label: 'Role' }, | ||
| ], | ||
| }; | ||
| ``` | ||
|
|
||
| ### Add Internationalization | ||
|
|
||
| ```bash | ||
| pnpm add @object-ui/i18n | ||
| ``` | ||
|
|
||
| ```tsx | ||
| import { I18nProvider } from '@object-ui/i18n'; | ||
|
|
||
| function App() { | ||
| return ( | ||
| <I18nProvider config={{ defaultLanguage: 'zh' }}> | ||
| <SchemaRenderer schema={schema} /> | ||
| </I18nProvider> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| ### Use Lazy Loading for Plugins | ||
|
|
||
| ```tsx | ||
| import { createLazyPlugin } from '@object-ui/react'; | ||
|
|
||
| const ObjectGrid = createLazyPlugin( | ||
| () => import('@object-ui/plugin-grid'), | ||
| { fallback: <div>Loading grid...</div> } | ||
| ); | ||
| ``` | ||
|
|
||
| ### Learn More | ||
|
|
||
| - [Architecture Overview](/docs/guide/architecture) — Understand how ObjectUI works | ||
| - [Schema Rendering](/docs/guide/schema-rendering) — Deep dive into schema rendering | ||
| - [Component Registry](/docs/guide/component-registry) — Customize and extend components | ||
| - [Plugins](/docs/guide/plugins) — Add views like Grid, Kanban, Charts | ||
| - [Fields Guide](/docs/guide/fields) — All 30+ field types | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { test, expect } from '@playwright/test'; | ||
|
|
||
| /** | ||
| * Smoke test to verify the console app loads correctly. | ||
| * This is a foundational E2E test that validates the basic app shell. | ||
| */ | ||
| test.describe('Console App', () => { | ||
| test('should load the home page', async ({ page }) => { | ||
| await page.goto('/'); | ||
| // Wait for the app to render | ||
| await page.waitForLoadState('networkidle'); | ||
| // The page should have rendered something (not blank) | ||
| const body = page.locator('body'); | ||
| await expect(body).not.toBeEmpty(); | ||
| }); | ||
|
|
||
| test('should display the navigation sidebar', async ({ page }) => { | ||
| await page.goto('/'); | ||
| await page.waitForLoadState('networkidle'); | ||
| // The app shell should contain a navigation area | ||
| const nav = page.locator('nav').first(); | ||
| await expect(nav).toBeVisible(); | ||
| }); | ||
|
|
||
| test('should have correct page title', async ({ page }) => { | ||
| await page.goto('/'); | ||
| await expect(page).toHaveTitle(/.+/); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -61,7 +61,9 @@ | |||||
| "changeset:version": "changeset version", | ||||||
| "changeset:publish": "changeset publish", | ||||||
| "pretest:coverage": "turbo run build --filter=@object-ui/types --filter=@object-ui/core --filter=@object-ui/react --filter=@object-ui/components --filter=@object-ui/fields --filter=@object-ui/layout --filter=@object-ui/plugin-kanban --filter=@object-ui/plugin-charts --filter=@object-ui/plugin-form --filter=@object-ui/plugin-grid --filter=@object-ui/plugin-dashboard", | ||||||
| "test:compliance": "vitest run src/__tests__/compliance.test.tsx" | ||||||
| "test:compliance": "vitest run src/__tests__/compliance.test.tsx", | ||||||
| "test:e2e": "playwright test", | ||||||
| "test:e2e:ui": "playwright test --ui" | ||||||
| }, | ||||||
| "devDependencies": { | ||||||
| "@changesets/cli": "^2.29.8", | ||||||
|
|
@@ -99,6 +101,7 @@ | |||||
| "jsdom": "^28.0.0", | ||||||
| "msw": "^2.12.7", | ||||||
| "msw-storybook-addon": "^2.0.6", | ||||||
| "@playwright/test": "^1.58.2", | ||||||
| "playwright": "^1.58.0", | ||||||
|
||||||
| "playwright": "^1.58.0", | |
| "playwright": "^1.58.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The quick-start guide’s component/field registration snippet doesn’t match the actual APIs here.
@object-ui/componentsregisters renderers via module side-effects (and exportsinitializeComponents()), andregisterAllFields()takes no arguments and registers into the globalComponentRegistry. As written,registerAllComponents(Registry)/registerAllFields(Registry)won’t work andSchemaRendererwon’t find renderers.