openuispec 0.1.19 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -96,7 +96,7 @@ openuispec/
96
96
  │ │ └── icons.schema.json # Icon token schema
97
97
  │ ├── defs/
98
98
  │ │ ├── common.schema.json # Shared types (icons, badges, etc.)
99
- │ │ ├── action.schema.json # 13 action types (discriminated union)
99
+ │ │ ├── action.schema.json # 14 action types (discriminated union)
100
100
  │ │ ├── data-binding.schema.json # Data sources, state, params
101
101
  │ │ ├── adaptive.schema.json # Adaptive override pattern
102
102
  │ │ └── validation.schema.json # Validation rule definitions
@@ -210,7 +210,7 @@ Paths are relative to `openuispec.yaml`. The `.openuispec-state.json` file is st
210
210
  | 6. Navigation flows | Multi-screen journeys with transitions and progress |
211
211
  | 7. Platform adaptation | Per-target overrides for iOS, Android, Web |
212
212
  | 8. AI generation contract | Compliance levels (MUST/SHOULD/MAY), validation, drift detection |
213
- | 9. Action system | 13 action types, composition, optimistic updates |
213
+ | 9. Action system | 14 action types, composition, optimistic updates |
214
214
  | 10. Data binding & state | Sources, paths, format expressions, reactivity, caching |
215
215
  | 11. Internationalization | Locale files, `$t:` references, ICU MessageFormat, RTL, platform mapping |
216
216
  | 12. Custom contract extensions | `x_` prefixed domain-specific contracts, registration, dependencies |
