uniweb 0.48.3 → 0.48.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniweb",
3
- "version": "0.48.3",
3
+ "version": "0.48.4",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,14 +42,14 @@
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
44
  "@uniweb/core": "^0.24.3",
45
- "@uniweb/semantic-parser": "^1.4.0",
45
+ "@uniweb/kit": "^0.18.1",
46
46
  "@uniweb/runtime": "^0.19.4",
47
- "@uniweb/kit": "^0.18.1"
47
+ "@uniweb/semantic-parser": "^1.4.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@uniweb/build": "^0.44.2",
51
50
  "@uniweb/content-reader": "^1.2.4",
52
- "@uniweb/semantic-parser": "^1.4.0"
51
+ "@uniweb/semantic-parser": "^1.4.0",
52
+ "@uniweb/build": "^0.44.3"
53
53
  },
54
54
  "peerDependenciesMeta": {
55
55
  "@uniweb/build": {
@@ -716,7 +716,7 @@ Measured on exactly that shape: **the agent corpus holds every page; the public
716
716
  - **A static host** (`uniweb export`, `deploy --host`) drops every page — they have no reader there — and you get an empty SPA shell. The build still says *"complete"*, because 0 pages is not an error: it reports `Collected 0 pages` and pre-renders none.
717
717
  - **A backend-hosted deployment that does not offer the service.** Whether an agent endpoint exists is the host's to decide, per site — it is not implied by deploying successfully.
718
718
 
719
- ⇒ **The way to know is to ask, at render:** `resolveService(website, 'assistant')` returns a `url` only where the host declared one. On a site that is *only* knowledge there is no component to ask — so confirm with your host that the agent is enabled for that site before you build an integration against it. If you meant to build an agent endpoint and got silence, this is where to look.
719
+ ⇒ **The way to know is to ask, at render:** `isAssistantEnabled()` from `@uniweb/kit` is true only where an agent endpoint is declared. On a site that is *only* knowledge there is no component to ask — so confirm with your host that the agent is enabled for that site before you build an integration against it. If you meant to build an agent endpoint and got silence, this is where to look.
720
720
 
721
721
  ### Your site is readable by agents, automatically
722
722
 
@@ -1904,7 +1904,26 @@ A form gets its destination from the first of these that applies:
1904
1904
 
1905
1905
  That is the general arrangement, not a forms-only one. A host declares
1906
1906
  everything it offers under `services`, keyed by name, and every service resolves
1907
- by the same rule — your declaration, then the host's, then neither:
1907
+ by the same rule — your declaration, then the host's, then neither.
1908
+
1909
+ ⭐ **Before you render UI for a service, ask whether the site has it** — one predicate per service,
1910
+ no arguments: `isSearchEnabled()`, `isSubmitEnabled()`, `isApiEnabled()`, `isAssistantEnabled()`,
1911
+ `isTrackingEnabled()`.
1912
+
1913
+ ```jsx
1914
+ import { isSearchEnabled } from '@uniweb/kit'
1915
+
1916
+ if (!isSearchEnabled()) return null // false ⇒ draw nothing
1917
+ ```
1918
+
1919
+ Each answers the same question — *would UI for this service work on this site?* — and `false`
1920
+ always means the same thing: **draw nothing.** `isSearchEnabled()` is true whenever *any* provider
1921
+ answers, including the prebuilt index a static site ships, so a search box gated on it appears
1922
+ wherever search works. The hooks that draw a feature hand you the same answer as a field
1923
+ (`useSearch().isEnabled`, `useFormSubmit().canSubmit`), so a component already using one needs
1924
+ nothing extra.
1925
+
1926
+ When you need the **address** itself, not just whether one exists, ask for it:
1908
1927
 
1909
1928
  ```jsx
1910
1929
  import { resolveService } from '@uniweb/kit'
@@ -1914,7 +1933,8 @@ const { url, source } = resolveService(website, 'assistant') // or 'search', o
1914
1933
 
1915
1934
  **The name is open**: the framework ships clients for what it implements and
1916
1935
  resolution for anything, so a foundation can define a service the framework has
1917
- never heard of and a host can fill it. Same escalation `fetcher.transports`
1936
+ never heard of and a host can fill it ask for it with
1937
+ `website.isServiceEnabled('booking')`. Same escalation `fetcher.transports`
1918
1938
  offers for data.
1919
1939
 
1920
1940
  **Building an "Ask AI" component?** The service name is `assistant`, and a host that runs an agent for a site typically serves it at the conventional path `/_agent`. **You should never need to write that path** — ask the runtime instead:
@@ -1936,7 +1956,7 @@ if (!url) return null // this site has no agent — render nothing, or
1936
1956
 
1937
1957
  ### Declaring what your foundation supports
1938
1958
 
1939
- `resolveService` is how you ask at render time. The other direction — telling a
1959
+ The predicates above, and `resolveService`, are how you ask at render time. The other direction — telling a
1940
1960
  host, *before* anything renders, which services your foundation is built to use —
1941
1961
  is one line in the foundation's `package.json`:
1942
1962
 
@@ -1953,23 +1973,24 @@ against it.** A host that offers search has no way to know whether your sections
1953
1973
  draw a search box, so without this it either offers a site something its code
1954
1974
  will ignore, or withholds something it would have used.
1955
1975
 
1956
- **Three states, and they are three different answers:**
1976
+ **What a host receives is one of three answers:**
1957
1977
 
1958
1978
  | | |
1959
1979
  |---|---|
1960
- | the key is **absent** | *unknown* nobody said. Not a refusal |
1961
- | `"supports": []` | an explicit *none*this foundation honours no host service |
1962
- | `"supports": ["search"]` | these, and only these |
1980
+ | a list `["search"]` | the services this foundation renders against, and only these |
1981
+ | `[]` | none — proven by the build, not assumed |
1982
+ | absent | *unknown* — the build could not tell, and nothing was declared |
1963
1983
 
1964
- **Nothing is assumed on your behalf**, in either direction. An unstated set is
1965
- never read as "all" and never as "none", so the only way a host learns your
1966
- search box exists is that you said so.
1984
+ **The build reads the set off your code.** When the foundation is built, `supports` is derived
1985
+ from what the bundle actually reaches `resolveService(website, 'search')`, or a predicate like
1986
+ `isSearchEnabled()` so a foundation that never writes the key still publishes an accurate set.
1987
+ What you write in `package.json` is a **supplement**: the build publishes the union, so a
1988
+ declaration can add a service but never remove one the code reaches.
1967
1989
 
1968
- **List what you actually integrate.** `uniweb doctor` warns when your source
1969
- reaches for a service you did not list but it reads your code with a pattern
1970
- matcher, so it sees `resolveService(website, 'search')` and misses a service
1971
- reached through a variable or a helper. It can tell you that you forgot one; it
1972
- cannot promise it found them all. The declaration is yours to keep accurate.
1990
+ **Declare only what the build cannot see.** A service reached through a *computed* name —
1991
+ `resolveService(website, name)` where `name` is a variableis invisible to it, and the build
1992
+ warns when that happens. List those. `uniweb doctor` compares what you declared with what the build
1993
+ found.
1973
1994
 
1974
1995
  ⚖️ **Baseline behaviour is not yours to declare.** Some services do something for
1975
1996
  a site whether or not a foundation cooperates — the runtime reports page views
@@ -2253,8 +2274,8 @@ happened into a journey.
2253
2274
  Everything above reaches the runtime through `@uniweb/kit` or through something
2254
2275
  handed to your component as a prop. That is the rule, not a stylistic preference:
2255
2276
 
2256
- - ✅ `useWebsite()`, `useTracker()`, `resolveService(website, …)` kit hooks and
2257
- utilities.
2277
+ - ✅ `useWebsite()`, `useTracker()`, `isSearchEnabled()` and the other service
2278
+ predicates, `resolveService(website, …)` — kit hooks and utilities.
2258
2279
  - ✅ `block.track(…)`, `block.page`, `block.website` — the block **arrives in your
2259
2280
  props**, so calling methods on it is not reaching for a global.
2260
2281
  - ⛔ `globalThis.uniweb`, `window.uniweb` — never, in a foundation.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-09-10T13:34:53.674Z",
3
+ "generatedAt": "2026-09-10T14:59:00.380Z",
4
4
  "packages": {
5
5
  "@uniweb/api": {
6
6
  "version": "0.3.0",
@@ -10,7 +10,7 @@
10
10
  ]
11
11
  },
12
12
  "@uniweb/build": {
13
- "version": "0.44.2",
13
+ "version": "0.44.3",
14
14
  "path": "framework/build",
15
15
  "deps": [
16
16
  "@uniweb/content-reader",
@@ -110,7 +110,7 @@
110
110
  "deps": []
111
111
  },
112
112
  "@uniweb/templates": {
113
- "version": "0.12.2",
113
+ "version": "0.12.3",
114
114
  "path": "framework/templates",
115
115
  "deps": []
116
116
  },