@lingxia/skill 0.8.0

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.
Files changed (37) hide show
  1. package/README.md +95 -0
  2. package/bin/install.mjs +247 -0
  3. package/package.json +49 -0
  4. package/scripts/sync.mjs +69 -0
  5. package/skill/SKILL.md +334 -0
  6. package/skill/app/apple-sdk.md +312 -0
  7. package/skill/app/applinks.md +289 -0
  8. package/skill/app/project.md +760 -0
  9. package/skill/cli/lxdev.md +195 -0
  10. package/skill/cli/reference.md +481 -0
  11. package/skill/examples/hello-host-js/README.md +25 -0
  12. package/skill/examples/hello-host-js/home/lxapp.json +12 -0
  13. package/skill/examples/hello-host-js/home/pages/home/index.json +4 -0
  14. package/skill/examples/hello-host-js/home/pages/home/index.ts +14 -0
  15. package/skill/examples/hello-host-js/home/pages/home/index.tsx +15 -0
  16. package/skill/examples/hello-host-js/lingxia.yaml +39 -0
  17. package/skill/examples/hello-host-rust/Cargo.toml +15 -0
  18. package/skill/examples/hello-host-rust/README.md +44 -0
  19. package/skill/examples/hello-host-rust/home/lxapp.json +13 -0
  20. package/skill/examples/hello-host-rust/home/pages/home/index.html +46 -0
  21. package/skill/examples/hello-host-rust/home/pages/home/index.json +4 -0
  22. package/skill/examples/hello-host-rust/lingxia.yaml +32 -0
  23. package/skill/examples/hello-host-rust/src/lib.rs +58 -0
  24. package/skill/examples/hello-lxapp/README.md +29 -0
  25. package/skill/examples/hello-lxapp/lxapp.config.ts +8 -0
  26. package/skill/examples/hello-lxapp/lxapp.json +14 -0
  27. package/skill/examples/hello-lxapp/package.json +14 -0
  28. package/skill/examples/hello-lxapp/pages/home/index.json +4 -0
  29. package/skill/examples/hello-lxapp/pages/home/index.ts +35 -0
  30. package/skill/examples/hello-lxapp/pages/home/index.tsx +34 -0
  31. package/skill/lxapp/bridge.md +654 -0
  32. package/skill/lxapp/components.md +375 -0
  33. package/skill/lxapp/guide.md +675 -0
  34. package/skill/lxapp/lx-api.md +481 -0
  35. package/skill/native/development.md +414 -0
  36. package/skill/reference/file-lifecycle.md +325 -0
  37. package/skill/skill-manifest.json +6 -0