package/cli/init.ts CHANGED
@@ -128,7 +128,7 @@ function specReadmeTemplate(name: string, targets: string[]): string {
128
128
 
129
129
  This directory contains the **OpenUISpec** semantic UI specification for **${name}**.
130
130
 
131
- OpenUISpec is a YAML-based format that describes your app's UI semantically — tokens, screens, flows, and platform overrides. AI reads the spec and generates native code (SwiftUI, Compose, React). The spec is the single source of truth across all platforms.
131
+ **Start here:** read \`openuispec.yaml\` it defines the project structure, data model, API endpoints, and generation targets (**${targetList}**).
132
132
 
133
133
  ## Directory structure
134
134
 
@@ -137,113 +137,26 @@ OpenUISpec is a YAML-based format that describes your app's UI semantically —
137
137
  | \`tokens/\` | Design tokens — colors, typography, spacing, elevation, motion, icons, themes |
138
138
  | \`screens/\` | Screen definitions — one YAML file per screen |
139
139
  | \`flows/\` | Navigation flows — multi-step user journeys |
140
- | \`contracts/\` | Component contracts — standard extensions (variants, tokens) and custom (\`x_\` prefixed) |
140
+ | \`contracts/\` | Component contracts — standard extensions and custom (\`x_\` prefixed) |
141
141
  | \`platform/\` | Platform overrides — per-target (iOS, Android, Web) behaviors |
142
142
  | \`locales/\` | Localization — i18n strings (JSON, ICU MessageFormat) |
143
143
 
144
- All directory paths are configured in \`openuispec.yaml\` under \`includes:\` and support relative paths. For example, to share locales across projects:
145
- \`\`\`yaml
146
- includes:
147
- locales: "../../shared/locales" # resolved relative to openuispec.yaml
148
- \`\`\`
149
-
150
- ## Getting started
151
-
152
- **Start here:** read \`openuispec.yaml\` — it's the root manifest that defines the project structure, data model, API endpoints, and generation targets.
153
-
154
- ### New project (no existing UI code)
155
-
156
- 1. Define your data model and API endpoints in \`openuispec.yaml\`
157
- 2. Create token files in \`tokens/\` (colors, typography, spacing)
158
- 3. Create screen specs in \`screens/\` (one YAML per screen)
159
- 4. Create navigation flows in \`flows/\`
160
- 5. Ask AI to generate native code from the spec
161
-
162
- ### Existing project (adopting OpenUISpec)
163
-
164
- 1. Scan the codebase for existing UI screens
165
- 2. Create a stub for each screen in \`screens/\`:
166
- \`\`\`yaml
167
- screen_name:
168
- semantic: "Brief description of what this screen does"
169
- status: stub
170
- layout:
171
- type: scroll_vertical
172
- \`\`\`
173
- 3. Extract design tokens (colors, fonts, spacing) into \`tokens/\`
174
- 4. Fill in \`data_model\` and \`api.endpoints\` in \`openuispec.yaml\`
175
- 5. Spec screens incrementally: \`stub\` → \`draft\` → \`ready\`
176
-
177
- ## Screen and flow status
178
-
179
- - \`stub\` — placeholder, not yet specced. Drift detection skips these.
180
- - \`draft\` — actively being specced. Tracked by drift.
181
- - \`ready\` — fully specified (default if omitted). Tracked by drift.
182
-
183
- ## Learning OpenUISpec — where to find the docs
184
-
185
- All documentation is included in the installed \`openuispec\` package. Search for it in this order:
186
- 1. **Local:** \`node_modules/openuispec/\` (if installed as a project dependency)
187
- 2. **Global:** run \`npm root -g\` to find the global prefix, then look in \`<prefix>/openuispec/\`
188
- 3. **Online fallback:** if the package is not installed at all, fetch from:
189
- - \`https://openuispec.rsteam.uz/llms-full.txt\` — complete spec + all JSON schemas in one file
190
- - \`https://openuispec.rsteam.uz/llms.txt\` — concise summary with links
191
-
192
- Inside the package:
193
- - **Full specification:** \`spec/openuispec-v0.1.md\`
194
- - **Example app:** \`examples/taskflow/\`
195
- - **JSON Schemas:** \`schema/\`
196
-
197
- ## Token file structure — root wrapper key required
198
-
199
- Every token file must have a single root key matching the token type. Do NOT put properties at the top level.
200
-
201
- \`\`\`yaml
202
- # ✅ Correct — tokens/typography.yaml
203
- typography:
204
- font_family: ...
205
- scale: ...
206
-
207
- # ❌ Wrong — missing root wrapper key
208
- font_family: ...
209
- scale: ...
210
- \`\`\`
211
-
212
- Root keys: \`color\`, \`typography\`, \`spacing\`, \`elevation\`, \`motion\`, \`layout\`, \`themes\`, \`icons\`.
213
-
214
- ## File formats and schemas
215
-
216
- **IMPORTANT:** Before creating or editing any spec file, read the corresponding JSON Schema to understand the valid structure. Do not guess the file format.
217
-
218
- | File | Schema | Root key |
219
- |------|--------|----------|
220
- | \`openuispec.yaml\` | \`openuispec.schema.json\` | \`spec_version\` |
221
- | \`screens/*.yaml\` | \`screen.schema.json\` | \`<screen_id>\` |
222
- | \`flows/*.yaml\` | \`flow.schema.json\` | \`<flow_id>\` |
223
- | \`platform/*.yaml\` | \`platform.schema.json\` | \`platform\` |
224
- | \`locales/*.json\` | \`locale.schema.json\` | (object) |
225
- | \`contracts/<name>.yaml\` | \`contract.schema.json\` | \`<contract_name>\` |
226
- | \`contracts/x_*.yaml\` | \`custom-contract.schema.json\` | \`<x_name>\` |
227
- | \`tokens/color.yaml\` | \`tokens/color.schema.json\` | \`color\` |
228
- | \`tokens/typography.yaml\` | \`tokens/typography.schema.json\` | \`typography\` |
229
- | \`tokens/spacing.yaml\` | \`tokens/spacing.schema.json\` | \`spacing\` |
230
- | \`tokens/elevation.yaml\` | \`tokens/elevation.schema.json\` | \`elevation\` |
231
- | \`tokens/motion.yaml\` | \`tokens/motion.schema.json\` | \`motion\` |
232
- | \`tokens/layout.yaml\` | \`tokens/layout.schema.json\` | \`layout\` |
233
- | \`tokens/themes.yaml\` | \`tokens/themes.schema.json\` | \`themes\` |
234
- | \`tokens/icons.yaml\` | \`tokens/icons.schema.json\` | \`icons\` |
235
-
236
- All schemas are in \`schema/\` inside the installed package. Shared type definitions (actions, data-binding, adaptive, validation, common) are in \`schema/defs/\`.
144
+ ## IMPORTANT Read the specification before working with spec files
237
145
 
238
- **Workflow:** read the schema read an example from \`examples/taskflow/\` create the YAML → run \`openuispec validate\`.
146
+ The spec format, file schemas, and generation rules are defined in the installed \`openuispec\` package.
147
+ You MUST read these reference files before creating, editing, or generating from any spec file.
148
+ Do NOT guess the file format — skipping this step will produce invalid YAML that fails validation.
239
149
 
240
- ## Spec format quick reference
150
+ **Find the package in this order:**
151
+ 1. \`node_modules/openuispec/\` (project dependency)
152
+ 2. Run \`npm root -g\` → \`<prefix>/openuispec/\` (global install)
153
+ 3. Online: \`https://openuispec.rsteam.uz/llms-full.txt\` (if not installed)
241
154
 
242
- - **7 contract families:** nav_container, surface, action_trigger, input_field, data_display, collection, feedback
243
- - **Custom contracts:** prefixed with \`x_\` (e.g., \`x_media_player\`)
244
- - **Data binding:** \`$data:\`, \`$state:\`, \`$param:\`, \`$t:\` prefixes
245
- - **Actions:** typed objects navigate, api_call, set_state, confirm, sequence, feedback, etc.
246
- - **Adaptive layout:** size classes (compact, regular, expanded) with per-section overrides
155
+ **Reference files inside the package (read in this order):**
156
+ 1. \`README.md\` schema tables, file format reference, root keys
157
+ 2. \`spec/openuispec-v0.1.md\` full specification (contracts, layout, expressions, etc.)
158
+ 3. \`examples/taskflow/\`complete working example with all file types
159
+ 4. \`schema/\` JSON Schemas for validation
247
160
 
248
161
  ## CLI commands
249
162
 
@@ -252,34 +165,11 @@ openuispec validate # Validate spec files against schemas
252
165
  openuispec validate screens # Validate only screens
253
166
  openuispec drift --target ${targets[0]} # Check for spec drift
254
167
  openuispec drift --snapshot --target ${targets[0]} # Snapshot current state
255
- openuispec drift --all # Include stubs in drift check
256
- \`\`\`
257
-
258
- ## Targets and output directories
259
-
260
- This project generates native code for: **${targetList}**
261
-
262
- By default, drift stores state in \`generated/<target>/<project>/\`. To point targets to your actual code directories, add \`output_dir\` to \`openuispec.yaml\`:
263
-
264
- \`\`\`yaml
265
- generation:
266
- targets: [ios, android, web]
267
- output_dir:
268
- web: "../web-ui/"
269
- android: "../kmp-ui/"
270
- ios: "../kmp-ui/iosApp/"
271
168
  \`\`\`
272
169
 
273
- Paths are relative to \`openuispec.yaml\`.
274
-
275
170
  ## Learn more
276
171
 
277
- All docs and examples are in the installed \`openuispec\` package — check \`node_modules/openuispec/\` or run \`npm root -g\` for the global install path.
278
-
279
- - Full spec: \`spec/openuispec-v0.1.md\`
280
- - Example app: \`examples/taskflow/\`
281
- - JSON Schemas: \`schema/\`
282
- - Online reference: \`https://openuispec.rsteam.uz/llms-full.txt\`
172
+ Docs: https://openuispec.rsteam.uz
283
173
  `;
284
174
  }
