diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b4a47e35..f2d22fd5c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
- Dashed border around entered container for visual feedback
- Layer panel click syncs canvas scope automatically
- Vue SDK internationalization primitives — `useI18n()`, locale detection, persisted locale selection, lazy-loaded locale JSON files, and exported locale metadata for custom editor shells
+- Vue SDK docs and public API audit — documented advanced exports (`useOkHCL()`, variables helpers, viewport and locale APIs), aligned docs with the actual `provideEditor()` injection model, and expanded release-ready SDK guidance
- App language picker in the menu bar — switch UI locale without reloading
- Added a vector curve editor and improved drawing experience with the pen tool
- Resume pen drawing from existing open path endpoints — click an endpoint to continue the curve
diff --git a/packages/docs/programmable/sdk/api/advanced/index.md b/packages/docs/programmable/sdk/api/advanced/index.md
index a20664bb6..ed0459183 100644
--- a/packages/docs/programmable/sdk/api/advanced/index.md
+++ b/packages/docs/programmable/sdk/api/advanced/index.md
@@ -13,12 +13,17 @@ These APIs are public, but they are more specialized than the main component and
- [useSceneComputed](./use-scene-computed)
- [usePropScrub](./use-prop-scrub)
-## Picker and editor internals
+## Picker, variables, locale, and editor internals
- [useColorVariableBinding](./use-color-variable-binding)
- [useFillPicker](./use-fill-picker)
- [useGradientStops](./use-gradient-stops)
- [useFontPicker](./use-font-picker)
+- [useOkHCL](./use-okhcl)
+- [useVariables](./use-variables)
+- [useVariablesDialogState](./use-variables-dialog-state)
+- [useVariablesTable](./use-variables-table)
+- [Locale APIs](./locale-apis)
- [useToolbarState](./use-toolbar-state)
- [useNodeFontStatus](./use-node-font-status)
@@ -28,6 +33,7 @@ These APIs are public, but they are more specialized than the main component and
- [useInlineRename](./use-inline-rename)
- [useCanvasDrop](./use-canvas-drop)
- [extractImageFilesFromClipboard](./extract-image-files-from-clipboard)
+- [useViewportKind](./use-viewport-kind)
- [toolCursor](./tool-cursor)
## Primitive context helpers
diff --git a/packages/docs/programmable/sdk/api/advanced/locale-apis.md b/packages/docs/programmable/sdk/api/advanced/locale-apis.md
new file mode 100644
index 000000000..d4ffc3ad2
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/advanced/locale-apis.md
@@ -0,0 +1,39 @@
+---
+title: Locale APIs
+description: Lower-level locale stores and metadata exported by @open-pencil/vue.
+---
+
+# Locale APIs
+
+In addition to `useI18n()`, the Vue SDK exports lower-level locale primitives for advanced integrations:
+
+- `locale`
+- `localeSetting`
+- `setLocale()`
+- `AVAILABLE_LOCALES`
+- `LOCALE_LABELS`
+
+Use these when you want direct store access, need to integrate locale state with a larger app shell, or want locale metadata without subscribing to the full `useI18n()` return object.
+
+## Usage
+
+```ts
+import {
+ locale,
+ localeSetting,
+ setLocale,
+ AVAILABLE_LOCALES,
+ LOCALE_LABELS,
+} from '@open-pencil/vue'
+```
+
+## Notes
+
+- `locale` is the resolved active locale store
+- `localeSetting` is the persisted user preference store
+- `setLocale()` updates the preference and active locale together
+- `AVAILABLE_LOCALES` and `LOCALE_LABELS` are useful for custom pickers
+
+## Related APIs
+
+- [useI18n](../composables/use-i18n)
diff --git a/packages/docs/programmable/sdk/api/advanced/use-okhcl.md b/packages/docs/programmable/sdk/api/advanced/use-okhcl.md
new file mode 100644
index 000000000..667cd71e0
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/advanced/use-okhcl.md
@@ -0,0 +1,38 @@
+---
+title: useOkHCL
+description: Work with RGBA and OkHCL color models for fills and strokes.
+---
+
+# useOkHCL
+
+`useOkHCL()` exposes helpers for reading, enabling, disabling, and updating OkHCL color values on node fills and strokes.
+
+Use it when you are building advanced color tooling that needs to switch between standard RGBA editing and perceptual OkHCL editing.
+
+## Usage
+
+```ts
+import { useOkHCL } from '@open-pencil/vue'
+
+const okhcl = useOkHCL()
+```
+
+## Returns
+
+- `getFillColorModel()`
+- `getStrokeColorModel()`
+- `getFillOkHCLColor()`
+- `getStrokeOkHCLColor()`
+- `enableFillOkHCL()`
+- `disableFillOkHCL()`
+- `enableStrokeOkHCL()`
+- `disableStrokeOkHCL()`
+- `updateFillOkHCL()`
+- `updateStrokeOkHCL()`
+- `modelOptions`
+
+## Related APIs
+
+- [useFillControls](../composables/use-fill-controls)
+- [useStrokeControls](../composables/use-stroke-controls)
+- [ColorPickerRoot](../components/color-picker-root)
diff --git a/packages/docs/programmable/sdk/api/advanced/use-variables-dialog-state.md b/packages/docs/programmable/sdk/api/advanced/use-variables-dialog-state.md
new file mode 100644
index 000000000..90b10b77b
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/advanced/use-variables-dialog-state.md
@@ -0,0 +1,30 @@
+---
+title: useVariablesDialogState
+description: Manage variables dialog editing state on top of useVariables().
+---
+
+# useVariablesDialogState
+
+`useVariablesDialogState()` builds on `useVariables()` and adds dialog-specific editing state for collection renaming and focus management.
+
+Use it when you are building a custom variables dialog rather than only consuming the combined `useVariablesEditor()` helper.
+
+## Usage
+
+```ts
+import { useVariablesDialogState } from '@open-pencil/vue'
+
+const variablesDialog = useVariablesDialogState()
+```
+
+## Adds to useVariables()
+
+- `editingCollectionId`
+- `setCollectionInputRef()`
+- `startRenameCollection()`
+- `commitRenameCollection()`
+
+## Related APIs
+
+- [useVariables](./use-variables)
+- [useVariablesEditor](../composables/use-variables-editor)
diff --git a/packages/docs/programmable/sdk/api/advanced/use-variables-table.md b/packages/docs/programmable/sdk/api/advanced/use-variables-table.md
new file mode 100644
index 000000000..91551cf1d
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/advanced/use-variables-table.md
@@ -0,0 +1,29 @@
+---
+title: useVariablesTable
+description: Build TanStack Table column definitions for OpenPencil variables UIs.
+---
+
+# useVariablesTable
+
+`useVariablesTable(options)` returns reactive TanStack Table column definitions for variables editors.
+
+Use it when you want the SDK's variable-table behavior but need to supply your own table instance, custom icons, or app-specific shell components.
+
+## Usage
+
+```ts
+import { useVariablesTable } from '@open-pencil/vue'
+
+const { columns } = useVariablesTable(options)
+```
+
+## Notes
+
+- this is a specialized integration helper for table-driven variables UIs
+- most consumers should start with `useVariablesEditor()` unless they need finer control
+
+## Related APIs
+
+- [useVariablesEditor](../composables/use-variables-editor)
+- [useVariables](./use-variables)
+- [useVariablesDialogState](./use-variables-dialog-state)
diff --git a/packages/docs/programmable/sdk/api/advanced/use-variables.md b/packages/docs/programmable/sdk/api/advanced/use-variables.md
new file mode 100644
index 000000000..02630cd31
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/advanced/use-variables.md
@@ -0,0 +1,44 @@
+---
+title: useVariables
+description: Read and mutate variable collections, variables, and variable values.
+---
+
+# useVariables
+
+`useVariables()` is the lower-level variables composable behind the higher-level variables editor helpers.
+
+Use it when you want direct control over collections, active modes, filtering, and CRUD operations without taking the full table/dialog abstraction.
+
+## Usage
+
+```ts
+import { useVariables } from '@open-pencil/vue'
+
+const variables = useVariables()
+```
+
+## Returns
+
+- `collections`
+- `activeCollectionId`
+- `activeCollection`
+- `activeModes`
+- `variables`
+- `searchTerm`
+- `setSearchTerm()`
+- `setActiveCollection()`
+- `addCollection()`
+- `renameCollection()`
+- `addVariable()`
+- `removeVariable()`
+- `renameVariable()`
+- `updateVariableValue()`
+- `formatModeValue()`
+- `parseVariableValue()`
+- `shortName()`
+
+## Related APIs
+
+- [useVariablesEditor](../composables/use-variables-editor)
+- [useVariablesDialogState](./use-variables-dialog-state)
+- [useVariablesTable](./use-variables-table)
diff --git a/packages/docs/programmable/sdk/api/advanced/use-viewport-kind.md b/packages/docs/programmable/sdk/api/advanced/use-viewport-kind.md
new file mode 100644
index 000000000..731d22862
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/advanced/use-viewport-kind.md
@@ -0,0 +1,27 @@
+---
+title: useViewportKind
+description: Read coarse mobile and desktop viewport flags for responsive editor shells.
+---
+
+# useViewportKind
+
+`useViewportKind()` returns simple responsive flags used by OpenPencil editor UI.
+
+Use it when your shell needs a light abstraction over breakpoints instead of wiring `useBreakpoints()` directly.
+
+## Usage
+
+```ts
+import { useViewportKind } from '@open-pencil/vue'
+
+const { isMobile, isDesktop } = useViewportKind()
+```
+
+## Returns
+
+- `isMobile`
+- `isDesktop`
+
+## Related APIs
+
+- [useCanvas](../composables/use-canvas)
diff --git a/packages/docs/programmable/sdk/api/composables/index.md b/packages/docs/programmable/sdk/api/composables/index.md
index da405055c..ca233b64a 100644
--- a/packages/docs/programmable/sdk/api/composables/index.md
+++ b/packages/docs/programmable/sdk/api/composables/index.md
@@ -33,7 +33,8 @@ These are the main composables most `@open-pencil/vue` consumers will use.
- [useStrokeControls](./use-stroke-controls)
- [useEffectsControls](./use-effects-controls)
-## Variables and navigation
+## Variables, navigation, and localization
- [useVariablesEditor](./use-variables-editor)
- [usePageList](./use-page-list)
+- [useI18n](./use-i18n)
diff --git a/packages/docs/programmable/sdk/api/composables/use-i18n.md b/packages/docs/programmable/sdk/api/composables/use-i18n.md
new file mode 100644
index 000000000..c271a8818
--- /dev/null
+++ b/packages/docs/programmable/sdk/api/composables/use-i18n.md
@@ -0,0 +1,62 @@
+---
+title: useI18n
+description: Read localized OpenPencil UI messages and switch the active SDK locale.
+---
+
+# useI18n
+
+`useI18n()` returns reactive translation groups plus locale controls for OpenPencil-powered editor shells.
+
+Use it when you want SDK-backed labels for menus, commands, panels, pages, and dialogs, or when you need to let users switch locales.
+
+## Usage
+
+```ts
+import { useI18n } from '@open-pencil/vue'
+
+const { menu, commands, panels, locale, availableLocales, localeLabels, setLocale } = useI18n()
+```
+
+## Returns
+
+- `menu`
+- `commands`
+- `tools`
+- `panels`
+- `pages`
+- `dialogs`
+- `locale`
+- `availableLocales`
+- `localeLabels`
+- `setLocale`
+
+## Basic example
+
+```vue
+
+
+
+
+
+```
+
+## Notes
+
+- locale changes are reactive across all SDK message groups
+- the SDK also exports lower-level locale primitives when you need direct store access
+
+## Related APIs
+
+- [useMenuModel](./use-menu-model)
+- [SDK Locale APIs](../advanced/locale-apis)
diff --git a/packages/docs/programmable/sdk/getting-started.md b/packages/docs/programmable/sdk/getting-started.md
index 3a57d6e3b..a15047cc6 100644
--- a/packages/docs/programmable/sdk/getting-started.md
+++ b/packages/docs/programmable/sdk/getting-started.md
@@ -7,7 +7,11 @@ description: Set up @open-pencil/vue with createEditor, provideEditor, and a can
## Installation
-The SDK lives in the monorepo today and is consumed by the app itself.
+```bash
+bun add @open-pencil/core @open-pencil/vue canvaskit-wasm
+```
+
+The SDK lives in the monorepo today and is also published as `@open-pencil/vue`.
```ts
import { createEditor } from '@open-pencil/core/editor'
@@ -122,3 +126,4 @@ useCanvas(canvasRef, editor, {
- [API Reference](./api/)
- [useEditor](./api/composables/use-editor)
- [useCanvas](./api/composables/use-canvas)
+- [useI18n](./api/composables/use-i18n)
diff --git a/packages/docs/programmable/sdk/index.md b/packages/docs/programmable/sdk/index.md
index 7ebae84e5..84b8591e0 100644
--- a/packages/docs/programmable/sdk/index.md
+++ b/packages/docs/programmable/sdk/index.md
@@ -15,8 +15,9 @@ It gives you:
- injected editor context
- CanvasKit-backed canvas rendering
-- selection, commands, menu, and property-panel composables
+- selection, commands, menu, property-panel, and variables composables
- headless structural primitives like `PageListRoot`, `PropertyListRoot`, and `ToolbarRoot`
+- built-in i18n primitives for menus, panels, dialogs, and custom locale pickers
## Start here
diff --git a/packages/vue/README.md b/packages/vue/README.md
index 507535453..dcf27000f 100644
--- a/packages/vue/README.md
+++ b/packages/vue/README.md
@@ -6,7 +6,7 @@ Headless Vue 3 SDK for building OpenPencil-powered editors.
- Vue editor injection via `provideEditor()` / `useEditor()`
- canvas integration via `useCanvas()`, `useCanvasInput()`, and `useTextEdit()`
-- selection, command, and panel composables
+- selection, command, panel, variables, and i18n composables
- headless structural primitives like `CanvasRoot`, `LayerTreeRoot`, `PageListRoot`, and `ToolbarRoot`
The SDK is headless by design: it provides logic and structure, while your app owns styling and product-specific UI.
@@ -121,10 +121,11 @@ These are the main APIs most SDK consumers should start with.
- `useStrokeControls()`
- `useEffectsControls()`
-#### Variables and navigation
+#### Variables, navigation, and localization
- `useVariablesEditor()`
- `usePageList()`
+- `useI18n()`
#### Headless primitives
@@ -144,6 +145,10 @@ These exports are intentionally public, but they are lower-level or more special
- `useFillPicker()`
- `useGradientStops()`
- `useFontPicker()`
+- `useOkHCL()`
+- `useVariables()`
+- `useVariablesDialogState()`
+- `useVariablesTable()`
- `usePropScrub()`
- `useLayerDrag()`
- `useInlineRename()`
@@ -151,9 +156,10 @@ These exports are intentionally public, but they are lower-level or more special
- `useNodeFontStatus()`
- `useCanvasDrop()`
- `extractImageFilesFromClipboard()`
+- `useViewportKind()`
- `toolCursor()`
-### Primitive context helpers
+### Primitive context helpers and low-level stores
These are mostly useful when extending SDK primitives rather than building from top-level composables.
@@ -162,6 +168,11 @@ These are mostly useful when extending SDK primitives rather than building from
- `useToolbar()`
- `usePropertyList()`
- `useScrubInput()`
+- `locale`
+- `localeSetting`
+- `setLocale()`
+- `AVAILABLE_LOCALES`
+- `LOCALE_LABELS`
## Example patterns
diff --git a/packages/vue/src/context/editorContext.ts b/packages/vue/src/context/editorContext.ts
index 76e3e8a5f..a63f6f6fa 100644
--- a/packages/vue/src/context/editorContext.ts
+++ b/packages/vue/src/context/editorContext.ts
@@ -31,8 +31,8 @@ export function useEditor(): Editor {
const editor = inject(EDITOR_KEY)
if (!editor) {
throw new Error(
- '[open-pencil] useEditor() called outside . ' +
- 'Wrap your component tree with .'
+ '[open-pencil] useEditor() called without an injected editor. ' +
+ 'Call provideEditor(editor) near the top of your Vue subtree first.'
)
}
return editor