@wix/himalaya-cli 0.1584.0 → 0.1585.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.
Binary file
@@ -106,7 +106,6 @@ auth: WixConsumerAuthProvider({
106
106
  | `HIMI_BRANDED_LITE_WIX_SITE_URL` | `WIX_SITE_URL` | Public site URL (login / member flows) |
107
107
  | `HIMI_BRANDED_LITE_WIX_REDIRECT_URI` | `WIX_REDIRECT_URI` | OAuth callback (default: `himalaya-demo-app://oauth/callback` for shared amit1) |
108
108
  | `HIMI_BRANDED_LITE_WIX_BOOT_VISITOR` | — | `"1"` (default) boots as anonymous visitor |
109
- | `HIMI_BRANDED_LITE_FROG_SRC` | — | Per-customer Frog BI `src` (dev default `172`) |
110
109
 
111
110
  Defaults today = shared Amit1 Headless (`clientId` `4f58d461-…`, site `shayco5.wixsite.com/amit1`).
112
111
 
@@ -150,6 +149,13 @@ Sites List, a persisted active business, and per-call site scope via `site.forSi
150
149
  To bind a build to a customer, fix **clientId + siteUrl** (and `provisioning.siteId` for
151
150
  the identity the CLI reports) to the real customer site.
152
151
 
152
+ `provisioning.siteId` also names the customer in **Wix BI**: the served frog config resolves
153
+ the RN Branded `mobile_app_id`, `brandedLite_{msid}`, from it, because the binary
154
+ itself holds no msid. Left at the `development-site` placeholder, every BI event goes without
155
+ `mobile_app_id`, and the RN Branded dashboards cannot attribute it to the customer.
156
+ `himi site analyze --apply` writes the real one, and so does
157
+ `himi site create --write-provisioning`.
158
+
153
159
  ---
154
160
 
155
161
  ## 2. Fixed shareable build — site + icon + splash
@@ -176,13 +176,16 @@ responsive master/detail. *Reach for `Card` to cluster, not to wrap every single
176
176
  (`columns: 1, columnsMedium: 2`); `Table` for tabular rows; `Carousel`/`Pager` for swipeable panels;
177
177
  `Timeline` for chronological events. Compose rows as `ListItem` / `LabeledContent` / `DisclosureGroup`
178
178
  cells inside a `Card([VStack(spacing: 0)])`.
179
- > For a feed/list *screen*, prefer a root `VStack` with a direct vertical worker-bound `LazyList`
180
- > when the screen has the simple root shape supported by the native host; Android flattens that
181
- > shape into one lazy root so long lists do not compose every row. Other root shapes stay on the
182
- > eager screen path, as does a root list that sets `pagination`, `stickyHeader` or
183
- > `rowSwipeActions`. A `LazyList` nested deeper inside the screen's outer scroll is rendered
184
- > eagerly on Android to avoid nested-scroll measurement failures, even in a fixed-height panel. A
185
- > worker-bound horizontal `LazyList` is eager on Android too, so keep rails short.
179
+ > For a feed/list *screen*, put a vertical worker-bound `LazyList` directly in a plain root
180
+ > `VStack`, as the screen's only bound list: the root carries padding and a literal background at
181
+ > most, is leading-aligned, starts with a child that is always shown, and holds no `Spacer` or
182
+ > weighted child. Android then makes the whole screen one lazy list that builds only the rows in
183
+ > view and recycles them, paged lists included. A root list with
184
+ > `stickyHeader`, `rowSwipeActions`, `staggerMs`, `animateItems`, `reverseLayout`, content insets or
185
+ > negative `spacing` keeps the screen on the plain path. There, and in a bound `LazyList` nested deeper in the screen
186
+ > (inside a `Card` or another stack), rows are built as they scroll into view but every row built
187
+ > stays built, so a long list grows heavier as the user scrolls. A worker-bound horizontal
188
+ > `LazyList` builds every card at once on Android, so keep rails short. See §7b.
186
189
 
187
190
  **Cursor-backed lists and grids use automatic pagination.** Bind `pagination.cursor` and
188
191
  `pagination.onLoadMore` on every layout, including compact and grid variants. Do not add a
@@ -576,6 +579,42 @@ nicety. Don't animate everything: if every element moves, nothing reads as impor
576
579
 
577
580
  ---
578
581
 
582
+ ## 7b. Fast screens
583
+
584
+ A screen feels fast when it builds only what the user sees and answers a tap at once. The platform
585
+ does most of that work; these choices are the author's. `himi validate` warns when a screen breaks
586
+ one of the first three.
587
+
588
+ - **Put a long or paged list at the scroll root.** A vertical worker-bound `LazyList` placed directly
589
+ in a plain root `VStack`, as the screen's only bound list, is recycled row by row on Android (§3,
590
+ Lists & collections, says what "plain" means); the same list
591
+ as the screen's root, inside a `Card` or a nested stack, or carrying `stickyHeader`,
592
+ `rowSwipeActions`, `staggerMs`, `animateItems`, `reverseLayout`, content insets, negative `spacing`,
593
+ scroll anchors or modifiers, keeps every row it has built. Warning:
594
+ `paged_list_not_at_scroll_root`, for a list with `pagination` in any of those places.
595
+ - **Give every row a stable id.** Each item a worker returns for a list, grid or carousel carries its
596
+ own unique `id`. With one, a row keeps its identity when items are inserted or reordered. Without
597
+ one, rows are matched by position: rows after an insert are rebuilt as other items, and row state
598
+ such as an expanded section moves to the wrong item. Warning:
599
+ `bound_rows_without_stable_id`, when the worker's starting items have no ids or repeat one.
600
+ - **Declare `nav` when a tap always opens the same screen.** The screen then opens on the tap, not
601
+ after the worker answers (`himi docs tier-5-add-a-screen`, "Navigate before the worker answers").
602
+ Warning: `declared_navigation_available`, when a tap's reducer can only ever return one fixed
603
+ destination and the action declares none (`himi docs tier-5-add-a-screen` says what it can
604
+ prove).
605
+ - **Keep horizontal rails short.** A worker-bound horizontal list builds every card at once on
606
+ Android. Show the first dozen or so and link to the full list.
607
+ - **Give row images a fixed size.** A fixed `height` or `aspectRatio` reserves the image's space
608
+ before it arrives, so the row does not jump or grow when it lands.
609
+ - **Page long data.** Bind `pagination` and load the next page as the user nears the end (§3); a
610
+ worker that loads hundreds of rows up front pays for all of them before the first frame.
611
+ - **Cascade the first rows only.** `staggerMs` animates the first rows a list shows. On a long root
612
+ list it also keeps Android from recycling rows, so leave it off there.
613
+ - **Let the screen draw loading.** Ship the designed loading state (§5) and nothing more: no spinner
614
+ of your own over content that is already shown.
615
+
616
+ ---
617
+
579
618
  ## 8. Design-kit awareness — compose so a kit can restyle you
580
619
 
581
620
  Screens should look right under **any** adopted kit (`liquid-glass`, `material`, `dark-luxe`, … —
@@ -610,6 +649,7 @@ Run this punch list on the screen (it's also a good reviewer checklist):
610
649
  - [ ] Verified in **both** light and dark (and highContrast for load-bearing color)?
611
650
  - [ ] RTL-safe — leading/trailing alignment + logical insets throughout?
612
651
  - [ ] Kit-clean — no hardcoded look a kit would override; `material`/gradient/background precedence respected?
652
+ - [ ] Fast (§7b) — long or paged lists at the scroll root, stable row ids, `nav` on taps whose destination is fixed, short rails, fixed-size row images?
613
653
 
614
654
  ---
615
655
 
@@ -560,6 +560,22 @@ Wix data never reach it, and there is no live-data path yet, so a widget written
560
560
  ships its placeholder. Design it around initial state, constants or a `timeline`, and deep-link the
561
561
  tap into the screen that has the live data.
562
562
 
563
+ ## Fast screens
564
+
565
+ Read §7b of `himi docs designing-himi-screens` before you build a list or a tap that opens a screen.
566
+ A screen is fast when it builds only the rows in view and opens the next screen on the tap:
567
+
568
+ - A long or paged list sits directly in a plain root `VStack`, as the screen's only bound list, so it is
569
+ recycled row by row.
570
+ - Every item a worker returns for a list has a stable `id`, so a row keeps its identity, and its state,
571
+ when items are inserted or reordered.
572
+ - An action whose tap always opens the same screen declares `nav`, so the screen opens before the
573
+ worker answers; the reducer keeps returning the same `_nav` for older apps.
574
+ - Horizontal rails stay short, and row images have a fixed `height` or `aspectRatio`.
575
+
576
+ `himi validate` warns on the first three (`paged_list_not_at_scroll_root`,
577
+ `bound_rows_without_stable_id`, `declared_navigation_available`). Resolve them before preview.
578
+
563
579
  ## Native UX evidence gate
564
580
 
565
581
  Before declaring a multi-screen app ready, run `himi ux audit --content . --strict` and resolve its findings. After driving each available native shell, persist the actual checks with `himi ux record`; record an unavailable platform with its reason rather than claiming coverage.
package/guides/index.json CHANGED
@@ -27,6 +27,7 @@
27
27
  "A screen that loads data asynchronously ships a designed LOADING state with it — a `Skeleton` shaped like the loaded layout when that layout is known (`StatefulSection` or `ActivityIndicator` when they fit the behavior better) — and a REDESIGN of a data screen reviews and updates that loading state in the same change, so it never shows the old layout. Loading is its own state, never the empty or the error state; a static screen gets no loading state (`himi docs designing-himi-screens` §5).",
28
28
  "CLASSIFY every error before you show it: offline, server failure, sign-in, site membership and permission each show an `ErrorState` (gated by `hiddenPath`): `variantPath` bound to the worker's error kind switches the copy and glyph, but `cta`, `title`, `body` and `ctaLabel` apply to every variant, so offline and server share one node with the retry `cta` while sign-in, permission and membership (`variant: \"permission\"` with its own `title`/`body`) keep a node each; user-facing copy — never `e.message`, a status code or an API error string — and a `cta` ONLY for a real recovery (Try again for offline, server and failed writes; the app's auth flow for sign-in; the site's join flow for `NotSiteMember` when available; none for permission, empty results or field errors). Empty results are the empty state, not an error. A refresh that fails KEEPS the rows and adds a `Banner` with retry; a load-more that fails keeps the rows and ends the list with a \"Couldn't load more\" row that retries the SAME cursor (`himi docs recipe-dynamic-list`), never the Banner, which reloads page 1. A sign-in, membership or permission failure CLEARS the rows instead — they are no longer the user's to see. Field errors stay in the field's slot; a failed action shows next to the action. (`himi docs designing-himi-screens` §5, `himi docs recipe-four-state`).",
29
29
  "Workers are sandboxed: no DOM, no timers, no raw fetch. Produce state synchronously in actions; do not rely on an ambient refresh tick.",
30
+ "Keep screens FAST (`himi docs designing-himi-screens`, §7b): put a long or paged list directly in the screen's root VStack, give every list item the worker returns a stable `id`, declare `nav` on an action whose tap always opens the same screen, keep horizontal rails short, and give row images a fixed size. Validation warns on the first three (`paged_list_not_at_scroll_root`, `bound_rows_without_stable_id`, `declared_navigation_available`).",
30
31
  "Declare every capability a worker uses in TWO places: the calling screen's logicBundle.declaredCapabilities (wix_platform, stream, camera, location, …) — undeclared calls are blocked — AND config.ts `capabilities`, the app-level list a binary is built with. The `capabilities` guide shows each id's import, what the binary needs and which shells serve it; validate flags an unknown id, an undeclared call, and (with `shell` in himalaya.content.json) an id that shell's binary does not serve. A capability with a native footprint (camera, location, push, …) only arrives with a new binary — an over-the-air push cannot add it. EXCEPTION: the Wix REST bridge (wix_api — the @himalaya/wix-* clients / wixApi.call) is ungated today (installed unconditionally), so it works WITHOUT a declaration; declaring wix_api is still recommended — it is where the platform is heading, and it documents what your worker touches.",
31
32
  "`validate`/`render` prove a screen is WELL-FORMED and, by default, paint its INITIAL state — NOT that the app's LOGIC is correct. A wrong reducer (a game that never ends, a bad total) passes both with ok:true. Run `himi test`: it needs NO test files — it boots each screen's real worker and dispatches every action your descriptor already declares, then reports anything that threw, stayed stuck on `loading`, or leaked a NaN/undefined/`$service:` token into visible text. It crawls on HERMETIC DATA by default (zero network): your `dev/net-mocks.json` first, then your config's CMS `seed:` rows, then a canned fixture of frozen real vertical responses shipped with the CLI — so the fetch-SUCCESS mapping path runs too, where data-shape bugs actually live (canned data exercises code paths, not API-contract truth). Two boot-only HOSTILE passes (every list empty; every request 500) then check the empty/outage day — their findings are errors, not warnings. It also runs the worker in a DEVICE-PARITY sandbox (no setTimeout/setInterval, as on JSC/WebView), so a bundle that would only die on the device fails locally instead — e.g. `svc.actions.load(…)` (actions are DIRECT methods; `.actions` is undefined on device). (You are NOT limited to the crawled states either: rendering with `--live` runs the worker's REAL fetches against live Wix — a minted anonymous visitor token from the app's clientId — so a render CAN prove real-data binding locally with no VPN/push; and injecting `state` (`{\"<svc>\":{…}}`) renders a specific mid-flow state without the network.)",
32
33
  "User-facing copy is CONFIGURATION, never hardcoded in a descriptor: route every string through a copy key with a stock fallback — `copyOf(key, fallback)` — and feed worker-emitted strings in as descriptor params, so any app/template consumer can retheme ALL copy without touching descriptors. Wire the seam yourself: declare a local `const COPY: Record<string,string> = {…}` in your content package plus `export const copyOf = (k, fallback) => COPY[k] ?? fallback;`, keyed `<screen>.<element>` so a later template publish is mechanical. Either way the rule is the same: no user-facing string baked into a descriptor literal."
@@ -854,6 +854,15 @@ what the reducer computed — and do not
854
854
  unresolved `$item.` value, an unknown presentation) is ignored and the action behaves as if
855
855
  `nav` were absent.
856
856
 
857
+ The other way round, `himi validate` suggests a declaration (`declared_navigation_available`, a
858
+ warning) for a tap whose reducer can only ever return one fixed `_nav`: its whole body is a single
859
+ `return`, built only from literals and its own parameters, with `_nav` last, or a `navigate(state,
860
+ { … })` call. Anything it cannot prove — a property read, a call, a branch — gets no suggestion, so
861
+ the absence of the warning does not mean a tap could not declare `nav`. It looks only at fields a
862
+ tap or a selection fires (`action`, `onTap`, `onLongPress`, a marker or date selection, bar
863
+ buttons, …), never at callbacks the runtime fires itself (`onAppear`, paging, playback, a visible
864
+ range change).
865
+
857
866
  A destination the reducer only reads from state the screen already shows can still be declared:
858
867
  `$service:` strings in `nav.screenId`, `nav.tab` and `nav.args` resolve when the tap happens,
859
868
  against the screen's worker, or against the saved state a cold screen painted from. Expose the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1584.0",
3
+ "version": "0.1585.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -72,5 +72,5 @@
72
72
  "artifactId": "himalaya-cli"
73
73
  }
74
74
  },
75
- "falconPackageHash": "f1ca254a55f9bb7d36feee8ce52a6f8cadb97ef9380ff0a18eece09b"
75
+ "falconPackageHash": "13c668a9a9c2afaf085f36d0e4f2399a3638d68746819beb1f1af2eb"
76
76
  }