285
175
 
@@ -292,26 +182,47 @@ function aiRulesBlock(specDir: string, targets: string[]): string {
292
182
  # Spec files are the single source of truth for all UI across platforms.
293
183
  # Targets: ${targetList}
294
184
 
185
+ ## IMPORTANT — Read the specification before working with spec files
186
+
187
+ The spec format, file schemas, and generation rules are defined in the installed \`openuispec\` package.
188
+ You MUST read the reference files listed below before creating, editing, or generating from any spec file.
189
+ Do NOT guess the file format — skipping this step will produce invalid YAML that fails validation.
190
+
191
+ **Find the package in this order:**
192
+ 1. \`node_modules/openuispec/\` (project dependency)
193
+ 2. Run \`npm root -g\` → \`<prefix>/openuispec/\` (global install)
194
+ 3. Online: \`https://openuispec.rsteam.uz/llms-full.txt\` (if not installed)
195
+
196
+ **Reference files inside the package (read in this order):**
197
+ 1. \`README.md\` — schema tables, file format reference, root wrapper keys
198
+ 2. \`spec/openuispec-v0.1.md\` — full specification (contracts, layout, expressions, adaptive, etc.)
199
+ 3. \`examples/taskflow/\` — complete working example with all file types
200
+ 4. \`schema/\` — JSON Schemas for every file type
201
+
202
+ These files are updated with each package version. Always read from the installed package,
203
+ not from cached or memorized content, to ensure you use the latest spec.
204
+
295
205
  ## What is OpenUISpec
296
206
  OpenUISpec is a YAML-based spec format that describes an app's UI semantically — tokens, screens, flows, and platform overrides. AI reads the spec and generates native code (SwiftUI, Compose, React). AI reads native code and updates the spec. The spec is the sync layer between platforms.
297
207
 
298
208
  ## Spec location
299
209
  - Spec root: \`${specDir}/\`
300
210
  - Manifest: \`${specDir}/openuispec.yaml\` — always read this first.
301
- - Tokens: \`${specDir}/tokens/\` — colors, typography, spacing, motion, icons, themes
302
- - Screens: \`${specDir}/screens/\` — one YAML file per screen
303
- - Flows: \`${specDir}/flows/\` — multi-step navigation journeys
304
- - Contracts: \`${specDir}/contracts/\` — standard extensions (variants, tokens) and custom (\`x_\` prefixed)
305
- - Platform: \`${specDir}/platform/\` — per-target overrides (iOS, Android, Web)
306
- - Locales: \`${specDir}/locales/\` — i18n strings (JSON, ICU MessageFormat)
211
+ - Tokens: \`${specDir}/tokens/\`
212
+ - Screens: \`${specDir}/screens/\`
213
+ - Flows: \`${specDir}/flows/\`
214
+ - Contracts: \`${specDir}/contracts/\`
215
+ - Platform: \`${specDir}/platform/\`
216
+ - Locales: \`${specDir}/locales/\`
307
217
 
308
- **Note:** These are the default paths. Actual paths are in \`includes:\` in \`openuispec.yaml\` and may use relative paths (e.g. \`../../shared/locales\`). Always read \`openuispec.yaml\` to find the real directories.
218
+ **Note:** These are the default paths. Actual paths are in \`includes:\` in \`openuispec.yaml\` and may use relative paths. Always read \`openuispec.yaml\` to find the real directories.
309
219
 
310
220
  ## If spec directories are empty (first-time setup)
311
221
  This means the project has existing UI code but hasn't been specced yet. Your job:
312
222
 
313
- 1. **Find existing screens** — scan the codebase for UI screen files (SwiftUI views, Compose screens, React components/pages).
314
- 2. **Create stubs** — for each screen, create \`${specDir}/screens/<name>.yaml\` with:
223
+ 1. **Read the spec first** — find and read \`spec/openuispec-v0.1.md\` from the installed package.
224
+ 2. **Find existing screens** — scan the codebase for UI screen files.
225
+ 3. **Create stubs** — for each screen, create \`${specDir}/screens/<name>.yaml\` with:
315
226
  \`\`\`yaml
316
227
  screen_name:
317
228
  semantic: "Brief description of what this screen does"
@@ -319,14 +230,8 @@ This means the project has existing UI code but hasn't been specced yet. Your jo
319
230
  layout:
320
231
  type: scroll_vertical
321
232
  \`\`\`
322
- 3. **Extract tokens** — scan the codebase for colors, fonts, spacing values and create token files in \`${specDir}/tokens/\`.
323
- 4. **Update the manifest** — fill in \`data_model\` and \`api.endpoints\` in \`${specDir}/openuispec.yaml\` based on the existing code.
324
- 5. **Spec screens on demand** — when the user asks to spec a screen, read the native code, create a full spec, and change \`status: draft\` → \`ready\`.
325
-
326
- ## Screen and flow status
327
- - \`stub\` — placeholder, not yet specced. Drift detection skips these.
328
- - \`draft\` — actively being specced. Tracked by drift.
329
- - \`ready\` — fully specified (default if omitted). Tracked by drift.
233
+ 4. **Extract tokens** — scan for colors, fonts, spacing and create files in \`${specDir}/tokens/\`.
234
+ 5. **Update the manifest** — fill in \`data_model\` and \`api.endpoints\` in \`${specDir}/openuispec.yaml\`.
330
235
 
331
236
  ## Making UI changes
332
237
  1. Read the relevant spec files before modifying any UI code.
@@ -340,74 +245,6 @@ This means the project has existing UI code but hasn't been specced yet. Your jo
340
245
  2. Run \`openuispec drift --snapshot --target <target>\` for each affected platform.
341
246
  3. Run \`openuispec drift\` to verify no untracked drift remains.
342
247
 
343
- ## Learning OpenUISpec — where to find the docs
344
- All documentation is in the installed \`openuispec\` package. Search in this order:
345
- 1. **Local:** \`node_modules/openuispec/\` (project dependency)
346
- 2. **Global:** run \`npm root -g\` to get the global prefix, then look in \`<prefix>/openuispec/\`
347
- 3. **Online fallback:** if not installed, fetch from:
348
- - \`https://openuispec.rsteam.uz/llms-full.txt\` — complete spec + all JSON schemas
349
- - \`https://openuispec.rsteam.uz/llms.txt\` — concise summary with links
350
-
351
- Inside the package:
352
- 1. **Full specification:** \`spec/openuispec-v0.1.md\` — the complete spec (read this to understand the format)
353
- 2. **Example app:** \`examples/taskflow/\` — a complete working app with all file types
354
- 3. **JSON Schemas:** \`schema/\` — validation schemas that define the exact structure of every file type
355
-
356
- ## Token file structure — root wrapper key required
357
- Every token file must have a single root key matching the token type. Do NOT put properties at the top level.
358
- - \`tokens/color.yaml\` → root key: \`color\`
359
- - \`tokens/typography.yaml\` → root key: \`typography\`
360
- - \`tokens/spacing.yaml\` → root key: \`spacing\`
361
- - \`tokens/elevation.yaml\` → root key: \`elevation\`
362
- - \`tokens/motion.yaml\` → root key: \`motion\`
363
- - \`tokens/layout.yaml\` → root key: \`layout\`
364
- - \`tokens/themes.yaml\` → root key: \`themes\`
365
- - \`tokens/icons.yaml\` → root key: \`icons\`
366
-
367
- ## File formats and schemas — read before creating spec files
368
- Before creating or editing any spec file, read the corresponding JSON Schema. Do not guess the file format.
369
-
370
- | File | Schema (in \`schema/\` inside the installed package) | Root key |
371
- |------|--------|----------|
372
- | \`openuispec.yaml\` | \`openuispec.schema.json\` | \`spec_version\` |
373
- | \`screens/*.yaml\` | \`screen.schema.json\` | \`<screen_id>\` |
374
- | \`flows/*.yaml\` | \`flow.schema.json\` | \`<flow_id>\` |
375
- | \`platform/*.yaml\` | \`platform.schema.json\` | \`platform\` |
376
- | \`locales/*.json\` | \`locale.schema.json\` | (object) |
377
- | \`contracts/<name>.yaml\` | \`contract.schema.json\` | \`<contract_name>\` |
378
- | \`contracts/x_*.yaml\` | \`custom-contract.schema.json\` | \`<x_name>\` |
379
- | \`tokens/color.yaml\` | \`tokens/color.schema.json\` | \`color\` |
380
- | \`tokens/typography.yaml\` | \`tokens/typography.schema.json\` | \`typography\` |
381
- | \`tokens/spacing.yaml\` | \`tokens/spacing.schema.json\` | \`spacing\` |
382
- | \`tokens/elevation.yaml\` | \`tokens/elevation.schema.json\` | \`elevation\` |
383
- | \`tokens/motion.yaml\` | \`tokens/motion.schema.json\` | \`motion\` |
384
- | \`tokens/layout.yaml\` | \`tokens/layout.schema.json\` | \`layout\` |
385
- | \`tokens/themes.yaml\` | \`tokens/themes.schema.json\` | \`themes\` |
386
- | \`tokens/icons.yaml\` | \`tokens/icons.schema.json\` | \`icons\` |
387
-
388
- Shared type definitions (actions, data-binding, adaptive, validation, common) are in \`schema/defs/\`.
389
-
390
- Workflow: read the schema → read an example from \`examples/taskflow/\` → create the YAML → run \`openuispec validate\`.
391
-
392
- ## Spec format reference
393
- - 7 contract families: nav_container, surface, action_trigger, input_field, data_display, collection, feedback
394
- - Custom contracts: prefixed with \`x_\` (e.g., \`x_media_player\`)
395
- - Data binding: \`$data:\`, \`$state:\`, \`$param:\`, \`$t:\` prefixes
396
- - Actions: typed objects (navigate, api_call, set_state, confirm, sequence, feedback, etc.)
397
- - Adaptive layout: size classes (compact, regular, expanded) with per-section overrides
398
-
399
- ## Output directories
400
- Drift tracks spec changes per target. By default state is stored in \`generated/<target>/<project>/\`.
401
- To map targets to actual code directories, set \`generation.output_dir\` in \`openuispec.yaml\`:
402
- \`\`\`yaml
403
- generation:
404
- output_dir:
405
- web: "../web-ui/"
406
- android: "../kmp-ui/"
407
- ios: "../kmp-ui/iosApp/"
408
- \`\`\`
409
- Paths are relative to \`openuispec.yaml\`. The \`.openuispec-state.json\` file is stored inside each output directory.
410
-
411
248
  ## CLI commands
412
249
  - \`openuispec init\` — scaffold a new spec project
413
250
  - \`openuispec validate [group...]\` — validate spec files against schemas
@@ -4,26 +4,47 @@
4
4
  # Spec files are the single source of truth for all UI across platforms.
5
5
  # Targets: "ios", "android", "web"
6
6
 
7
+ ## IMPORTANT — Read the specification before working with spec files
8
+
9
+ The spec format, file schemas, and generation rules are defined in the installed `openuispec` package.
10
+ You MUST read the reference files listed below before creating, editing, or generating from any spec file.
11
+ Do NOT guess the file format — skipping this step will produce invalid YAML that fails validation.
12
+
13
+ **Find the package in this order:**
14
+ 1. `node_modules/openuispec/` (project dependency)
15
+ 2. Run `npm root -g` → `<prefix>/openuispec/` (global install)
16
+ 3. Online: `https://openuispec.rsteam.uz/llms-full.txt` (if not installed)
17
+
18
+ **Reference files inside the package (read in this order):**
19
+ 1. `README.md` — schema tables, file format reference, root wrapper keys
20
+ 2. `spec/openuispec-v0.1.md` — full specification (contracts, layout, expressions, adaptive, etc.)
21
+ 3. `examples/taskflow/` — complete working example with all file types
22
+ 4. `schema/` — JSON Schemas for every file type
23
+
24
+ These files are updated with each package version. Always read from the installed package,
25
+ not from cached or memorized content, to ensure you use the latest spec.
26
+
7
27
  ## What is OpenUISpec
8
28
  OpenUISpec is a YAML-based spec format that describes an app's UI semantically — tokens, screens, flows, and platform overrides. AI reads the spec and generates native code (SwiftUI, Compose, React). AI reads native code and updates the spec. The spec is the sync layer between platforms.
9
29
 
10
30
  ## Spec location
11
31
  - Spec root: `openuispec/`
12
32
  - Manifest: `openuispec/openuispec.yaml` — always read this first.
13
- - Tokens: `openuispec/tokens/` — colors, typography, spacing, motion, icons, themes
14
- - Screens: `openuispec/screens/` — one YAML file per screen
15
- - Flows: `openuispec/flows/` — multi-step navigation journeys
16
- - Contracts: `openuispec/contracts/` — UI component definitions
17
- - Platform: `openuispec/platform/` — per-target overrides (iOS, Android, Web)
18
- - Locales: `openuispec/locales/` — i18n strings (JSON, ICU MessageFormat)
33
+ - Tokens: `openuispec/tokens/`
34
+ - Screens: `openuispec/screens/`
35
+ - Flows: `openuispec/flows/`
36
+ - Contracts: `openuispec/contracts/`
37
+ - Platform: `openuispec/platform/`
38
+ - Locales: `openuispec/locales/`
19
39
 
20
- **Note:** These are the default paths. Actual paths are in `includes:` in `openuispec.yaml` and may use relative paths (e.g. `../../shared/locales`). Always read `openuispec.yaml` to find the real directories.
40
+ **Note:** These are the default paths. Actual paths are in `includes:` in `openuispec.yaml` and may use relative paths. Always read `openuispec.yaml` to find the real directories.
21
41
 
22
42
  ## If spec directories are empty (first-time setup)
23
43
  This means the project has existing UI code but hasn't been specced yet. Your job:
24
44
 
25
- 1. **Find existing screens** — scan the codebase for UI screen files (SwiftUI views, Compose screens, React components/pages).
26
- 2. **Create stubs** — for each screen, create `openuispec/screens/<name>.yaml` with:
45
+ 1. **Read the spec first** — find and read `spec/openuispec-v0.1.md` from the installed package.
46
+ 2. **Find existing screens** — scan the codebase for UI screen files.
47
+ 3. **Create stubs** — for each screen, create `openuispec/screens/<name>.yaml` with:
27
48
  ```yaml
28
49
  screen_name:
29
50
  semantic: "Brief description of what this screen does"
@@ -31,14 +52,8 @@ This means the project has existing UI code but hasn't been specced yet. Your jo
31
52
  layout:
32
53
  type: scroll_vertical
33
54
  ```
34
- 3. **Extract tokens** — scan the codebase for colors, fonts, spacing values and create token files in `openuispec/tokens/`.
35
- 4. **Update the manifest** — fill in `data_model` and `api.endpoints` in `openuispec/openuispec.yaml` based on the existing code.
36
- 5. **Spec screens on demand** — when the user asks to spec a screen, read the native code, create a full spec, and change `status: draft` → `ready`.
37
-
38
- ## Screen and flow status
39
- - `stub` — placeholder, not yet specced. Drift detection skips these.
40
- - `draft` — actively being specced. Tracked by drift.
41
- - `ready` — fully specified (default if omitted). Tracked by drift.
55
+ 4. **Extract tokens** — scan for colors, fonts, spacing and create files in `openuispec/tokens/`.
56
+ 5. **Update the manifest** — fill in `data_model` and `api.endpoints` in `openuispec/openuispec.yaml`.
42
57
 
43
58
  ## Making UI changes
44
59
  1. Read the relevant spec files before modifying any UI code.
@@ -52,73 +67,6 @@ This means the project has existing UI code but hasn't been specced yet. Your jo
52
67
  2. Run `openuispec drift --snapshot --target <target>` for each affected platform.
53
68
  3. Run `openuispec drift` to verify no untracked drift remains.
54
69
 
55
- ## Learning OpenUISpec — where to find the docs
56
- All documentation is in the installed `openuispec` package. Search in this order:
57
- 1. **Local:** `node_modules/openuispec/` (project dependency)
58
- 2. **Global:** run `npm root -g` to get the global prefix, then look in `<prefix>/openuispec/`
59
- 3. **Online fallback:** if not installed, fetch from:
60
- - `https://openuispec.rsteam.uz/llms-full.txt` — complete spec + all JSON schemas
61
- - `https://openuispec.rsteam.uz/llms.txt` — concise summary with links
62
-
63
- Inside the package:
64
- 1. **Full specification:** `spec/openuispec-v0.1.md` — the complete spec (read this to understand the format)
65
- 2. **Example app:** `examples/taskflow/` — a complete working app with all file types
66
- 3. **JSON Schemas:** `schema/` — validation schemas that define the exact structure of every file type
67
-
68
- ## Token file structure — root wrapper key required
69
- Every token file must have a single root key matching the token type. Do NOT put properties at the top level.
70
- - `tokens/color.yaml` → root key: `color`
71
- - `tokens/typography.yaml` → root key: `typography`
72
- - `tokens/spacing.yaml` → root key: `spacing`
73
- - `tokens/elevation.yaml` → root key: `elevation`
74
- - `tokens/motion.yaml` → root key: `motion`
75
- - `tokens/layout.yaml` → root key: `layout`
76
- - `tokens/themes.yaml` → root key: `themes`
77
- - `tokens/icons.yaml` → root key: `icons`
78
-
79
- ## File formats and schemas — read before creating spec files
80
- Before creating or editing any spec file, read the corresponding JSON Schema. Do not guess the file format.
81
-
82
- | File | Schema (in `schema/` inside the installed package) | Root key |
83
- |------|--------|----------|
84
- | `openuispec.yaml` | `openuispec.schema.json` | `spec_version` |
85
- | `screens/*.yaml` | `screen.schema.json` | `<screen_id>` |
86
- | `flows/*.yaml` | `flow.schema.json` | `<flow_id>` |
87
- | `platform/*.yaml` | `platform.schema.json` | `platform` |
88
- | `locales/*.json` | `locale.schema.json` | (object) |
89
- | `contracts/x_*.yaml` | `custom-contract.schema.json` | `contract` |
90
- | `tokens/color.yaml` | `tokens/color.schema.json` | `color` |
91
- | `tokens/typography.yaml` | `tokens/typography.schema.json` | `typography` |
92
- | `tokens/spacing.yaml` | `tokens/spacing.schema.json` | `spacing` |
93
- | `tokens/elevation.yaml` | `tokens/elevation.schema.json` | `elevation` |
94
- | `tokens/motion.yaml` | `tokens/motion.schema.json` | `motion` |
95
- | `tokens/layout.yaml` | `tokens/layout.schema.json` | `layout` |
96
- | `tokens/themes.yaml` | `tokens/themes.schema.json` | `themes` |
97
- | `tokens/icons.yaml` | `tokens/icons.schema.json` | `icons` |
98
-
99
- Shared type definitions (actions, data-binding, adaptive, validation, common) are in `schema/defs/`.
100
-
101
- Workflow: read the schema → read an example from `examples/taskflow/` → create the YAML → run `openuispec validate`.
102
-
103
- ## Spec format reference
104
- - 7 contract families: nav_container, surface, action_trigger, input_field, data_display, collection, feedback
105
- - Custom contracts: prefixed with `x_` (e.g., `x_media_player`)
106
- - Data binding: `$data:`, `$state:`, `$param:`, `$t:` prefixes
107
- - Actions: typed objects (navigate, api_call, set_state, confirm, sequence, feedback, etc.)
108
- - Adaptive layout: size classes (compact, regular, expanded) with per-section overrides
109
-
110
- ## Output directories
111
- Drift tracks spec changes per target. By default state is stored in `generated/<target>/<project>/`.
112
- To map targets to actual code directories, set `generation.output_dir` in `openuispec.yaml`:
113
- ```yaml
114
- generation:
115
- output_dir:
116
- web: "../web-ui/"
117
- android: "../kmp-ui/"
118
- ios: "../kmp-ui/iosApp/"
119
- ```
120
- Paths are relative to `openuispec.yaml`. The `.openuispec-state.json` file is stored inside each output directory.
121
-
122
70
  ## CLI commands
123
71
  - `openuispec init` — scaffold a new spec project
124
72
  - `openuispec validate [group...]` — validate spec files against schemas
@@ -1,5 +1,6 @@
1
1
  analytics:
2
2
  semantic: "Analytics dashboard for productivity trends, weekly completion, and overdue task review"
3
+ title: "$t:nav.analytics"
3
4
  status: ready
4
5
 
5
6
  data:
@@ -1,5 +1,6 @@
1
1
  home:
2
2
  semantic: "Main todo list with search, filters, completion toggles, and a quick-create action"
3
+ title: "$t:nav.tasks"
3
4
  status: ready
4
5
 
5
6
  data:
@@ -1,5 +1,6 @@
1
1
  settings:
2
2
  semantic: "Preferences screen for application language and theme"
3
+ title: "$t:nav.settings"
3
4
  status: ready
4
5
 
5
6
  data:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openuispec",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "A semantic UI specification format for AI-native, platform-native app development",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openuispec.org/schema/defs/action.schema.json",
4
4
  "title": "OpenUISpec Action",
5
- "description": "Discriminated union of the 13 action types in OpenUISpec",
5
+ "description": "Discriminated union of the 14 action types in OpenUISpec",
6
6
 
7
7
  "type": "object",
8
8
  "required": ["type"],
@@ -17,6 +17,10 @@
17
17
  "semantic": {
18
18
  "type": "string"
19
19
  },
20
+ "title": {
21
+ "type": "string",
22
+ "description": "Optional screen title for navigation bars and headers. When omitted, inferred from the first data_display title in the layout or the nav item label."
23
+ },
20
24
  "status": {
21
25
  "type": "string",
22
26
  "enum": [
@@ -182,6 +186,11 @@
182
186
  "input_type": {
183
187
  "type": "string"
184
188
  },
189
+ "render_hint": {
190
+ "type": "string",
191
+ "enum": ["dropdown", "segmented", "radio_group", "bottom_sheet"],
192
+ "description": "Optional hint for how an input_field with input_type select should render. When omitted, the platform default is used (e.g., Picker on iOS, ExposedDropdownMenuBox on Android, select on Web)."
193
+ },
185
194
  "size": {
186
195
  "type": "string"
187
196
  },
@@ -835,6 +835,12 @@ input_field:
835
835
  suffix: { type: string, required: false }
836
836
  icon: { type: icon_ref, required: false, position: [leading, trailing] }
837
837
  clearable: { type: bool, default: false }
838
+ render_hint:
839
+ type: enum
840
+ values: [dropdown, segmented, radio_group, bottom_sheet]
841
+ required: false
842
+ condition: "input_type == select"
843
+ description: "Overrides the default platform widget for select fields. When omitted, the platform default is used."
838
844
 
839
845
  states:
840
846
  empty:
@@ -909,6 +915,7 @@ input_field:
909
915
  text: { widget: "TextField" }
910
916
  multiline: { widget: "TextEditor" }
911
917
  select: { widget: "Picker" }
918
+ select[segmented]: { widget: "Picker(style: .segmented)" }
912
919
  toggle: { widget: "Toggle" }
913
920
  slider: { widget: "Slider" }
914
921
  date: { widget: "DatePicker" }
@@ -916,6 +923,7 @@ input_field:
916
923
  text: { composable: "OutlinedTextField" }
917
924
  multiline: { composable: "OutlinedTextField(singleLine=false)" }
918
925
  select: { composable: "ExposedDropdownMenuBox" }
926
+ select[segmented]: { composable: "SegmentedButton / SingleChoiceSegmentedButtonRow" }
919
927
  toggle: { composable: "Switch" }
920
928
  slider: { composable: "Slider" }
921
929
  date: { composable: "DatePicker" }
@@ -923,6 +931,7 @@ input_field:
923
931
  text: { element: "input", type: "text" }
924
932
  multiline: { element: "textarea" }
925
933
  select: { element: "select" }
934
+ select[segmented]: { element: "fieldset > input[type=radio]", styled: "segmented control" }
926
935
  toggle: { element: "input", type: "checkbox", role: "switch" }
927
936
  slider: { element: "input", type: "range" }
928
937
  date: { element: "input", type: "date" }
@@ -1484,7 +1493,8 @@ Screens compose contracts into layouts. A screen never references platform widge
1484
1493
  # Example: screens/order_detail.yaml
1485
1494
  order_detail:
1486
1495
  semantic: "Displays detailed information about a single order"
1487
-
1496
+ title: "$t:order_detail.title" # Optional — shown in nav bar / browser tab
1497
+
1488
1498
  params:
1489
1499
  order_id: { type: string, required: true }
1490
1500
 
@@ -1561,7 +1571,19 @@ order_detail:
1561
1571
 
1562
1572
  ### 5.1 Screen-level keys
1563
1573
 
1564
- Beyond contract props and layout primitives, screen files use several keys that modify how sections and contract instances behave. These keys are available on any section or contract instance within a screen's `sections:` array.
1574
+ Screen definitions support the following top-level keys alongside `semantic`, `layout`, `data`, `state`, `params`, `navigation`, and `surfaces`:
1575
+
1576
+ #### `title`
1577
+
1578
+ Optional display title for the screen, shown in navigation bars, browser tabs, and back-button labels. When omitted, generators should infer the title from the first `data_display` title in the layout, or from the corresponding `nav_container` item label.
1579
+
1580
+ ```yaml
1581
+ settings:
1582
+ semantic: "Preferences screen for language and theme"
1583
+ title: "$t:settings.title" # "Preferences"
1584
+ ```
1585
+
1586
+ Beyond these, screen files use several keys that modify how sections and contract instances behave. These keys are available on any section or contract instance within a screen's `sections:` array.
1565
1587
 
1566
1588
  #### `tokens_override`
1567
1589
 
@@ -2648,8 +2670,9 @@ Format expressions transform values for display. They appear inside `{}` delimit
2648
2670
  ```
2649
2671
  interpolation := '{' (piped_expr | computed_expr) '}'
2650
2672
  piped_expr := data_path ('|' pipe)*
2651
- pipe := operation ':' argument
2673
+ pipe := operation ':' argument ('.' option)?
2652
2674
  operation := 'format' | 'map' | 'default'
2675
+ option := identifier # e.g., abbreviated, narrow
2653
2676
  computed_expr := data_path comparator value '?' literal ':' literal
2654
2677
  comparator := '==' | '!=' | '>' | '<' | '>=' | '<='
2655
2678
  locale_ref := '$t:' locale_key
@@ -2705,18 +2728,18 @@ subtitle: "{item.quantity} × {item.unit_price | format:currency}"
2705
2728
 
2706
2729
  **Built-in formatters:**
2707
2730
 
2708
- | Formatter | Input | Output | Locale-aware |
2709
- |-----------|-------|--------|-------------|
2710
- | `currency` | number | "$1,234.56" | Yes |
2711
- | `date` | date/datetime | "Mar 13, 2026" | Yes |
2712
- | `date_relative` | date/datetime | "2 hours ago", "yesterday" | Yes |
2713
- | `date_short` | date/datetime | "Mar 13" | Yes |
2714
- | `time` | datetime | "3:45 PM" | Yes |
2715
- | `number` | number | "1,234" | Yes |
2716
- | `percentage` | number (0-1) | "45%" | No |
2717
- | `status_label` | enum string | "In Progress" (title case) | No |
2718
- | `pluralize` | number | "1 task" / "3 tasks" | Yes |
2719
- | `file_size` | number (bytes) | "2.4 MB" | No |
2731
+ | Formatter | Input | Output | Locale-aware | Options |
2732
+ |-----------|-------|--------|-------------|---------|
2733
+ | `currency` | number | "$1,234.56" | Yes | — |
2734
+ | `date` | date/datetime | "Mar 13, 2026" | Yes | — |
2735
+ | `date_relative` | date/datetime | "2 hours ago", "yesterday" | Yes | `style`: full (default), abbreviated, narrow |
2736
+ | `date_short` | date/datetime | "Mar 13" | Yes | — |
2737
+ | `time` | datetime | "3:45 PM" | Yes | — |
2738
+ | `number` | number | "1,234" | Yes | — |
2739
+ | `percentage` | number (0-1) | "45%" | No | — |
2740
+ | `status_label` | enum string | "In Progress" (title case) | No | — |
2741
+ | `pluralize` | number | "1 task" / "3 tasks" | Yes | — |
2742
+ | `file_size` | number (bytes) | "2.4 MB" | No | — |
2720
2743
 
2721
2744
  **Built-in mappers:**
2722
2745
 
@@ -2726,6 +2749,21 @@ subtitle: "{item.quantity} × {item.unit_price | format:currency}"
2726
2749
  | `priority_to_severity` | priority enum → severity enum (e.g., "urgent" → "error") |
2727
2750
  | `bool_to_label` | true/false → "Yes"/"No" (or custom mapping) |
2728
2751
 
2752
+ **Formatter options** — some built-in formatters accept an `options` parameter, passed with a dot suffix:
2753
+
2754
+ ```yaml
2755
+ # Default style (full): "in 2 days", "3 hours ago"
2756
+ subtitle: "{task.due_date | format:date_relative}"
2757
+
2758
+ # Abbreviated: "in 2d", "3h ago"
2759
+ subtitle: "{task.due_date | format:date_relative.abbreviated}"
2760
+
2761
+ # Narrow: "2d", "3h"
2762
+ subtitle: "{task.due_date | format:date_relative.narrow}"
2763
+ ```
2764
+
2765
+ When no option is provided, the default style is used. Generators must respect the option across all platforms to ensure consistent output.
2766
+
2729
2767
  **Custom formatters and mappers** can be defined in the project manifest:
2730
2768
 
2731
2769
  ```yaml