@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.
- package/README.md +95 -0
- package/bin/install.mjs +247 -0
- package/package.json +49 -0
- package/scripts/sync.mjs +69 -0
- package/skill/SKILL.md +334 -0
- package/skill/app/apple-sdk.md +312 -0
- package/skill/app/applinks.md +289 -0
- package/skill/app/project.md +760 -0
- package/skill/cli/lxdev.md +195 -0
- package/skill/cli/reference.md +481 -0
- package/skill/examples/hello-host-js/README.md +25 -0
- package/skill/examples/hello-host-js/home/lxapp.json +12 -0
- package/skill/examples/hello-host-js/home/pages/home/index.json +4 -0
- package/skill/examples/hello-host-js/home/pages/home/index.ts +14 -0
- package/skill/examples/hello-host-js/home/pages/home/index.tsx +15 -0
- package/skill/examples/hello-host-js/lingxia.yaml +39 -0
- package/skill/examples/hello-host-rust/Cargo.toml +15 -0
- package/skill/examples/hello-host-rust/README.md +44 -0
- package/skill/examples/hello-host-rust/home/lxapp.json +13 -0
- package/skill/examples/hello-host-rust/home/pages/home/index.html +46 -0
- package/skill/examples/hello-host-rust/home/pages/home/index.json +4 -0
- package/skill/examples/hello-host-rust/lingxia.yaml +32 -0
- package/skill/examples/hello-host-rust/src/lib.rs +58 -0
- package/skill/examples/hello-lxapp/README.md +29 -0
- package/skill/examples/hello-lxapp/lxapp.config.ts +8 -0
- package/skill/examples/hello-lxapp/lxapp.json +14 -0
- package/skill/examples/hello-lxapp/package.json +14 -0
- package/skill/examples/hello-lxapp/pages/home/index.json +4 -0
- package/skill/examples/hello-lxapp/pages/home/index.ts +35 -0
- package/skill/examples/hello-lxapp/pages/home/index.tsx +34 -0
- package/skill/lxapp/bridge.md +654 -0
- package/skill/lxapp/components.md +375 -0
- package/skill/lxapp/guide.md +675 -0
- package/skill/lxapp/lx-api.md +481 -0
- package/skill/native/development.md +414 -0
- package/skill/reference/file-lifecycle.md +325 -0
- 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
|