@@ -0,0 +1,760 @@
1
+ # App Project Configuration
2
+
3
+ A LingXia app project is a native host app that embeds one home lxapp and can open bundled or runtime lxapps.
4
+
5
+ This page focuses on the macOS host app path because that is the current product App UI runtime. Android, iOS, and Harmony still use their platform host scaffolding, but the `ui` section below is implemented for macOS first.
6
+
7
+ For lxapp page development, see [LxApp Development Guide](../lxapp/guide.md).
8
+ For quick onboarding, see `docs/quick-start.md` (outside this skill).
9
+ For CLI commands, see [CLI Command Reference](../cli/reference.md).
10
+
11
+ ---
12
+
13
+ ## Create A Host App
14
+
15
+ ```bash
16
+ lingxia new my-app -t native-app -p macos --package-id com.example.myapp -y
17
+ ```
18
+
19
+ This creates a host app project, not a standalone lxapp. A host app owns native platform directories, a `lingxia.yaml`, and one embedded home lxapp.
20
+
21
+ To create a standalone lxapp instead, use `-t lxapp`.
22
+
23
+ ---
24
+
25
+ ## Project Layout
26
+
27
+ ```text
28
+ my-app/
29
+ ├── lingxia.yaml # build-time host project config
30
+ ├── macos/ # macOS Swift Package host
31
+ ├── android/ # optional Android host
32
+ ├── ios/ # optional iOS host
33
+ ├── harmony/ # optional Harmony host
34
+ └── lingxia-showcase/ # embedded home lxapp source
35
+ ```
36
+
37
+ - `lingxia.yaml` is the source of truth for host build metadata and macOS App UI.
38
+ - `lingxia build` generates runtime `app.json` and `ui.json` from `lingxia.yaml`.
39
+ - Do not edit generated `app.json` or `ui.json` directly.
40
+ - `app.homeAppId` controls the home app opened by default; `resources.bundles` controls bundled asset sources.
41
+
42
+ ---
43
+
44
+ ## SDK Startup APIs
45
+
46
+ Use the product-app startup entry on each platform:
47
+
48
+ | Platform | Entry |
49
+ |---|---|
50
+ | Apple | `Lingxia.quickStart()` |
51
+ | Android | `Lingxia.quickStart(activity)` |
52
+ | Harmony | `Lingxia.quickStart(context, windowStage)` |
53
+
54
+ `quickStart` means the native app is a LingXia host product. It initializes the
55
+ runtime and opens the configured home lxapp through the platform host shell or
56
+ navigation container.
57
+
58
+ Android and Harmony intentionally expose only `quickStart` as the public startup
59
+ API today. Advanced embedding into an existing native app should stay internal
60
+ until the host-view/session API is designed for those platforms. Do not add
61
+ compatibility wrappers such as `Lingxia.initialize(...)`.
62
+
63
+ ---
64
+
65
+ ## Minimal macOS Example
66
+
67
+ ```yaml
68
+ app:
69
+ projectName: myapp
70
+ productName: My App
71
+ productVersion: 1.0.0
72
+ platforms:
73
+ - macos
74
+ homeAppId: my-home
75
+
76
+ macos:
77
+ bundleId: com.example.myapp
78
+ deploymentTarget: "12.0"
79
+ targetName: MyApp
80
+ executableName: MyApp
81
+
82
+ ui:
83
+ launch:
84
+ initialSurface: main
85
+ surfaces:
86
+ - id: main
87
+ presentation:
88
+ kind: window
89
+ content:
90
+ kind: lxapp
91
+ appId: my-home
92
+ activators: []
93
+
94
+ ```
95
+
96
+ For a native-only menu bar app, see `examples/menubar`. It uses
97
+ `features.appService: false`, a `menuBarItem` activator, a panel root surface,
98
+ and a `logic: false` HTML home lxapp.
99
+
100
+ ---
101
+
102
+ ## Root Sections
103
+
104
+ | Section | Required | macOS Status | Description |
105
+ |---|---:|---|---|
106
+ | `app` | Yes | Required | Host metadata used to generate runtime `app.json` |
107
+ | `macos` | For macOS | Required for macOS builds | macOS bundle and SwiftPM target settings |
108
+ | `ui` | For macOS product hosts | Required | App UI model used to generate `ui.json` |
109
+ | `android` | For Android | Supported | Android host settings |
110
+ | `ios` | For iOS | Supported | iOS host settings |
111
+ | `harmony` | For Harmony | Supported | Harmony host settings |
112
+ | `features` | Recommended | Supported | Native Rust compile-time feature switches |
113
+ | `capabilities` | Recommended | Supported | Platform/runtime integrations that may initialize SDK capability flows |
114
+ | `resources` | Recommended | Supported | Bundle asset sources copied into native app resources |
115
+ | `shell` | When `features.shell` is true | Supported | Shell webui source configuration |
116
+ | `storage` | Recommended | Supported | Explicit host temp/cache/data size limits |
117
+
118
+ ---
119
+
120
+ ## `app` Section
121
+
122
+ | Field | Type | Required | Description |
123
+ |---|---|---:|---|
124
+ | `projectName` | string | Yes | Technical project identifier. Used by native build tooling and Rust host library naming. |
125
+ | `productName` | string | Yes | User-facing app name. |
126
+ | `productVersion` | string | Yes | Host app version. |
127
+ | `platforms` | string[] | Yes | Enabled platforms, for example `macos`, `android`, `ios`, `harmony`. |
128
+ | `homeAppId` | string | Yes | Home app id opened by default. |
129
+ | `lingxiaId` | string | No | Logical publishing ID, used by app publishing flows. |
130
+ | `lingxiaServer` | string \| map | No | LingXia server base URL paired with `lingxiaId`. Single string applies to every env, or per-env map (see Environment versions). |
131
+ | `packageIdSuffix` | map | No | Per-env override of the suffix appended to the bundle/package id (see Environment versions). |
132
+
133
+ `homeAppVersion` is not configured in `lingxia.yaml`; the CLI derives it from the matching `resources.bundles` source.
134
+
135
+ ---
136
+
137
+ ## Environment versions
138
+
139
+ A LingXia host build is always one of three envs — `developer`, `preview`, or `release` — selected via `lingxia {build,dev,package} --env <env>`. The default is `developer` for `build`/`dev` and `release` for `package`.
140
+
141
+ **What each env produces:**
142
+
143
+ | Env | Default `packageIdSuffix` | Launcher icon | Default `lingxia dev/build` | Default `lingxia package` |
144
+ |---|---|---|---|---|
145
+ | `developer` | `.dev` | red `D` badge | ✓ | |
146
+ | `preview` | `.preview` | red `P` badge | | |
147
+ | `release` | `(none)` | unmodified | | ✓ |
148
+
149
+ Different envs of the same app install **side by side** because their bundle/package ids differ. No git-tracked file changes when you switch envs — every effect lands in a build-output directory or is passed at build time.
150
+
151
+ ### Per-env `lingxiaServer`
152
+
153
+ Single URL (same for every env):
154
+
155
+ ```yaml
156
+ app:
157
+ lingxiaServer: https://api.myapp.com
158
+ ```
159
+
160
+ Per-env map (omit envs you don't have a server for — typical for `developer`):
161
+
162
+ ```yaml
163
+ app:
164
+ lingxiaServer:
165
+ developer: http://192.168.1.10:8080
166
+ preview: https://preview.api.myapp.com
167
+ release: https://api.myapp.com
168
+ ```
169
+
170
+ ### Per-env `packageIdSuffix`
171
+
172
+ Built-in defaults (`.dev` / `.preview` / `(none)`) cover most apps. Override only when you need custom suffixes:
173
+
174
+ ```yaml
175
+ app:
176
+ packageIdSuffix:
177
+ developer: .internal # → com.example.myapp.internal
178
+ preview: ".preview" # quote when starting with .
179
+ release: "" # "" = opt out of any suffix
180
+ ```
181
+
182
+ Validation rules:
183
+
184
+ - Each suffix must match `^\.[a-z0-9]+(\.[a-z0-9]+)*$` (start with `.`, lowercase a-z 0-9 segments) — or be `""` to opt out.
185
+ - Empty `lingxiaServer` string is rejected. Per-env map must have at least one entry set.
186
+ - Unknown keys (e.g. `enviroments:` typo) surface as YAML parse errors, not silent ignores.
187
+
188
+ ### Reading the env at runtime
189
+
190
+ JS Logic (`pages/*/index.ts`): `lx.app.envVersion` — `'developer' | 'preview' | 'release'`, fixed at app boot. See [Logic-side `lx.*` API](../lxapp/lx-api.md).
191
+
192
+ Rust host: `lingxia::env_version()` returns the same enum.
193
+
194
+ The build-time plumbing per platform (Android Gradle properties, iOS bundle id rewrite, Harmony staging mirror, publish-flow id matching) is internal — app authors don't touch it. Framework contributors can find the normative spec in `docs/internal/env-version.md` in the LingXia repo.
195
+
196
+ ---
197
+
198
+ ## `features` Section
199
+
200
+ `features` controls native Rust compile-time features. When `appService` is `false`, the CLI builds the host Rust library with `--no-default-features`. When `appService` is `true`, Cargo default features stay enabled and the CLI adds the selected features.
201
+
202
+ | Field | Type | Default | Description |
203
+ |---|---|---:|---|
204
+ | `appService` | bool | `true` | Enables JS/TS AppService runtime support. Set `false` for native-only hosts; logic-enabled lxapps will be rejected. |
205
+ | `shell` | bool | `false` | Enables product shell/browser chrome: browser, downloads, settings, panels. This can be used by native-only hosts. |
206
+ | `devtools` | bool | `false` | Compiles devtools hooks into the host. `lingxia dev` may temporarily enable it without editing YAML. |
207
+
208
+ `-t lxapp` projects always require an AppService-capable host. `-t native-app` projects may set `appService: false` when they only need native-hosted UI and host APIs.
209
+
210
+ ---
211
+
212
+ ## `capabilities` Section
213
+
214
+ `capabilities` is for platform/runtime integrations that must be predeclared before the SDK auto-enables them. Do not list ordinary SDK APIs such as camera here; those should request permission only when called.
215
+
216
+ | Field | Type | Default | Description |
217
+ |---|---|---:|---|
218
+ | `notifications` | bool | `false` | Enables push/notification integration where supported. iOS/Harmony SDK startup may request notification permission and fetch a push token. |
219
+ | `terminal` | bool | `false` | Enables the macOS terminal runtime. When true, the CLI auto-generates a bottom `terminal` App UI attach panel and sidebar activator if they are not already declared. |
220
+
221
+ ---
222
+
223
+ ## `shell` Section
224
+
225
+ `shell` is used only when `features.shell: true`. Normal apps can omit it and use the SDK default shell webui. Repo development can point to a local checkout; external apps should use the package form.
226
+
227
+ ```yaml
228
+ shell:
229
+ webui:
230
+ package: '@lingxia/shell-webui'
231
+ version: '0.5.1'
232
+ ```
233
+
234
+ | Field | Type | Required | Description |
235
+ |---|---|---:|---|
236
+ | `webui.path` | string | One of path/package | Project-relative path to a shell webui lxapp source tree. The CLI builds it. |
237
+ | `webui.package` | string | One of path/package | npm package containing prebuilt shell webui `lxapp.json` and `dist/`. |
238
+ | `webui.version` | string | With package | npm package version. If omitted, the CLI version is used. |
239
+
240
+ Do not use `app.homeAppId` for shell internals. `app.homeAppId` is the product home app; `shell.webui` is the shell/browser UI asset.
241
+
242
+ ---
243
+
244
+ ## `resources` Section
245
+
246
+ `resources.bundles` declares lxapp asset sources bundled into the native host. It does not decide what the app opens; `app.homeAppId` and `ui.surfaces[].content.appId` do that.
247
+
248
+ | Field | Type | Required | Description |
249
+ |---|---|---:|---|
250
+ | `bundles[].type` | string | Yes | Currently `lxapp`. |
251
+ | `bundles[].appId` | string | Yes | App id provided by this bundle. Must match the bundle `lxapp.json.appId`. |
252
+ | `bundles[].path` | string | No | Project-relative local lxapp source path. When set, the CLI builds and bundles it. |
253
+ | `bundles[].package` | string | No | npm package containing prebuilt `lxapp.json` and `dist/`. When set, the CLI downloads and bundles it. |
254
+ | `bundles[].version` | string | With package | npm package version. If omitted, the CLI version is used. |
255
+
256
+ Example:
257
+
258
+ ```yaml
259
+ resources:
260
+ bundles:
261
+ - type: lxapp
262
+ appId: lingxia-showcase
263
+ path: lingxia-showcase
264
+ - type: lxapp
265
+ appId: app.lingxia.browser
266
+ package: '@lingxia/shell-webui'
267
+ version: '0.5.1'
268
+ - type: lxapp
269
+ appId: lingxia-chat
270
+ ```
271
+
272
+ If a bundle entry has only `type` and `appId`, it declares the appId but does not bundle local assets; the runtime/update provider must make it available.
273
+
274
+ ---
275
+
276
+ ## `storage` Section
277
+
278
+ `storage` makes storage policy visible instead of relying on hidden defaults. Values are MiB.
279
+
280
+ | Field | Type | Default | Description |
281
+ |---|---|---:|---|
282
+ | `tempMaxSizeMB` | number | `1024` | Maximum host temp storage size. |
283
+ | `cacheMaxSizeMB` | number | `2048` | Per-LxApp usercache size cap. Cleanup triggers at 80% high water and LRU-evicts down to 50% low water. `0` disables size enforcement. |
284
+ | `dataMaxSizeMB` | number | `4096` | Maximum user data storage size. |
285
+ | `appStorageMaxSizeMB` | number | `16384` | Maximum app-scoped storage size. |
286
+
287
+ ---
288
+
289
+ ## `macos` Section
290
+
291
+ | Field | Type | Required | Description |
292
+ |---|---|---:|---|
293
+ | `bundleId` | string | No | macOS bundle identifier. |
294
+ | `deploymentTarget` | string | No | macOS deployment target, for example `"12.0"`. |
295
+ | `targetName` | string | Recommended | SwiftPM executable target name used for resource lookup. |
296
+ | `executableName` | string | Recommended | SwiftPM executable product/binary name. |
297
+
298
+ If `targetName` or `executableName` are omitted, the CLI tries reasonable defaults and then falls back to inference. Explicit names are preferred for reproducible builds.
299
+
300
+ ---
301
+
302
+ ## macOS App UI
303
+
304
+ The `ui` section describes product-level macOS UI: windows, panels, and native chrome entry points.
305
+
306
+ `Lingxia.quickStart()` loads bundled `app.json` and `ui.json`, initializes the runtime, creates the macOS shell window, and then applies this App UI model.
307
+
308
+ The model has three parts:
309
+
310
+ - `launch`: startup behavior.
311
+ - `surfaces`: UI containers.
312
+ - `activators`: native entry points that operate on surfaces.
313
+
314
+ ### Important Boundary
315
+
316
+ Settings and Downloads are built-in shell/browser entries. Do not duplicate them in `ui.activators`.
317
+
318
+ When the macOS native host is built with the `shell` feature, the shell provides built-in Settings and Downloads chrome. The example app should configure only product-specific entries such as Browser/Assistant panels.
319
+
320
+ ### `launch`
321
+
322
+ ```yaml
323
+ ui:
324
+ launch:
325
+ initialSurface: main
326
+ ```
327
+
328
+ | Field | Type | Required | Description |
329
+ |---|---|---:|---|
330
+ | `initialSurface` | string | Yes | Surface opened first. Must reference `ui.surfaces[].id`. |
331
+ | `openOnLaunch` | bool | No | Defaults to open-on-launch behavior. Set `false` for menu-bar style apps. |
332
+ | `splash.path` | string | No | Optional PNG source path copied into native resources as `splash.png`; macOS App UI does not present it yet. |
333
+
334
+ For menu-bar apps, use `openOnLaunch: false` and add a `menuBarItem` activator that toggles a panel anchored to the activator.
335
+
336
+ ### `surfaces`
337
+
338
+ A surface is a visible macOS container.
339
+
340
+ One sentence model: **a surface defines what can be shown, presentation defines
341
+ how it is shown, and activators define who opens it.**
342
+
343
+ Current macOS supported presentation kinds:
344
+
345
+ | Kind | Status | Description |
346
+ |---|---|---|
347
+ | `window` | Supported | Normal app window. |
348
+ | `panel` | Supported | Floating panel. Use `anchor: activator` to position it from the entry point that opened it. |
349
+ | `attachPanel` | Supported | Panel attached to the single root window/panel. |
350
+ | `embedded` | Rejected | Not implemented in macOS runtime. |
351
+
352
+ Current macOS rules:
353
+
354
+ - Exactly one root surface is required.
355
+ - The root surface must be `window` or `panel`.
356
+ - Menu-bar panels use `presentation.kind: panel` and `presentation.anchor: activator`; when opened by a `menuBarItem`, the activator is the menu-bar icon.
357
+ - `attachPanel` must set `presentation.attachTo`.
358
+ - `attachPanel.attachTo` must reference the root surface.
359
+ - `attachPanel.edge` must be `leading`, `trailing`, or `bottom`.
360
+ - `attachPanel.edge: top` is rejected.
361
+ - The stable `content.kind` today is `lxapp`.
362
+ - Each `lxapp` surface must currently use a unique `content.appId`.
363
+
364
+ Common presentation fields:
365
+
366
+ | Field | Applies To | Description |
367
+ |---|---|---|
368
+ | `kind` | all surfaces | `window`, `panel`, or `attachPanel` in the product model. Current runtime may still map this to platform-specific styles internally. |
369
+ | `anchor` | `panel` | Optional anchor. Use `activator` to position the panel from the native entry point that opened it. |
370
+ | `size.width` | `window`, `panel` | Optional initial width. Omit it to use the shell's native default. |
371
+ | `size.height` | `window`, `panel` | Optional initial height. Omit it to use the shell's native default. |
372
+ | `resizable` | `window`, `panel` | Whether the native window can resize. Defaults to `true`. |
373
+ | `showTrafficLights` | `window`, `panel` | Whether macOS traffic lights are shown. Defaults to `true` for `window` and `false` for menu-bar panels. |
374
+ | `attachTo` | `attachPanel` | Parent/root surface id. |
375
+ | `edge` | `attachPanel` | `leading`, `trailing`, or `bottom`. |
376
+
377
+ Content fields:
378
+
379
+ | Field | Required | Description |
380
+ |---|---:|---|
381
+ | `kind` | Yes | Use `lxapp` or `terminal`. `terminal` is currently macOS-only and must be used as a bottom `attachPanel`. |
382
+ | `appId` | For `lxapp` | Lxapp appId to open in this surface. |
383
+ | `path` | No | Initial route/path for `lxapp` content. |
384
+
385
+ Example root window:
386
+
387
+ ```yaml
388
+ surfaces:
389
+ - id: main
390
+ presentation:
391
+ kind: window
392
+ content:
393
+ kind: lxapp
394
+ appId: my-home
395
+ ```
396
+
397
+ `attachPanel` is supported by the macOS runtime. If the panel uses another lxapp, list it in `resources.bundles` for local bundling, or let the runtime/update provider fetch it.
398
+
399
+ Do not define separate `settings` or `downloads` surfaces for the built-in browser app. Those pages are opened by built-in shell controls.
400
+
401
+ ### `activators`
402
+
403
+ An activator is a native entry point that performs an action on a surface.
404
+
405
+ Supported macOS activator kinds:
406
+
407
+ | Kind | Scope | Status | Rules |
408
+ |---|---|---|---|
409
+ | `menuBarItem` | App-level | Supported | Must not set `hostSurface`. |
410
+ | `appActivation` | App-level | Supported | Must not set `hostSurface`. Runs when the app becomes active. |
411
+ | `sidebarItem` | Surface-owned | Supported | Must set `hostSurface`. Rendered in shell sidebar chrome. |
412
+ | `toolbarItem` | Surface-owned | Supported | Must set `hostSurface`. Rendered in navigation toolbar chrome. |
413
+ | `titlebarItem` | Surface-owned | Supported | Must set `hostSurface`. Rendered as a titlebar accessory action strip. |
414
+
415
+ `trayItem` is not a macOS App UI activator.
416
+
417
+ Supported action kinds:
418
+
419
+ | Action | Description |
420
+ |---|---|
421
+ | `toggleSurface` | If the surface is visible, close it; otherwise open it. |
422
+ | `openSurface` | Open the surface; if it already exists, focus/show it. |
423
+ | `closeSurface` | Hide the surface. Does not destroy the lxapp session or WebView. |
424
+ | `focusSurface` | Bring an already-visible surface to the front. Does not open it. |
425
+
426
+ All current App UI actions require:
427
+
428
+ ```yaml
429
+ action:
430
+ kind: toggleSurface
431
+ surface: someSurfaceId
432
+ ```
433
+
434
+ Examples:
435
+
436
+ ```yaml
437
+ activators:
438
+ - id: homeSidebar
439
+ kind: sidebarItem
440
+ hostSurface: main
441
+ label: Home
442
+ icon: icons/home.svg
443
+ action:
444
+ kind: focusSurface
445
+ surface: main
446
+ ```
447
+
448
+
449
+ ```yaml
450
+ activators:
451
+ - id: menuBar
452
+ kind: menuBarItem
453
+ label: My App
454
+ icon: icons/menu.svg
455
+ action:
456
+ kind: toggleSurface
457
+ surface: main
458
+ ```
459
+
460
+ Surface-owned activators are visible only while their `hostSurface` is visible.
461
+
462
+ ### Assistant Panel Example
463
+
464
+ This shape uses one main app window plus an attached AI assistant panel. Settings and Downloads remain shell built-ins. `lingxia-chat` can be bundled locally through `resources.bundles`, or omitted there and fetched by runtime/update flow.
465
+
466
+ ```yaml
467
+ ui:
468
+ launch:
469
+ initialSurface: main
470
+ surfaces:
471
+ - id: main
472
+ presentation:
473
+ kind: window
474
+ content:
475
+ kind: lxapp
476
+ appId: lingxia-showcase
477
+ - id: assistant
478
+ presentation:
479
+ kind: attachPanel
480
+ attachTo: main
481
+ edge: trailing
482
+ content:
483
+ kind: lxapp
484
+ appId: lingxia-chat
485
+ activators:
486
+ - id: assistantSidebar
487
+ kind: sidebarItem
488
+ hostSurface: main
489
+ label: AI Chat
490
+ icon: lingxia-chat/chat.svg
491
+ action:
492
+ kind: toggleSurface
493
+ surface: assistant
494
+
495
+ ```
496
+
497
+ ### Terminal Panel (Native Host, Shared Rust Engine)
498
+
499
+ The App UI runtime supports a native terminal surface that can be opened from product chrome and shown as a bottom panel. macOS is the first host, but the runtime boundary is designed for Windows to reuse the same Rust terminal engine.
500
+
501
+ Current scope and limits:
502
+
503
+ - macOS first; Windows should attach to the same Rust session/snapshot API instead of reimplementing terminal semantics.
504
+ - `content.kind: terminal` only.
505
+ - `presentation.kind: attachPanel` only.
506
+ - `presentation.edge: bottom` only.
507
+ - `content.backend` is not product config. If present, validation rejects it.
508
+ - Rust owns terminal sessions, PTY/conpty transport, `libghostty-vt` terminal semantics, themes, and the stable snapshot/input protocol.
509
+ - Platform SDKs own only native view rendering, focus/input event capture, clipboard/menu integration, and host UX such as tabs/splits/panel lifecycle.
510
+
511
+ Ghostty preparation is handled by `crates/lingxia-terminal/build.rs`. Terminal builds use a pinned Ghostty git checkout and build `libghostty-vt`; the build script does not fetch release tarballs.
512
+
513
+ ```bash
514
+ cargo build -p lingxia --features shell-runtime
515
+ ```
516
+
517
+ Supported build-time inputs:
518
+
519
+ | Environment | Description |
520
+ |---|---|
521
+ | `LINGXIA_GHOSTTY_SOURCE_DIR=/path/to/ghostty` | Uses an existing local checkout/source tree. |
522
+ | `LINGXIA_GHOSTTY_REV=<rev>` | Overrides the pinned Ghostty git revision. If omitted, LingXia uses the pinned revision in `crates/lingxia-terminal/build.rs`. |
523
+ | `LINGXIA_GHOSTTY_REPO=<url>` | Overrides the git repo used with `LINGXIA_GHOSTTY_REV`. |
524
+ | `LINGXIA_GHOSTTY_ZIG=/path/to/zig` | Overrides the `zig` executable. |
525
+ | `LINGXIA_GHOSTTY_ZIG_ARGS="..."` | Appends extra `zig build` arguments. |
526
+
527
+ Target behavior:
528
+
529
+ - A terminal icon in product chrome toggles the terminal surface.
530
+ - Terminal surface is attached to the main window with `attachPanel.edge: bottom`.
531
+ - The terminal workspace supports multi-tab sessions.
532
+ - Each tab supports pane split in `left`, `right`, `up`, and `down` directions.
533
+ - Hiding the surface should preserve terminal sessions (same lifecycle expectation as `closeSurface`).
534
+
535
+ Example shape:
536
+
537
+ ```yaml
538
+ ui:
539
+ launch:
540
+ initialSurface: main
541
+ surfaces:
542
+ - id: main
543
+ presentation:
544
+ kind: window
545
+ content:
546
+ kind: lxapp
547
+ appId: lingxia-showcase
548
+ - id: terminal
549
+ presentation:
550
+ kind: attachPanel
551
+ attachTo: main
552
+ edge: bottom
553
+ size:
554
+ height: 320
555
+ content:
556
+ kind: terminal
557
+ activators:
558
+ - id: terminalSidebar
559
+ kind: sidebarItem
560
+ hostSurface: main
561
+ label: Terminal
562
+ icon: icons/terminal.svg
563
+ action:
564
+ kind: toggleSurface
565
+ surface: terminal
566
+ ```
567
+
568
+ Engine/platform boundary:
569
+
570
+ - `crates/lingxia-terminal` is the product terminal engine. Public APIs use `terminal_*` naming; `portable-pty` is an internal transport detail.
571
+ - The engine emits JSON snapshots containing grid size, cells, grapheme text, colors, attributes, cursor state, title, alternate-screen state, and lifecycle state.
572
+ - macOS renders snapshots into `NSView`; Windows should render the same snapshots into its native view while sharing session create/write/resize/close behavior.
573
+ - Do not add backend selectors to `lingxia.yaml`; backend choice is owned by the runtime.
574
+
575
+ Implementation notes for native hosts:
576
+
577
+ - Terminal content is mounted as the platform-native terminal view (`NSView` on macOS, Windows-native view later) into the attachPanel container.
578
+ - Keep terminal runtime state in native host scope: `surface -> tabs -> split tree -> panes`.
579
+ - Drive split layouts with native split containers and map each pane to one terminal session.
580
+ - Add native terminal commands for: new tab, close tab, split left/right/up/down, and focus movement between panes.
581
+
582
+ Future phases:
583
+
584
+ 1. Phase 1: bottom terminal surface with single tab/single pane.
585
+ 2. Phase 2: multi-tab support with stable session lifecycle.
586
+ 3. Phase 3: four-direction split and pane focus/resize behavior.
587
+
588
+ ### Menu Bar Panel Example
589
+
590
+ This example uses a single declarative `panel` surface opened by the native
591
+ menu-bar icon. The current macOS runtime supports exactly one root
592
+ `window`/`panel` surface, so this example does not also declare a separate main
593
+ window.
594
+
595
+ `menuBarItem` is the native entry point. `presentation.kind: panel` describes
596
+ how the `menu` surface is displayed. `presentation.anchor: activator` means the
597
+ panel is positioned from whichever native entry point opened it; in this example
598
+ that entry point is the menu-bar icon.
599
+
600
+ ```yaml
601
+ ui:
602
+ launch:
603
+ initialSurface: menu
604
+ openOnLaunch: false
605
+ surfaces:
606
+ - id: menu
607
+ presentation:
608
+ kind: panel
609
+ anchor: activator
610
+ resizable: false
611
+ showTrafficLights: false
612
+ size:
613
+ width: 360
614
+ height: 480
615
+ content:
616
+ kind: lxapp
617
+ appId: monitor-home
618
+ path: pages/menubar/index
619
+ activators:
620
+ - id: status
621
+ kind: menuBarItem
622
+ label: Monitor
623
+ icon: icons/monitor.svg
624
+ action:
625
+ kind: toggleSurface
626
+ surface: menu
627
+ ```
628
+
629
+ Runtime behavior:
630
+
631
+ - If the app only has menu-bar activators and no app-activation activator, it can run as an accessory-style menu-bar app.
632
+ - Clicking the menu-bar icon toggles the `menu` surface.
633
+ - The `menu` surface renders `monitor-home/pages/menubar/index`.
634
+ - The string `menu` is a surface ID, not a page path.
635
+ - A menu-bar anchored panel is positioned from the source menu-bar item.
636
+
637
+ ### App Activation Example
638
+
639
+ Use `appActivation` when clicking the Dock icon or activating the app should focus/open a known surface.
640
+
641
+ ```yaml
642
+ activators:
643
+ - id: activateMain
644
+ kind: appActivation
645
+ action:
646
+ kind: openSurface
647
+ surface: main
648
+ ```
649
+
650
+ If an app has `appActivation` activators, the macOS runtime uses regular app activation behavior.
651
+
652
+ ---
653
+
654
+ ## Icon Paths
655
+
656
+ `ui.activators[].icon` is a source icon path relative to the host project root.
657
+
658
+ Current macOS App UI supports SVG source icons only. During `lingxia build`, the CLI validates each source icon, converts it to a PDF resource, copies it into generated `icons/`, and rewrites the generated `ui.json` to reference that generated resource path.
659
+
660
+ Example:
661
+
662
+ ```yaml
663
+ icon: icons/browser.svg
664
+ ```
665
+
666
+ Validation rules:
667
+
668
+ | Check | Rule |
669
+ |---|---|
670
+ | Source format | SVG only |
671
+ | Path | Relative to host project root; absolute paths and `..` are rejected |
672
+ | File size | Maximum 512 KB |
673
+ | SVG viewport size | 16x16 px through 512x512 px |
674
+ | Aspect ratio | Must be square, within a small tolerance |
675
+
676
+ Generated macOS resource paths look like:
677
+
678
+ ```text
679
+ icons/browser-<hash>.pdf
680
+ ```
681
+
682
+ Do not reference generated lxapp runtime assets such as `app.lingxia.browser/public/LingXia.png` for native chrome icons. Use a host-root-relative SVG source file instead; it is fine for that source file to live inside the home lxapp project, because the CLI converts and copies it into native host resources.
683
+
684
+ ---
685
+
686
+ ## Generated Files
687
+
688
+ During `lingxia build`, the CLI generates platform resources:
689
+
690
+ - `app.json`: runtime app metadata.
691
+ - `ui.json`: macOS App UI structure.
692
+ - `icons/*.pdf`: generated macOS native chrome icons.
693
+ - `splash.png`: optional copied splash image when `ui.launch.splash.path` is configured.
694
+ - bundled lxapp directories from `resources.bundles`.
695
+ - bundled shell webui directory when `features.shell: true`.
696
+ - `bridge-runtime.js`.
697
+
698
+ For macOS, these are copied into the SwiftPM target resource directory, usually `macos/Sources/<targetName>/Resources` unless the target declares a custom `path`.
699
+
700
+ Generated files are build artifacts. Edit `lingxia.yaml` instead.
701
+
702
+ ---
703
+
704
+ ## Build
705
+
706
+ Build macOS from the host project root:
707
+
708
+ ```bash
709
+ lingxia build --platform macos --framework vue
710
+ ```
711
+
712
+ The macOS host build does the following:
713
+
714
+ - Builds the configured home lxapp resource bundle.
715
+ - Generates `app.json` and `ui.json`.
716
+ - Builds the Rust host static library.
717
+ - Enables the native `shell` feature for macOS builds by default.
718
+ - Builds the SwiftPM macOS app.
719
+ - Packages the `.app` under `macos/.lingxia/`.
720
+
721
+ Example output:
722
+
723
+ ```text
724
+ macos/.lingxia/My App.app
725
+ ```
726
+
727
+ If `--skip-native` is used, SwiftPM links an existing Rust static library. That can leave runtime capabilities stale, including shell/browser capability bits. For App UI debugging, prefer a normal build without `--skip-native`.
728
+
729
+ ---
730
+
731
+ ## Common Pitfalls
732
+
733
+ - Adding Settings or Downloads to `ui.activators`: these are built-in shell entries, not product UI activators.
734
+ - Adding `trayItem` to macOS `ui.activators`: it is not a macOS App UI activator.
735
+ - Defining multiple surfaces with the same `content.appId`: current macOS runtime rejects this.
736
+ - Using `attachPanel` without `attachTo` or `edge`.
737
+ - Attaching a panel to another panel instead of the root surface.
738
+ - Using `attachPanel.edge: top`, which is not supported yet.
739
+ - Expecting `closeSurface` to destroy WebViews; it hides the surface.
740
+ - Using PNG or generated lxapp runtime images for `ui.activators[].icon`; App UI icons must be host-root-relative SVG source files.
741
+ - Defining `content.kind: terminal` outside `attachPanel` or with non-`bottom` edge; current terminal surfaces are bottom attach panels only.
742
+ - Adding terminal backend selectors to product config; the runtime owns backend selection.
743
+ - Editing generated `app.json` or `ui.json`.
744
+ - Running an older `lingxia` binary from `PATH` after changing config schema or CLI validation.
745
+
746
+ ---
747
+
748
+ ## Out Of Scope / Not Implemented In macOS App UI
749
+
750
+ This page intentionally does not define product behavior for:
751
+
752
+ - splash presentation
753
+ - multiple root windows
754
+ - embedded native host surfaces
755
+ - attach panels nested under other panels
756
+ - top-attach panels
757
+ - reusing one lxapp appId across multiple surfaces
758
+ - page-owned App UI APIs for toggling or closing surfaces from lxapp content
759
+ - terminal surfaces outside macOS `attachPanel` bottom shape
760
+ - terminal backend selection in App UI config