uniweb 0.48.3 → 0.48.5
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 +7 -7
- package/partials/agents.md +60 -36
- package/src/framework-index.json +7 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.5",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"js-yaml": "^4.1.0",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.0.0",
|
|
44
|
-
"@uniweb/
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
47
|
-
"@uniweb/
|
|
44
|
+
"@uniweb/runtime": "^0.19.5",
|
|
45
|
+
"@uniweb/core": "^0.24.4",
|
|
46
|
+
"@uniweb/kit": "^0.18.2",
|
|
47
|
+
"@uniweb/semantic-parser": "^1.4.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@uniweb/
|
|
50
|
+
"@uniweb/semantic-parser": "^1.4.0",
|
|
51
51
|
"@uniweb/content-reader": "^1.2.4",
|
|
52
|
-
"@uniweb/
|
|
52
|
+
"@uniweb/build": "^0.44.4"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -86,7 +86,7 @@ Documentation paths in this guide are given bare — `development/creating-compo
|
|
|
86
86
|
| Theming and styling | `authoring/theming.md` |
|
|
87
87
|
| Authoring collections | `authoring/collections.md` |
|
|
88
88
|
| Where-object predicate format | `authoring/predicates.md` |
|
|
89
|
-
|
|
|
89
|
+
| Data sources / custom transports | `development/data-sources.md` |
|
|
90
90
|
| Building components | `development/creating-components.md` |
|
|
91
91
|
| Schemas in practice | `development/schemas-in-practice.md` |
|
|
92
92
|
| Workspace layouts and their wiring | `development/project-structures.md` |
|
|
@@ -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:** `
|
|
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
|
|
|
@@ -1843,7 +1843,7 @@ fetcher:
|
|
|
1843
1843
|
|
|
1844
1844
|
**Failures are visible, not empty:** a fetch that failed leaves its key ABSENT from `content.data` and names the message on `block.dataError[key]`; it is never delivered as `[]`, which means "no records". The page still renders — a section reads `dataError` to tell the two apart.
|
|
1845
1845
|
|
|
1846
|
-
When a plain `url:` is enough and when a transport is the answer: `development/
|
|
1846
|
+
When a plain `url:` is enough and when a transport is the answer: `development/data-sources.md`.
|
|
1847
1847
|
|
|
1848
1848
|
Full model: `reference/data-fetching.md`. Where-object format with examples: `authoring/predicates.md`.
|
|
1849
1849
|
|
|
@@ -1895,16 +1895,37 @@ section type, same arrangement as `fetcher:` and `search:`.
|
|
|
1895
1895
|
|
|
1896
1896
|
A form gets its destination from the first of these that applies:
|
|
1897
1897
|
|
|
1898
|
-
1.
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1898
|
+
1. **One the host supplies** — `services.submit` in the served payload. Where the
|
|
1899
|
+
host handles submissions, that is the destination and nothing in `site.yml`
|
|
1900
|
+
overrides it — so a site published to Uniweb Cloud normally needs **no
|
|
1901
|
+
`submit:` at all**.
|
|
1902
|
+
2. **`submit:` in `site.yml`** — an endpoint you name yourself, for a host that
|
|
1903
|
+
does not handle submissions, or a static site.
|
|
1902
1904
|
3. **Neither** — there is no destination, and the form says so instead of
|
|
1903
1905
|
guessing at one.
|
|
1904
1906
|
|
|
1905
1907
|
That is the general arrangement, not a forms-only one. A host declares
|
|
1906
1908
|
everything it offers under `services`, keyed by name, and every service resolves
|
|
1907
|
-
by the same rule —
|
|
1909
|
+
by the same rule — the host's offer, then your declaration, then neither.
|
|
1910
|
+
|
|
1911
|
+
⭐ **Before you render UI for a service, ask whether the site has it** — one predicate per service,
|
|
1912
|
+
no arguments: `isSearchEnabled()`, `isSubmitEnabled()`, `isApiEnabled()`, `isAssistantEnabled()`,
|
|
1913
|
+
`isTrackingEnabled()`.
|
|
1914
|
+
|
|
1915
|
+
```jsx
|
|
1916
|
+
import { isSearchEnabled } from '@uniweb/kit'
|
|
1917
|
+
|
|
1918
|
+
if (!isSearchEnabled()) return null // false ⇒ draw nothing
|
|
1919
|
+
```
|
|
1920
|
+
|
|
1921
|
+
Each answers the same question — *would UI for this service work on this site?* — and `false`
|
|
1922
|
+
always means the same thing: **draw nothing.** `isSearchEnabled()` is true whenever *any* provider
|
|
1923
|
+
answers, including the prebuilt index a static site ships, so a search box gated on it appears
|
|
1924
|
+
wherever search works. The hooks that draw a feature hand you the same answer as a field
|
|
1925
|
+
(`useSearch().isEnabled`, `useFormSubmit().canSubmit`), so a component already using one needs
|
|
1926
|
+
nothing extra.
|
|
1927
|
+
|
|
1928
|
+
When you need the **address** itself, not just whether one exists, ask for it:
|
|
1908
1929
|
|
|
1909
1930
|
```jsx
|
|
1910
1931
|
import { resolveService } from '@uniweb/kit'
|
|
@@ -1914,7 +1935,8 @@ const { url, source } = resolveService(website, 'assistant') // or 'search', o
|
|
|
1914
1935
|
|
|
1915
1936
|
**The name is open**: the framework ships clients for what it implements and
|
|
1916
1937
|
resolution for anything, so a foundation can define a service the framework has
|
|
1917
|
-
never heard of and a host can fill it
|
|
1938
|
+
never heard of and a host can fill it — ask for it with
|
|
1939
|
+
`website.isServiceEnabled('booking')`. Same escalation `fetcher.transports`
|
|
1918
1940
|
offers for data.
|
|
1919
1941
|
|
|
1920
1942
|
**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 +1958,7 @@ if (!url) return null // this site has no agent — render nothing, or
|
|
|
1936
1958
|
|
|
1937
1959
|
### Declaring what your foundation supports
|
|
1938
1960
|
|
|
1939
|
-
`resolveService
|
|
1961
|
+
The predicates above, and `resolveService`, are how you ask at render time. The other direction — telling a
|
|
1940
1962
|
host, *before* anything renders, which services your foundation is built to use —
|
|
1941
1963
|
is one line in the foundation's `package.json`:
|
|
1942
1964
|
|
|
@@ -1953,23 +1975,24 @@ against it.** A host that offers search has no way to know whether your sections
|
|
|
1953
1975
|
draw a search box, so without this it either offers a site something its code
|
|
1954
1976
|
will ignore, or withholds something it would have used.
|
|
1955
1977
|
|
|
1956
|
-
**
|
|
1978
|
+
**What a host receives is one of three answers:**
|
|
1957
1979
|
|
|
1958
1980
|
| | |
|
|
1959
1981
|
|---|---|
|
|
1960
|
-
|
|
|
1961
|
-
| `
|
|
1962
|
-
|
|
|
1982
|
+
| a list — `["search"]` | the services this foundation renders against, and only these |
|
|
1983
|
+
| `[]` | none — proven by the build, not assumed |
|
|
1984
|
+
| absent | *unknown* — the build could not tell, and nothing was declared |
|
|
1963
1985
|
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1986
|
+
⭐ **The build reads the set off your code.** When the foundation is built, `supports` is derived
|
|
1987
|
+
from what the bundle actually reaches — `resolveService(website, 'search')`, or a predicate like
|
|
1988
|
+
`isSearchEnabled()` — so a foundation that never writes the key still publishes an accurate set.
|
|
1989
|
+
What you write in `package.json` is a **supplement**: the build publishes the union, so a
|
|
1990
|
+
declaration can add a service but never remove one the code reaches.
|
|
1967
1991
|
|
|
1968
|
-
**
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
cannot promise it found them all. The declaration is yours to keep accurate.
|
|
1992
|
+
**Declare only what the build cannot see.** A service reached through a *computed* name —
|
|
1993
|
+
`resolveService(website, name)` where `name` is a variable — is invisible to it, and the build
|
|
1994
|
+
warns when that happens. List those. `uniweb doctor` compares what you declared with what the build
|
|
1995
|
+
found.
|
|
1973
1996
|
|
|
1974
1997
|
⚖️ **Baseline behaviour is not yours to declare.** Some services do something for
|
|
1975
1998
|
a site whether or not a foundation cooperates — the runtime reports page views
|
|
@@ -2076,7 +2099,7 @@ tracking:
|
|
|
2076
2099
|
```
|
|
2077
2100
|
|
|
2078
2101
|
A host may also supply one under `services.tracking`, and the usual precedence
|
|
2079
|
-
applies:
|
|
2102
|
+
applies: the host's, then yours, then neither.
|
|
2080
2103
|
|
|
2081
2104
|
⚠️ **The endpoint has to accept the framework's own format** — a batched
|
|
2082
2105
|
`{ "events": [ … ] }` POST, documented in `reference/site-configuration.md`. It
|
|
@@ -2145,17 +2168,18 @@ tracking:
|
|
|
2145
2168
|
⭐ **`emit` needs no endpoint of its own.** Where a host provides one, the site
|
|
2146
2169
|
declares only what it wants sent and the address comes from the host. The two
|
|
2147
2170
|
are read key by key, so naming `emit` alone overrides nothing else the host
|
|
2148
|
-
declared.
|
|
2149
|
-
|
|
2171
|
+
declared. An `endpoint:` of your own is used wherever the host supplies no
|
|
2172
|
+
collector — on a host without one, and on none — and where the host supplies
|
|
2173
|
+
one, the host's is used.
|
|
2150
2174
|
|
|
2151
|
-
`minimal` is `page_view` alone. `standard` is the default when
|
|
2152
|
-
own `
|
|
2175
|
+
`minimal` is `page_view` alone. `standard` is the default when the collector is
|
|
2176
|
+
your own. `all` is a standing yes, so an event added in a later framework
|
|
2153
2177
|
release is included without you changing anything — which is exactly why
|
|
2154
2178
|
`standard` exists as well: it is a curated set that a release cannot grow behind
|
|
2155
2179
|
your back.
|
|
2156
2180
|
|
|
2157
2181
|
⭐ **Saying nothing means two different things, and which one depends on who
|
|
2158
|
-
supplies the address.** A site
|
|
2182
|
+
supplies the address.** A site sending to its own `endpoint:` gets `standard`. A site
|
|
2159
2183
|
on a **host-supplied** collector gets **whatever that host declares it
|
|
2160
2184
|
collects** — it has no address of its own, so the arrangement is that the host
|
|
2161
2185
|
does analytics for it, and the set grows when the host starts collecting
|
|
@@ -2253,8 +2277,8 @@ happened into a journey.
|
|
|
2253
2277
|
Everything above reaches the runtime through `@uniweb/kit` or through something
|
|
2254
2278
|
handed to your component as a prop. That is the rule, not a stylistic preference:
|
|
2255
2279
|
|
|
2256
|
-
- ✅ `useWebsite()`, `useTracker()`, `
|
|
2257
|
-
utilities.
|
|
2280
|
+
- ✅ `useWebsite()`, `useTracker()`, `isSearchEnabled()` and the other service
|
|
2281
|
+
predicates, `resolveService(website, …)` — kit hooks and utilities.
|
|
2258
2282
|
- ✅ `block.track(…)`, `block.page`, `block.website` — the block **arrives in your
|
|
2259
2283
|
props**, so calling methods on it is not reaching for a global.
|
|
2260
2284
|
- ⛔ `globalThis.uniweb`, `window.uniweb` — never, in a foundation.
|
|
@@ -2303,10 +2327,10 @@ For cases the factory doesn't cover, write handlers directly using `Loom`, `inst
|
|
|
2303
2327
|
## Part 4b — When the site is also an app
|
|
2304
2328
|
|
|
2305
2329
|
Everything above is a site: content the author writes, built into pages. Some sites
|
|
2306
|
-
also have **
|
|
2307
|
-
create and edit.
|
|
2330
|
+
also have **an `api` service** — accounts, per-visitor data, records their members
|
|
2331
|
+
create and edit. `@uniweb/api` is its client.
|
|
2308
2332
|
|
|
2309
|
-
⛔ **Only reach for this when the site actually has one.** A site
|
|
2333
|
+
⛔ **Only reach for this when the site actually has one.** A site without one is
|
|
2310
2334
|
the normal case, and a foundation that assumes one breaks on every other site it is
|
|
2311
2335
|
used with.
|
|
2312
2336
|
|
|
@@ -2323,7 +2347,7 @@ import { useSession, SignedIn, SignedOut } from '@uniweb/api'
|
|
|
2323
2347
|
if (!isApiEnabled()) return <StaticVersion /> // synchronous — nothing to await
|
|
2324
2348
|
```
|
|
2325
2349
|
|
|
2326
|
-
⛔ **When
|
|
2350
|
+
⛔ **When the site has no `api` service, draw nothing** — not a disabled control, and not an
|
|
2327
2351
|
explanation. Same rule as `services` in Part 4: which capabilities a site's operator
|
|
2328
2352
|
set up is none of a visitor's business, and "sign-in unavailable" reads as breakage
|
|
2329
2353
|
when it is simply a feature this site does not have. Render the version of your
|
|
@@ -2336,8 +2360,8 @@ const { status, records } = useRecords({ schema: '@/session' })
|
|
|
2336
2360
|
```
|
|
2337
2361
|
|
|
2338
2362
|
⭐ **`absent` and an empty `ready` are different answers, and confusing them is the
|
|
2339
|
-
mistake to avoid.** `absent` = there is no live source (no
|
|
2340
|
-
in) → render the site's authored content. `ready` with `records: []` = the
|
|
2363
|
+
mistake to avoid.** `absent` = there is no live source (no `api` service, or nobody signed
|
|
2364
|
+
in) → render the site's authored content. `ready` with `records: []` = the service
|
|
2341
2365
|
answered and there is nothing there → render your empty state. Showing "nothing yet"
|
|
2342
2366
|
for the first tells a visitor their content is gone when it was never requested.
|
|
2343
2367
|
|
package/src/framework-index.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-10T16:24:13.926Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/api": {
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.1",
|
|
7
7
|
"path": "framework/api",
|
|
8
8
|
"deps": [
|
|
9
9
|
"@uniweb/core"
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
12
|
"@uniweb/build": {
|
|
13
|
-
"version": "0.44.
|
|
13
|
+
"version": "0.44.4",
|
|
14
14
|
"path": "framework/build",
|
|
15
15
|
"deps": [
|
|
16
16
|
"@uniweb/content-reader",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"deps": []
|
|
35
35
|
},
|
|
36
36
|
"@uniweb/core": {
|
|
37
|
-
"version": "0.24.
|
|
37
|
+
"version": "0.24.4",
|
|
38
38
|
"path": "framework/core",
|
|
39
39
|
"deps": [
|
|
40
40
|
"@uniweb/semantic-parser",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
]
|
|
55
55
|
},
|
|
56
56
|
"@uniweb/kit": {
|
|
57
|
-
"version": "0.18.
|
|
57
|
+
"version": "0.18.2",
|
|
58
58
|
"path": "framework/kit",
|
|
59
59
|
"deps": [
|
|
60
60
|
"@uniweb/core",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
]
|
|
83
83
|
},
|
|
84
84
|
"@uniweb/runtime": {
|
|
85
|
-
"version": "0.19.
|
|
85
|
+
"version": "0.19.5",
|
|
86
86
|
"path": "framework/runtime",
|
|
87
87
|
"deps": [
|
|
88
88
|
"@uniweb/core",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"deps": []
|
|
111
111
|
},
|
|
112
112
|
"@uniweb/templates": {
|
|
113
|
-
"version": "0.12.
|
|
113
|
+
"version": "0.12.4",
|
|
114
114
|
"path": "framework/templates",
|
|
115
115
|
"deps": []
|
|
116
116
|
},
|