@warlock.js/web 5.2.2 → 5.2.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/CHANGELOG.md +6 -0
- package/esm/build/contribution.mjs.map +1 -1
- package/esm/build/discover-pages.mjs.map +1 -1
- package/esm/build/generate-client-registry.mjs.map +1 -1
- package/esm/build/generate-pages-barrel.mjs.map +1 -1
- package/esm/build/page-default-export.mjs.map +1 -1
- package/esm/build/page-routes-manifest.mjs.map +1 -1
- package/esm/build/public-files.mjs.map +1 -1
- package/esm/build/read-route-exports.mjs.map +1 -1
- package/esm/client/build-hydrated-tree.mjs.map +1 -1
- package/esm/client/navigation/fetch-page-data.mjs.map +1 -1
- package/esm/client/navigation/prefetch.mjs.map +1 -1
- package/esm/client/runtime/manifest.mjs.map +1 -1
- package/esm/client/runtime/matcher.mjs.map +1 -1
- package/esm/components/document-context.mjs.map +1 -1
- package/esm/components/link.mjs.map +1 -1
- package/esm/routing/filesystem-route.mjs.map +1 -1
- package/esm/routing/layout-policy.mjs.map +1 -1
- package/esm/routing/query-string.mjs.map +1 -1
- package/esm/routing/route-table.mjs.map +1 -1
- package/esm/server/create-page-route-handler.mjs.map +1 -1
- package/esm/server/execute-page-request.mjs.map +1 -1
- package/esm/server/install-page-routes-from-manifest.mjs.map +1 -1
- package/esm/server/install-page-routes.mjs.map +1 -1
- package/esm/server/match-page-route.mjs.map +1 -1
- package/esm/server/not-found-page.mjs.map +1 -1
- package/esm/server/page-file-change.mjs.map +1 -1
- package/esm/server/page-route-reload.mjs.map +1 -1
- package/esm/server/render-page.mjs.map +1 -1
- package/esm/server/settle-page-response.mjs.map +1 -1
- package/esm/server/stylesheet-urls.mjs.map +1 -1
- package/esm/server/unregistered-pages.mjs.map +1 -1
- package/esm/server/web-connector-factory.mjs.map +1 -1
- package/esm/server/web-connector.mjs.map +1 -1
- package/esm/shared.mjs.map +1 -1
- package/esm/vite/build-client.mjs.map +1 -1
- package/esm/vite/gate-a-resolve.mjs.map +1 -1
- package/esm/vite/gate-b-secrets.mjs.map +1 -1
- package/esm/vite/gate-c-verify.mjs.map +1 -1
- package/esm/vite/hydration-entries.mjs.map +1 -1
- package/esm/vite/index.mjs.map +1 -1
- package/esm/vite/page-registry-plugin.mjs.map +1 -1
- package/esm/vite/projection.mjs.map +1 -1
- package/llms-full.txt +33 -9
- package/llms.txt +1 -1
- package/package.json +3 -3
- package/skills/add-web-to-an-app/SKILL.md +7 -5
package/llms-full.txt
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
name: add-web-to-an-app
|
|
11
|
-
description: 'Install the SSR page layer with `warlock add web`: add React/Vite peers, scaffold `src/web/root.tsx` and `src/web/
|
|
11
|
+
description: 'Install the SSR page layer with `warlock add web`: add React/Vite peers, scaffold `src/web/root.tsx` and `src/web/index.page.tsx`, register `webConnector()`, and safely relocate the stock top-level `GET "/"` JSON route to `/welcome`. Triggers: `warlock add web`, `webConnector`, `src/web/root.tsx`, `src/web/index.page.tsx`, `GET "/welcome"`; "add web to an app", "install Warlock web", "scaffold SSR", "homepage route collision". Skip: author a page — `@warlock.js/web/create-a-page/SKILL.md`; customize the document — `@warlock.js/web/write-the-root/SKILL.md`; dev/build/start commands — `@warlock.js/core/run-app/SKILL.md`; competing installers `create-next-app`, `vite create`, `remix init`.'
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Warlock — add web to an app
|
|
@@ -27,11 +27,13 @@ On the ordinary path it leaves this application-owned shape:
|
|
|
27
27
|
src/
|
|
28
28
|
web/
|
|
29
29
|
root.tsx
|
|
30
|
-
|
|
30
|
+
index.page.tsx
|
|
31
31
|
warlock.config.ts
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
The generated
|
|
34
|
+
The generated index page declares `route = { path: "/", name: "index" }`, so the server payload and client registry consume one explicit identity. Universal localization setup is inside its synchronous `register()` hook. The generated root owns the document, renders `<Head />`, keeps `{children}` inside `#root`, and renders `<Scripts />`.
|
|
35
|
+
|
|
36
|
+
Every added `@warlock.js/*` package is saved at the exact version of the Core CLI executing the command. Third-party dependency ranges stay as declared by the feature.
|
|
35
37
|
|
|
36
38
|
## Connector registration
|
|
37
39
|
|
|
@@ -76,9 +78,9 @@ Indented `router.get("/", ...)` declarations inside a prefixed group are not roo
|
|
|
76
78
|
|
|
77
79
|
- No `src/app/shared/routes.ts`, or no top-level `GET "/"`: create the root page normally.
|
|
78
80
|
- Exactly one recognized top-level `GET "/"` and no top-level `GET "/welcome"`: move it to `/welcome`, then create the home page.
|
|
79
|
-
- More than one top-level `GET "/"`, an existing top-level `GET "/welcome"`, an unreadable/unwritable routes file, or an unrecognized rewrite: create `root.tsx`, do not create `
|
|
81
|
+
- More than one top-level `GET "/"`, an existing top-level `GET "/welcome"`, an unreadable/unwritable routes file, or an unrecognized rewrite: create `root.tsx`, do not create `index.page.tsx`, set a failing exit code, and still register the connector.
|
|
80
82
|
|
|
81
|
-
On the refusal path, free `/` yourself and create a page with either `route = "/"` or another literal route.
|
|
83
|
+
On the refusal path, free `/` yourself and create a page with either `route = { path: "/", name: "index" }` or another literal route.
|
|
82
84
|
|
|
83
85
|
## Re-running the command
|
|
84
86
|
|
|
@@ -319,6 +321,24 @@ The browser boundary is decided by the import graph, not by the file's location.
|
|
|
319
321
|
|
|
320
322
|
Keep server-only repository and service reads inside `loader`. Do not read them from module-scope initializers or the default component.
|
|
321
323
|
|
|
324
|
+
### `.client` does not isolate SSR in 5.2
|
|
325
|
+
|
|
326
|
+
A `.client.tsx` suffix is a naming convention, not an SSR-isolation boundary. A
|
|
327
|
+
module statically imported by a page, layout, root, or any of their imports is
|
|
328
|
+
still evaluated by the server. Top-level browser globals such as `window`
|
|
329
|
+
therefore crash SSR boot. Warlock 5.2 does not ship a client-only component
|
|
330
|
+
primitive; code that requires browser globals at module scope cannot be part of
|
|
331
|
+
the SSR page graph.
|
|
332
|
+
|
|
333
|
+
### Static assets use `public/` in 5.2
|
|
334
|
+
|
|
335
|
+
The production server build does not support imported non-stylesheet assets. An
|
|
336
|
+
import such as `import logo from "./logo.svg"` works under Vite in development
|
|
337
|
+
but `warlock build` refuses it rather than emit a server URL that disagrees with
|
|
338
|
+
the client bundle. Put the file in the application's `public/` directory and
|
|
339
|
+
reference it by root URL: `public/logo.svg` is `/logo.svg`. Stylesheet imports
|
|
340
|
+
are the exception and remain supported.
|
|
341
|
+
|
|
322
342
|
## Editing a page in development
|
|
323
343
|
|
|
324
344
|
`warlock dev` decides Fast Refresh vs. a full reload by comparing the module's *skeleton* — its source with every component body masked out — across the edit. Everything outside a component body is part of the skeleton: imports, module-level declarations, and all server exports (`route`, `middleware`, `validation`, `loader`, `metadata`). The skeleton moving, with or without a simultaneous JSX change, forces a full reload; the skeleton holding still defers to Fast Refresh.
|
|
@@ -341,6 +361,8 @@ Changed in 5.2: through 5.1 the route table was built once at boot and never aga
|
|
|
341
361
|
|
|
342
362
|
- **A page with no `route` is not unreachable.** It derives a real URL from its file location — see [Filesystem routing](#filesystem-routing). Nothing about a route-less page is refused anymore.
|
|
343
363
|
- **A page with no default export IS refused.** Named exports alone fail the build naming the file, instead of serving a blank 200.
|
|
364
|
+
- **`.client.tsx` does not prevent SSR evaluation.** It is a naming convention in 5.2, not a client-only component primitive.
|
|
365
|
+
- **Imported static assets do not build in 5.2.** Put them in `public/` and reference their root URL; CSS imports remain supported.
|
|
344
366
|
- **`[...slug]` is not a catch-all.** It is read as a literal path segment and silently produces an unreachable route — see [Catch-all segments are NOT supported](#catch-all-segments-are-not-supported).
|
|
345
367
|
- **`process.env` is refused in the client/universal graph, `PUBLIC_` prefix included.** Read env values in a loader and return them as page data; see [`load-page-data/SKILL.md`](../load-page-data/SKILL.md).
|
|
346
368
|
- **Keep `route` literal.** A computed route cannot be discovered without executing app code and is refused.
|
|
@@ -508,7 +530,7 @@ When `validating` is absent or empty, pages validate query + params, with params
|
|
|
508
530
|
|
|
509
531
|
## Execution order
|
|
510
532
|
|
|
511
|
-
Loaders run **sequentially, root to leaf, each one awaited before the next starts**: `root.tsx`'s `AppLoader`, then
|
|
533
|
+
Loaders run **sequentially, root to leaf, each one awaited before the next starts**: `root.tsx`'s `AppLoader`, then every matched `LayoutLoader` from outermost to innermost, then the page's `PageLoader`. The runtime has three top-level slots (`app`, `layout`, `page`), but the layout slot composes the full matched layout chain. A page may have only one _rendering_ layout; prefix-, middleware-, and loader-only layouts may still appear at multiple ancestry levels.
|
|
512
534
|
|
|
513
535
|
**The first core `Response` a loader returns is terminal.** Returning a `Response` object stops the pipeline immediately: no lower loader starts, `metadata` is not resolved, and that response is sent as-is. It is more terminal than a short-circuit — because the response is returned whole, the buffered header/cookie writes made at that same level are discarded along with everything below it. Use `response.redirect()` / `response.notFound()` (which produce a `LoaderShortCircuit`, committing that level's buffer inclusively) when you want your buffered writes to survive; return a raw `Response` only when you mean "this exact response, nothing else."
|
|
514
536
|
|
|
@@ -902,7 +924,9 @@ export default function ProductsPage() {
|
|
|
902
924
|
}
|
|
903
925
|
```
|
|
904
926
|
|
|
905
|
-
Recognized
|
|
927
|
+
Recognized stylesheet imports survive the page's client projection. The client boundary is determined by the import graph, not by the file living under `web/`.
|
|
928
|
+
|
|
929
|
+
That support is specific to stylesheets in the production page graph. An imported non-stylesheet asset such as `import logo from "./logo.svg"` works under Vite in development but is refused by `warlock build` in 5.2. Put it in the application's `public/` directory and reference its root URL instead: `public/logo.svg` is `/logo.svg`.
|
|
906
930
|
|
|
907
931
|
For each matched handler, Warlock builds one ordered CSS chain: `[root, ...matched layouts, page]`. A stylesheet imported directly by any member of that chain becomes a render-blocking link in the initial document in both development and production. Unrelated pages and layouts do not contribute CSS to this response.
|
|
908
932
|
|
|
@@ -1069,7 +1093,7 @@ Client navigation rebuilds the Layout + Page element tree at the same `#root` po
|
|
|
1069
1093
|
|
|
1070
1094
|
## Loader data
|
|
1071
1095
|
|
|
1072
|
-
`LayoutLoader` receives the full `PageContext` and its return reaches `LayoutProps<typeof loader>["data"]`.
|
|
1096
|
+
`LayoutLoader` receives the full `PageContext` and its return reaches `LayoutProps<typeof loader>["data"]`. Loaders run sequentially as App, every matched layout from outermost to innermost, then Page. Each loader's return belongs only to its own component, so a layout loader still cannot read another loader's result.
|
|
1073
1097
|
|
|
1074
1098
|
Use `shared` when multiple levels need one request-derived value, and write it in middleware before loaders run. See [load-page-data](../load-page-data/SKILL.md).
|
|
1075
1099
|
|
|
@@ -1212,7 +1236,7 @@ export default function App({ data, children }: AppProps<typeof loader>) {
|
|
|
1212
1236
|
}
|
|
1213
1237
|
```
|
|
1214
1238
|
|
|
1215
|
-
The App loader runs
|
|
1239
|
+
The App loader runs first and is awaited before the outermost layout loader starts; matched layout loaders then run outermost to innermost before the page loader. Its return is for the App component; use `shared` for request data that multiple levels need.
|
|
1216
1240
|
|
|
1217
1241
|
## Gotchas
|
|
1218
1242
|
|
package/llms.txt
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
## Skills
|
|
18
18
|
|
|
19
|
-
- [add-web-to-an-app](@warlock.js/web/add-web-to-an-app/SKILL.md): Install the SSR page layer with `warlock add web`: add React/Vite peers, scaffold `src/web/root.tsx` and `src/web/
|
|
19
|
+
- [add-web-to-an-app](@warlock.js/web/add-web-to-an-app/SKILL.md): Install the SSR page layer with `warlock add web`: add React/Vite peers, scaffold `src/web/root.tsx` and `src/web/index.page.tsx`, register `webConnector()`, and safely relocate the stock top-level `GET "/"` JSON route to `/welcome`. Triggers: `warlock add web`, `webConnector`, `src/web/root.tsx`, `src/web/index.page.tsx`, `GET "/welcome"`; "add web to an app", "install Warlock web", "scaffold SSR", "homepage route collision". Skip: author a page — `@warlock.js/web/create-a-page/SKILL.md`; customize the document — `@warlock.js/web/write-the-root/SKILL.md`; dev/build/start commands — `@warlock.js/core/run-app/SKILL.md`; competing installers `create-next-app`, `vite create`, `remix init`.
|
|
20
20
|
- [create-a-page](@warlock.js/web/create-a-page/SKILL.md): Create an SSR React page under `src/web/**`, with either a literal `route` or a filesystem-derived one, a default component, an optional typed `loader`, page `metadata`, the `error.page.tsx` boundary, and the universal `register()` hook. Triggers: `*.page.tsx`, `route`, `PageLoader`, `PageProps`, `PageMetadata`, `error.page.tsx`, `register`, `[...slug]`; "create a page", "add an SSR route", "make a React page", "type page loader data", "add an error boundary", "catch-all route", "page renders blank 200", "page has no default export"; typical import `import type { PageLoader, PageProps } from "@warlock.js/web"`. Skip: root document shell — `@warlock.js/web/write-the-root/SKILL.md`; layout wrappers and prefixes — `@warlock.js/web/use-layouts/SKILL.md`; loader lifecycle and `shared` — `@warlock.js/web/load-page-data/SKILL.md`; competing frameworks `next`, `remix`, `react-router` file routes.
|
|
21
21
|
- [load-page-data](@warlock.js/web/load-page-data/SKILL.md): Load App, Layout, and Page data with `AppLoader`, `LayoutLoader`, and `PageLoader`; type component `data`, validate page input, short-circuit with the buffered response, and publish request-scoped browser-safe values through `shared`. Triggers: `PageLoader`, `LayoutLoader`, `AppLoader`, `PageProps`, `shared`, `useShared`, `validation`, `request.validated`, `process.env`, `env("PUBLIC_...")`, `import.meta.env.PUBLIC_`; "load page data", "pass server data to React", "share request data", "redirect from a loader", "read an environment variable in a page", "process.env refused in the client build", "loader execution order", "return a Response from a loader". Skip: page module basics — `@warlock.js/web/create-a-page/SKILL.md`; layouts — `@warlock.js/web/use-layouts/SKILL.md`; mutation follow-up — `@warlock.js/web/navigate-on-the-client/SKILL.md`; competing loaders Next data functions, Remix loaders, React Server Components.
|
|
22
22
|
- [navigate-on-the-client](@warlock.js/web/navigate-on-the-client/SKILL.md): Navigate hydrated pages with `<Link>`, resolve named URLs with `href()`, use `navigateTo` / `navigateBack`, prefetch on interaction, inspect the server match with `currentRoute()`, and re-fetch loaders after a mutation with `refresh()`. Triggers: `Link`, `href`, `navigateTo`, `navigateBack`, `refresh`, `currentRoute`, `previousRoute`; "navigate without a reload", "link to a named route", "refresh page data", "revalidate loaders", "client-side back"; typical import `import { Link, refresh } from "@warlock.js/web"`. Skip: define a page route — `@warlock.js/web/create-a-page/SKILL.md`; loader mechanics — `@warlock.js/web/load-page-data/SKILL.md`; root hydration boundary — `@warlock.js/web/write-the-root/SKILL.md`; competing routers `@mongez/react-router`, `react-router-dom`, Next navigation.
|
package/package.json
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"@vitejs/plugin-react": "^5.2.0",
|
|
14
|
-
"@warlock.js/core": "5.2.
|
|
15
|
-
"@warlock.js/seal": "5.2.
|
|
14
|
+
"@warlock.js/core": "5.2.4",
|
|
15
|
+
"@warlock.js/seal": "5.2.4",
|
|
16
16
|
"react": "*",
|
|
17
17
|
"react-dom": "*",
|
|
18
18
|
"vite": ">=7.3.5 <8"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
],
|
|
38
38
|
"author": "hassanzohdy",
|
|
39
39
|
"license": "MIT",
|
|
40
|
-
"version": "5.2.
|
|
40
|
+
"version": "5.2.4",
|
|
41
41
|
"type": "module",
|
|
42
42
|
"main": "./esm/index.mjs",
|
|
43
43
|
"module": "./esm/index.mjs",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: add-web-to-an-app
|
|
3
|
-
description: 'Install the SSR page layer with `warlock add web`: add React/Vite peers, scaffold `src/web/root.tsx` and `src/web/
|
|
3
|
+
description: 'Install the SSR page layer with `warlock add web`: add React/Vite peers, scaffold `src/web/root.tsx` and `src/web/index.page.tsx`, register `webConnector()`, and safely relocate the stock top-level `GET "/"` JSON route to `/welcome`. Triggers: `warlock add web`, `webConnector`, `src/web/root.tsx`, `src/web/index.page.tsx`, `GET "/welcome"`; "add web to an app", "install Warlock web", "scaffold SSR", "homepage route collision". Skip: author a page — `@warlock.js/web/create-a-page/SKILL.md`; customize the document — `@warlock.js/web/write-the-root/SKILL.md`; dev/build/start commands — `@warlock.js/core/run-app/SKILL.md`; competing installers `create-next-app`, `vite create`, `remix init`.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Warlock — add web to an app
|
|
@@ -19,11 +19,13 @@ On the ordinary path it leaves this application-owned shape:
|
|
|
19
19
|
src/
|
|
20
20
|
web/
|
|
21
21
|
root.tsx
|
|
22
|
-
|
|
22
|
+
index.page.tsx
|
|
23
23
|
warlock.config.ts
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
The generated
|
|
26
|
+
The generated index page declares `route = { path: "/", name: "index" }`, so the server payload and client registry consume one explicit identity. Universal localization setup is inside its synchronous `register()` hook. The generated root owns the document, renders `<Head />`, keeps `{children}` inside `#root`, and renders `<Scripts />`.
|
|
27
|
+
|
|
28
|
+
Every added `@warlock.js/*` package is saved at the exact version of the Core CLI executing the command. Third-party dependency ranges stay as declared by the feature.
|
|
27
29
|
|
|
28
30
|
## Connector registration
|
|
29
31
|
|
|
@@ -68,9 +70,9 @@ Indented `router.get("/", ...)` declarations inside a prefixed group are not roo
|
|
|
68
70
|
|
|
69
71
|
- No `src/app/shared/routes.ts`, or no top-level `GET "/"`: create the root page normally.
|
|
70
72
|
- Exactly one recognized top-level `GET "/"` and no top-level `GET "/welcome"`: move it to `/welcome`, then create the home page.
|
|
71
|
-
- More than one top-level `GET "/"`, an existing top-level `GET "/welcome"`, an unreadable/unwritable routes file, or an unrecognized rewrite: create `root.tsx`, do not create `
|
|
73
|
+
- More than one top-level `GET "/"`, an existing top-level `GET "/welcome"`, an unreadable/unwritable routes file, or an unrecognized rewrite: create `root.tsx`, do not create `index.page.tsx`, set a failing exit code, and still register the connector.
|
|
72
74
|
|
|
73
|
-
On the refusal path, free `/` yourself and create a page with either `route = "/"` or another literal route.
|
|
75
|
+
On the refusal path, free `/` yourself and create a page with either `route = { path: "/", name: "index" }` or another literal route.
|
|
74
76
|
|
|
75
77
|
## Re-running the command
|
|
76
78
|
|