This is a demonstration of third-party ObjectUI integration using
- @object-ui/app-shell and @object-ui/providers.
+ @object-ui/app-shell and @object-ui/react.
diff --git a/packages/providers/README.md b/packages/providers/README.md
index 3e986a6de1..6082476467 100644
--- a/packages/providers/README.md
+++ b/packages/providers/README.md
@@ -2,7 +2,7 @@
**Reusable Context Providers for ObjectUI**
-A collection of framework-agnostic React context providers that can be used by third-party systems without console dependencies.
+React context providers for ObjectUI applications that third-party systems can use without console dependencies — today, the upload adapter context.
## Installation
@@ -14,97 +14,43 @@ pnpm add @object-ui/providers
Every example below compiles against this package's built types. The values your
own app supplies are written as `declare const` stand-ins so each block stands
-alone, and each stand-in is typed from the prop it is passed to — so the bound
-the example teaches is the bound the package actually declares.
+alone.
-### DataSourceProvider
+### UploadProvider
-Generic data source context that decouples ObjectUI from ObjectStack.
+The ambient upload adapter the `@object-ui/fields` file, image and avatar widgets
+upload through (`useUpload()` reads it). Without a provider they fall back to
+`createObjectUrlAdapter()`, which persists nothing and is a no-crash default, not
+an upload destination.
```tsx
import type { ReactNode } from 'react';
-import { DataSourceProvider, type DataSourceProviderProps } from '@object-ui/providers';
+import { UploadProvider, createObjectStackUploadAdapter } from '@object-ui/providers';
-// `DataSourceProviderProps['dataSource']` is declared `any` today, so this
-// stand-in inherits `any`: the compiler checks nothing about the adapter's
-// shape here (objectui#8160, objectui#7912 track that laundering).
-declare const myCustomDataSource: DataSourceProviderProps['dataSource'];
declare const App: () => ReactNode;
-
-
-
-```
-
-### MetadataProvider
+const adapter = createObjectStackUploadAdapter({ baseUrl: 'https://api.example.com' });
-Schema/metadata management for objects, fields, and views.
-
-```tsx
-import type { ReactNode } from 'react';
-import { MetadataProvider, type MetadataProviderProps } from '@object-ui/providers';
-
-// `MetadataProviderProps['metadata']` is declared `any` today — same bound as
-// `dataSource` above, so nothing about this object's shape is checked here.
-declare const myMetadata: MetadataProviderProps['metadata'];
-declare const App: () => ReactNode;
-
-
+
-
+
```
-### ThemeProvider
-
-Theme management with system theme detection.
-
-`defaultTheme` takes a `ThemePreference` (`auto | light | dark | system`); both
-props are optional.
+`createS3Adapter` and `createAzureBlobAdapter` build adapters for presigned
+S3 and Azure Blob uploads; any object with a `name` and an `upload(file, opts)`
+method is an `UploadAdapter`.
-```tsx
-import type { ReactNode } from 'react';
-import { ThemeProvider } from '@object-ui/providers';
-
-declare const App: () => ReactNode;
+## Retired providers
-
-
-
-```
+`DataSourceProvider` / `useDataSource`, `MetadataProvider` / `useMetadata` and
+`ThemeProvider` / `useTheme` are no longer exported from this package. Use the
+ones the rest of ObjectUI reads instead:
-## Usage Example
-
-`DataSourceProvider` and `MetadataProvider` both declare `children` as required,
-so each one needs a real element inside it — a placeholder comment is not a
-child.
-
-```tsx
-import type { ReactNode } from 'react';
-import {
- DataSourceProvider,
- MetadataProvider,
- ThemeProvider,
- type DataSourceProviderProps,
- type MetadataProviderProps,
-} from '@object-ui/providers';
-
-declare const myDataSource: DataSourceProviderProps['dataSource'];
-declare const myMetadata: MetadataProviderProps['metadata'];
-// Your own component tree goes here.
-declare const AppContent: () => ReactNode;
-
-function App() {
- return (
-
-
-
-
-
-
-
- );
-}
-```
+- the data source: `SchemaRendererProvider` (its `dataSource` prop) from
+ `@object-ui/react`;
+- metadata: `MetadataProvider` / `useMetadata` from `@object-ui/app-shell`;
+- theme: `ThemeProvider` / `useTheme` from `@object-ui/react` (`defaultMode`
+ takes `auto | light | dark`; the old `system` spelling is `auto`).
## Links
diff --git a/packages/providers/src/DataSourceProvider.tsx b/packages/providers/src/DataSourceProvider.tsx
deleted file mode 100644
index 78bcc41ee9..0000000000
--- a/packages/providers/src/DataSourceProvider.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { createContext, useContext } from 'react';
-import type { DataSourceProviderProps } from './types.js';
-
-const DataSourceContext = createContext
(null);
-
-/**
- * DataSourceProvider - Generic data source context
- *
- * Provides data source to child components without coupling to ObjectStack.
- * Third-party systems can inject their own data adapters.
- */
-export function DataSourceProvider({
- dataSource,
- children,
-}: DataSourceProviderProps) {
- return (
-
- {children}
-
- );
-}
-
-/**
- * Hook to access data source from context
- */
-export function useDataSource() {
- const context = useContext(DataSourceContext);
- if (!context) {
- throw new Error('useDataSource must be used within DataSourceProvider');
- }
- return context;
-}
diff --git a/packages/providers/src/MetadataProvider.tsx b/packages/providers/src/MetadataProvider.tsx
deleted file mode 100644
index 1e5c826f9e..0000000000
--- a/packages/providers/src/MetadataProvider.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { createContext, useContext, useState, useEffect } from 'react';
-import type { MetadataProviderProps } from './types.js';
-
-interface MetadataContextValue {
- metadata: any;
- loading: boolean;
- error: string | null;
- refetch: () => void;
-}
-
-const MetadataContext = createContext(null);
-
-/**
- * MetadataProvider - Schema/metadata management
- *
- * Provides application metadata (objects, fields, views) to child components.
- * Can work with static metadata or fetch from API.
- */
-export function MetadataProvider({
- metadata: initialMetadata,
- children,
-}: MetadataProviderProps) {
- const [metadata, setMetadata] = useState(initialMetadata || null);
- const [loading, setLoading] = useState(!initialMetadata);
-
- const refetch = () => {
- // Placeholder for refetch logic
- setLoading(true);
- // In real implementation, this would call the API
- setTimeout(() => {
- setLoading(false);
- }, 100);
- };
-
- useEffect(() => {
- if (initialMetadata) {
- setMetadata(initialMetadata);
- setLoading(false);
- }
- }, [initialMetadata]);
-
- const value: MetadataContextValue = {
- metadata,
- loading,
- error: null,
- refetch,
- };
-
- return (
-
- {children}
-
- );
-}
-
-/**
- * Hook to access metadata from context
- */
-export function useMetadata() {
- const context = useContext(MetadataContext);
- if (!context) {
- throw new Error('useMetadata must be used within MetadataProvider');
- }
- return context;
-}
diff --git a/packages/providers/src/ThemeProvider.tsx b/packages/providers/src/ThemeProvider.tsx
deleted file mode 100644
index da240aa495..0000000000
--- a/packages/providers/src/ThemeProvider.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import { createContext, useContext, useEffect, useState } from 'react';
-import type { ThemePreference, ThemePreferenceProviderProps } from './types.js';
-
-interface ThemeContextValue {
- theme: ThemePreference;
- setTheme: (theme: ThemePreference) => void;
-}
-
-const ThemeContext = createContext(null);
-
-/**
- * ThemeProvider - Theme management
- *
- * Provides theme context and handles system theme detection.
- * Extracted from console for reuse in third-party applications.
- */
-export function ThemeProvider({
- defaultTheme = 'system',
- storageKey = 'ui-theme',
- children,
-}: ThemePreferenceProviderProps) {
- const [theme, setTheme] = useState(() => {
- if (typeof window !== 'undefined') {
- return (localStorage.getItem(storageKey) as ThemePreference) || defaultTheme;
- }
- return defaultTheme;
- });
-
- useEffect(() => {
- const root = window.document.documentElement;
- root.classList.remove('light', 'dark');
-
- // The spec's OS-following mode is `auto` (ThemeModeSchema, ui/theme.zod.ts);
- // `system` is this provider's pre-spec spelling, kept for stored values.
- // Branching on `system` alone sent `auto` into `classList.add('auto')` —
- // a class no Tailwind variant matches, locking the light theme (#2942).
- if (theme === 'auto' || theme === 'system') {
- const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')
- .matches
- ? 'dark'
- : 'light';
- root.classList.add(systemTheme);
- } else {
- root.classList.add(theme);
- }
- }, [theme]);
-
- const value: ThemeContextValue = {
- theme,
- setTheme: (newTheme: ThemePreference) => {
- localStorage.setItem(storageKey, newTheme);
- setTheme(newTheme);
- },
- };
-
- return (
- {children}
- );
-}
-
-/**
- * Hook to access theme from context
- */
-export function useTheme() {
- const context = useContext(ThemeContext);
- if (!context) {
- throw new Error('useTheme must be used within ThemeProvider');
- }
- return context;
-}
diff --git a/packages/providers/src/__tests__/spec-symbol-batch7.test.ts b/packages/providers/src/__tests__/spec-symbol-batch7.test.ts
deleted file mode 100644
index a68d43412f..0000000000
--- a/packages/providers/src/__tests__/spec-symbol-batch7.test.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * ObjectUI
- * Copyright (c) 2024-present ObjectStack Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-/**
- * `ThemePreference` derivation pin
- * (objectui#3161, objectstack#4115 ledger batch 7; re-homed by objectui#5716).
- *
- * `Theme` → `ThemePreference`, derived from the theme MODE vocabulary plus the
- * one legacy spelling this provider still honours. The batch-7 naming
- * judgement is recorded at the declaration in `../types.ts`.
- *
- * This file used to read the vocabulary from the spec's `ThemeModeSchema` and
- * carried a designed tripwire: "if the spec retires `Theme`, this stops
- * compiling and the rename is up for re-triage". The spec DID retire its
- * theme module (objectstack#10485), the re-triage happened, and the
- * objectui#5716 ruling made `@object-ui/types` the vocabulary's owner
- * (`ThemeMode`, with the `THEME_MODES` runtime witness). So the pins below
- * read the new owner — the tripwire fired, was triaged, and is retired.
- */
-
-import { describe, it, expect } from 'vitest';
-import { THEME_MODES } from '@object-ui/types';
-import type { ThemeMode } from '@object-ui/types';
-
-import type { ThemePreference } from '../types';
-
-describe("'system' is this package's own legacy spelling, not the vocabulary's", () => {
- it('reads a non-empty mode tuple from the owner (the probe is not vacuous)', () => {
- expect(Array.isArray(THEME_MODES) && THEME_MODES.length > 0).toBe(true);
- });
-
- it('the vocabulary never declares `system` — the OS-following mode is spelled `auto`', () => {
- expect(THEME_MODES).toContain('auto');
- expect(
- (THEME_MODES as readonly string[]).includes('system'),
- 'the mode vocabulary now declares `system` too — drop the extra union member in types.ts, it is no longer a local alias',
- ).toBe(false);
- });
-});
-
-/* -------------------------------------------------------------------------- */
-/* Compile-time pins — compiled by tsconfig.test.json, chained off type-check. */
-/* -------------------------------------------------------------------------- */
-
-type Assert = T;
-type Equal = (() => T extends A ? 1 : 2) extends () => T extends B ? 1 : 2 ? true : false;
-type IsAny = 0 extends 1 & T ? true : false;
-
-describe('ThemePreference is the mode vocabulary plus one legacy member', () => {
- it('is pinned at compile time', () => {
- // The owner's type is real (not `any`), and the runtime witness and the
- // type are the same vocabulary — the pair cannot drift apart.
- type _OwnerIsReal = Assert, false>>;
- type _WitnessCarriesTheType = Assert>;
-
- // …and this is exactly that vocabulary, plus `system`. Derived, so a mode
- // the owner adds appears here (and `ThemeProvider`'s branch must handle it
- // — `theme-mode-spec-parity.test.tsx` fails at runtime if it does not).
- type _IsTheModeVocabularyPlusLegacy = Assert>;
- type _NothingElseIsLocal = Assert, 'system'>>;
-
- expect(true).toBe(true);
- });
-});
diff --git a/packages/providers/src/__tests__/theme-mode-spec-parity.test.tsx b/packages/providers/src/__tests__/theme-mode-spec-parity.test.tsx
deleted file mode 100644
index b85a0d196b..0000000000
--- a/packages/providers/src/__tests__/theme-mode-spec-parity.test.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * ObjectUI
- * Copyright (c) 2024-present ObjectStack Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-/**
- * Theme mode ↔ vocabulary parity + behavior (#2942).
- *
- * The vocabulary's OS-following mode is `auto`; this provider branched on its
- * pre-spec `system` spelling only, so `mode: 'auto'` fell into
- * `classList.add('auto')` — a class no Tailwind variant matches. The page
- * locked to the light theme, the OS preference was ignored, and nothing
- * errored.
- *
- * The vocabulary read here came from the spec's `ThemeModeSchema` until the
- * spec retired its theme module (objectstack#10485) and the objectui#5716
- * ruling moved ownership to `@object-ui/types` — `THEME_MODES` is the owner's
- * runtime witness, kept as a tuple precisely so this parity coverage stays
- * executable (the `SPEC_GESTURE_TYPES` precedent).
- */
-import { describe, it, expect, beforeEach, vi } from 'vitest';
-import { render } from '@testing-library/react';
-import React from 'react';
-import { THEME_MODES } from '@object-ui/types';
-import { ThemeProvider } from '../ThemeProvider';
-
-function mockMatchMedia(prefersDark: boolean) {
- Object.defineProperty(window, 'matchMedia', {
- writable: true,
- value: vi.fn().mockImplementation((query: string) => ({
- matches: prefersDark,
- media: query,
- addEventListener: vi.fn(),
- removeEventListener: vi.fn(),
- addListener: vi.fn(),
- removeListener: vi.fn(),
- dispatchEvent: vi.fn(),
- onchange: null,
- })),
- });
-}
-
-describe('ThemeProvider covers the theme-mode vocabulary', () => {
- beforeEach(() => {
- document.documentElement.className = '';
- window.localStorage?.clear?.();
- mockMatchMedia(true);
- });
-
- it('reads a non-empty mode tuple from the owner', () => {
- expect(Array.isArray(THEME_MODES) && THEME_MODES.length > 0, 'could not read THEME_MODES').toBe(true);
- });
-
- it('every declared mode resolves to a real light/dark class — never a dead literal', () => {
- for (const mode of THEME_MODES) {
- document.documentElement.className = '';
- const { unmount } = render(
-
-
- ,
- );
- const classes = [...document.documentElement.classList];
- expect(
- classes.some((c) => c === 'light' || c === 'dark'),
- `mode '${mode}' must resolve to light/dark, got [${classes.join(', ')}]`,
- ).toBe(true);
- expect(classes, `mode '${mode}' leaked a dead class`).not.toContain(mode === 'auto' ? 'auto' : '__never__');
- unmount();
- }
- });
-
- it("'auto' follows the OS preference (dark here)", () => {
- render(
-
-
- ,
- );
- expect(document.documentElement.classList.contains('dark')).toBe(true);
- });
-
- it("legacy 'system' keeps following the OS preference", () => {
- render(
-
-
- ,
- );
- expect(document.documentElement.classList.contains('dark')).toBe(true);
- });
-});
diff --git a/packages/providers/src/index.ts b/packages/providers/src/index.ts
index 46ec9b4b3f..eeab3e9c2a 100644
--- a/packages/providers/src/index.ts
+++ b/packages/providers/src/index.ts
@@ -4,9 +4,10 @@
* Reusable context providers for ObjectUI applications
*/
-export { DataSourceProvider, useDataSource } from './DataSourceProvider.js';
-export { MetadataProvider, useMetadata } from './MetadataProvider.js';
-export { ThemeProvider, useTheme } from './ThemeProvider.js';
+// `DataSourceProvider` / `useDataSource`, `MetadataProvider` / `useMetadata`
+// and `ThemeProvider` / `useTheme` retired in objectui#13453: they duplicated
+// names `@object-ui/react` and `@object-ui/app-shell` publish with different
+// implementations, and nothing in the repo but one example read them.
export {
UploadProvider,
useUpload,
@@ -16,13 +17,6 @@ export {
createObjectStackUploadAdapter,
} from './UploadProvider.js';
-export type {
- DataSourceProviderProps,
- MetadataProviderProps,
- ThemePreferenceProviderProps,
- ThemePreference,
-} from './types.js';
-
export type {
UploadAdapter,
UploadOptions,
diff --git a/packages/providers/src/types.ts b/packages/providers/src/types.ts
deleted file mode 100644
index d8fc9eb49e..0000000000
--- a/packages/providers/src/types.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import type { ReactNode } from 'react';
-import type { ThemeMode } from '@object-ui/types';
-
-export interface DataSourceProviderProps {
- dataSource: any;
- children: ReactNode;
-}
-
-export interface MetadataProviderProps {
- metadata?: any;
- children: ReactNode;
-}
-
-/**
- * The theme MODE this provider stores and applies: the `ThemeMode` vocabulary
- * (`auto | light | dark`) plus the one legacy spelling this package still
- * accepts.
- *
- * Named `ThemePreference`, not `Theme` (objectui#3161, objectstack#4115 ledger
- * batch 7). `Theme` names a whole theme DOCUMENT — `{ name, label, mode,
- * colors: { primary, background, … }, typography, … }` — so the old local
- * declaration was not a drifted copy of that document type at all; it was
- * `Theme['mode']` under `Theme`'s name, which is the more misleading of the
- * two failures: a session reading `Theme` here would conclude an ObjectStack
- * theme is a string. `ThemeMode`, the vocabulary's own name for what this
- * really is, could not be taken either (the "run the new name past the guard
- * first" rule from objectui#3169 — it would have traded one collision for
- * another); and it would be wrong anyway, because of `'system'`.
- *
- * Derivation history (objectui#5716): this union was born reading the spec's
- * `ThemeModeSchema` through its `_zod` input carrier. The spec then retired
- * its whole theme module (objectstack `35ad101bc`), objectui assumed ownership of
- * the theme document types, and the mode vocabulary's owner is now
- * `@object-ui/types` (`ThemeMode`, with the `THEME_MODES` runtime witness) —
- * so the derivation reads from there. A mode the owner adds still arrives
- * here and `ThemeProvider`'s branch must handle it. `'system'` stays as an
- * explicit local union member: it is the pre-spec spelling of `auto`, still
- * sitting in users' `localStorage`, and the provider treats the two
- * identically (#2942, pinned in `theme-mode-spec-parity`).
- */
-export type ThemePreference = ThemeMode | 'system';
-
-/**
- * Props of this package's `ThemeProvider`, which stores one
- * {@link ThemePreference} and applies it as the `light` / `dark` class.
- *
- * Named `ThemePreferenceProviderProps`, not `ThemeProviderProps`
- * (objectui#6349, batch 10). `@object-ui/react` publishes a
- * `ThemeProviderProps` with a different meaning: the props of its theme-system
- * `ThemeProvider`, which registers whole `Theme` documents and turns the
- * active one into CSS variables. There `defaultTheme` is a theme NAME and the
- * mode is `defaultMode`; here `defaultTheme` is the mode itself. One exported
- * name stood for both, so this, the narrower of the two, takes the specific
- * name and react keeps the general one.
- */
-export interface ThemePreferenceProviderProps {
- defaultTheme?: ThemePreference;
- storageKey?: string;
- children: ReactNode;
-}
diff --git a/packages/types/src/__tests__/p2-spec-exports.test.ts b/packages/types/src/__tests__/p2-spec-exports.test.ts
index b2f6d20060..77cbec3680 100644
--- a/packages/types/src/__tests__/p2-spec-exports.test.ts
+++ b/packages/types/src/__tests__/p2-spec-exports.test.ts
@@ -252,8 +252,8 @@ describe('v3.0.10 Spec Protocol New Types', () => {
// that the spec publishes a live `ThemeModeSchema` validator, and
// objectstack#10485 (PR objectstack#10695) retired the spec's entire theme
// module — there is no upstream referent left to assert against
- // (objectui#5710). The provider's own mode handling stays covered by
- // `packages/providers/src/__tests__/theme-mode-spec-parity.test.tsx`.
+ // (objectui#5710). The mode-only provider that test pointed at retired with
+ // the `@object-ui/providers` theme trio (objectui#13453).
});
describe('Type re-exports from @object-ui/types index', () => {
it('should re-export P2.3 types (compile-time verification)', async () => {
diff --git a/packages/types/src/theme.ts b/packages/types/src/theme.ts
index 007f6d5b2e..4f4c043043 100644
--- a/packages/types/src/theme.ts
+++ b/packages/types/src/theme.ts
@@ -61,12 +61,11 @@
* The theme mode vocabulary, as a runtime tuple.
*
* A runtime `as const` tuple rather than a bare union, deliberately — the
- * `SPEC_GESTURE_TYPES` precedent in `./mobile.ts`: the parity pins in
- * `@object-ui/providers` (`theme-mode-spec-parity.test.tsx`,
- * `spec-symbol-batch7.test.ts`) read the mode vocabulary at runtime, and this
- * tuple keeps those pins executable against the vocabulary's owner. A
- * type-only union would have left them nothing to read, which is how a
- * retirement quietly takes working coverage with it.
+ * `SPEC_GESTURE_TYPES` precedent in `./mobile.ts`: a pin can read the mode
+ * vocabulary at runtime against its owner, where a type-only union would
+ * leave it nothing to read, which is how a retirement quietly takes working
+ * coverage with it. (Its first readers, the parity pins of the
+ * `@object-ui/providers` theme provider, retired with it in objectui#13453.)
*/
export const THEME_MODES = ['auto', 'light', 'dark'] as const;
@@ -74,9 +73,9 @@ export const THEME_MODES = ['auto', 'light', 'dark'] as const;
* Theme display mode. `auto` follows the OS preference.
*
* Owned here since the upstream theme retirement (objectui#5716). Note the
- * pre-spec `'system'` spelling is NOT part of this vocabulary — it is
- * `@object-ui/providers`' own legacy alias of `auto`, declared there on
- * `ThemePreference` (objectui#2942).
+ * pre-spec `'system'` spelling is NOT part of this vocabulary — it was the
+ * legacy alias of `auto` on `@object-ui/providers`' `ThemePreference`
+ * (objectui#2942), which retired in objectui#13453.
*/
export type ThemeMode = (typeof THEME_MODES)[number];
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 904fc88232..3d07c753f4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -492,9 +492,6 @@ importers:
'@object-ui/plugin-view':
specifier: workspace:*
version: link:../../packages/plugin-view
- '@object-ui/providers':
- specifier: workspace:*
- version: link:../../packages/providers
'@object-ui/react':
specifier: workspace:*
version: link:../../packages/react
diff --git a/scripts/__tests__/one-authority-per-exported-name-6273.test.ts b/scripts/__tests__/one-authority-per-exported-name-6273.test.ts
index 6fbf07fe1b..88c22418bb 100644
--- a/scripts/__tests__/one-authority-per-exported-name-6273.test.ts
+++ b/scripts/__tests__/one-authority-per-exported-name-6273.test.ts
@@ -622,8 +622,11 @@ const KNOWN_COLLISIONS: ReadonlyMap = new Map([
// RENAME branch: providers' declaration now spells
// `ThemePreferenceProviderProps`, and the providers root publishes that name
// instead; react keeps the general one. The two `ThemeProvider` components
- // keep their names — value names are outside this gate's bound
- // (objectui#6349, batch 10).
+ // kept their names — value names are outside this gate's bound
+ // (objectui#6349, batch 10). objectui#13453 then retired the providers
+ // copy outright (`ThemeProvider`, `ThemePreferenceProviderProps`, and the
+ // `DataSourceProvider` / `MetadataProvider` beside it), so react's is the
+ // only `ThemeProvider` left.
// `TranslateFn` sat here — i18next's `t` narrowed to `(key, options?) => string`,
// declared BYTE-IDENTICALLY in three files (one sha256 across the three).
// objectui#8165 re-pointed `packages/app-shell/src/providers/saveAdvisoryToast.ts`
diff --git a/skills/objectui/README.md b/skills/objectui/README.md
index 05c91c0bb6..735c9c4c5a 100644
--- a/skills/objectui/README.md
+++ b/skills/objectui/README.md
@@ -53,7 +53,7 @@ The published packages this skill covers. Nothing checks this list against the
- **Core renderer:** `@object-ui/types`, `core`, `components`, `fields`, `layout`, `react`
- **Parsing & runtime:** `@object-ui/sdui-parser`, `react-runtime`
-- **Integration:** `@object-ui/app-shell`, `providers`, `runner`, `data-objectstack`
+- **Integration:** `@object-ui/app-shell`, `providers`, `data-objectstack`
- **Platform features:** `@object-ui/auth`, `permissions`, `i18n`, `mobile`, `collaboration`
- **Plugins (19):** `plugin-{grid, list, detail, form, kanban, calendar, timeline, gantt, dashboard, report, charts, map, editor, markdown, view, tree, designer, ai, chatbot}`
- **Tooling:** `@object-ui/cli`, `create-plugin`, `vscode-extension`
diff --git a/skills/objectui/guides/architecture.md b/skills/objectui/guides/architecture.md
index d7c5cbd3fd..41cd002aa7 100644
--- a/skills/objectui/guides/architecture.md
+++ b/skills/objectui/guides/architecture.md
@@ -9,8 +9,8 @@ integration package to install. Day-to-day schema authoring is
## Choosing an integration package
-- **Embedding ObjectUI into a third-party React app with your own router/shell?** → use `@object-ui/app-shell` + `@object-ui/providers`.
-- **Running a schema as a standalone app?** → use `@object-ui/runner` or the `objectui` CLI.
+- **Embedding ObjectUI into a third-party React app with your own router/shell?** → use `@object-ui/app-shell` + `@object-ui/react` (`SchemaRendererProvider`, `ThemeProvider`).
+- **Running a schema as a standalone app?** → use the `objectui` CLI (`objectui dev`).
- **Custom rendering only (no shell)?** → use `@object-ui/react` (`SchemaRenderer`) directly.
## The JSON Protocol (The "DNA")
diff --git a/skills/objectui/guides/project-setup.md b/skills/objectui/guides/project-setup.md
index 157185816d..648280c009 100644
--- a/skills/objectui/guides/project-setup.md
+++ b/skills/objectui/guides/project-setup.md
@@ -89,12 +89,13 @@ Opt-in platform packages (auth, i18n, mobile, realtime):
}
```
-Embedding shell + provider stack into a third-party app:
+Embedding the shell into a third-party app (the theme and data-source providers come
+from `@object-ui/react`):
```json
{
"@object-ui/app-shell": "latest",
- "@object-ui/providers": "latest"
+ "@object-ui/react": "latest"
}
```
@@ -236,23 +237,26 @@ import { SchemaRenderer, SchemaRendererProvider } from '@object-ui/react';
```
-### `@object-ui/providers` — reusable context stack
+### Context providers
-Framework-agnostic providers without console-specific dependencies:
+The provider stack for a third-party app comes from the packages that read it:
-- `DataSourceProvider` / `useDataSource` — generic data source binding.
-- `MetadataProvider` / `useMetadata` — apps / objects / dashboards / pages metadata.
-- `ThemeProvider` / `useTheme` — light/dark/system theming wired to Shadcn variables.
+- `SchemaRendererProvider` (`@object-ui/react`) — the ambient data source; pass the
+ adapter as its `dataSource` prop.
+- `ThemeProvider` / `useTheme` (`@object-ui/react`) — theme documents and the
+ `auto` / `light` / `dark` mode.
+- `MetadataProvider` / `useMetadata` (`@object-ui/app-shell`) — apps / objects /
+ dashboards / pages metadata from the API.
+- `UploadProvider` / `useUpload` (`@object-ui/providers`) — the upload adapter the
+ file and image fields upload through.
```tsx
-import { DataSourceProvider, MetadataProvider, ThemeProvider } from '@object-ui/providers';
-
-
-
-
-
-
-
+import { SchemaRendererProvider, ThemeProvider } from '@object-ui/react';
+
+
+
+
+
```
@@ -290,23 +294,21 @@ takes no `objectName` prop. Its props are the exported `ConsoleObjectViewProps`
mount from the "ObjectView" section of `packages/app-shell/README.md`: that block is
the one `pnpm check:doc-snippets` compiles, and this guide does not restate it.
-### `@object-ui/runner` — universal runtime
+### Running a schema as a standalone app
-Standalone runtime + dev server with `plugin-charts` and `plugin-kanban`
-pre-registered, for running a schema as a one-off app with no project
-scaffolding. Usually reached through the `objectui dev` CLI, which wraps the
-same renderer; no app in this repo's `apps/` or `examples/` imports it directly.
+Use the `objectui dev` CLI (`@object-ui/cli`). The repository's `packages/runner` is
+a private workspace demo app, not a published package.
### Decision matrix
| Need | Use |
|------|-----|
| Bare renderer in existing app | `@object-ui/react` |
-| Need shared providers (data/metadata/theme) | + `@object-ui/providers` |
+| Need the data-source / theme providers | `SchemaRendererProvider`, `ThemeProvider` from `@object-ui/react` |
+| Need file / image uploads | + `@object-ui/providers` (`UploadProvider`) |
| Need shell + object/dashboard/page/record views | + `@object-ui/app-shell` |
| Need full admin console (sidebar, system hub, navigation) | study `apps/console` patterns |
| Need a CLI-driven dev server | `@object-ui/cli` (`objectui dev`) |
-| Need a standalone runtime bundle | `@object-ui/runner` |
## Deployment