@farm.js/core 0.1.34 → 0.1.35

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.
Files changed (261) hide show
  1. package/dist/agent-runtime.cjs +3 -3
  2. package/dist/agent-runtime.d.mts +4 -5
  3. package/dist/agent-runtime.d.ts +4 -5
  4. package/dist/agent-runtime.mjs +2 -2
  5. package/dist/api/route-manager.cjs +5 -5
  6. package/dist/api/route-manager.d.mts +6 -7
  7. package/dist/api/route-manager.d.ts +6 -7
  8. package/dist/api/route-manager.mjs +4 -4
  9. package/dist/api/runtime.cjs +6 -4
  10. package/dist/api/runtime.d.mts +4 -5
  11. package/dist/api/runtime.d.ts +4 -5
  12. package/dist/api/runtime.mjs +6 -4
  13. package/dist/api.cjs +6 -6
  14. package/dist/api.d.mts +7 -8
  15. package/dist/api.d.ts +7 -8
  16. package/dist/api.mjs +5 -5
  17. package/dist/{app-DgotYGbq.d.ts → app-BXB3JZYc.d.ts} +38 -12
  18. package/dist/{app-q4rmZlXK.d.mts → app-D_j9AAVL.d.mts} +38 -12
  19. package/dist/app-markdown.cjs +5 -5
  20. package/dist/app-markdown.d.mts +5 -6
  21. package/dist/app-markdown.d.ts +5 -6
  22. package/dist/app-markdown.mjs +4 -4
  23. package/dist/{chunk-LMJ7VRHZ.mjs → chunk-22LTEMGQ.mjs} +1 -1
  24. package/dist/{chunk-AQZFOP7S.mjs → chunk-2G2NNLE2.mjs} +1 -1
  25. package/dist/{chunk-QJ3J6MZT.cjs → chunk-3BHT4WMP.cjs} +2 -2
  26. package/dist/{chunk-X242HVD5.mjs → chunk-3PXS2MHU.mjs} +1 -1
  27. package/dist/{chunk-A5FGU2WU.cjs → chunk-3UH7MRCP.cjs} +19 -23
  28. package/dist/{chunk-AGC75XAE.mjs → chunk-4JHOT46A.mjs} +1 -1
  29. package/dist/{chunk-XV5DJTBX.mjs → chunk-4KU5Q7C2.mjs} +424 -230
  30. package/dist/{chunk-TA5G2HWD.cjs → chunk-4MMGO7YW.cjs} +21 -21
  31. package/dist/{chunk-7BT4H4P7.cjs → chunk-62XKI4Z3.cjs} +2 -2
  32. package/dist/{chunk-ZKP7C2B6.mjs → chunk-6DU6UFUE.mjs} +12 -11
  33. package/dist/{chunk-GOABMOX3.mjs → chunk-6ETPZTJI.mjs} +366 -4
  34. package/dist/{chunk-7Y6ZNFPX.mjs → chunk-6TJOML4E.mjs} +13 -3
  35. package/dist/{chunk-3ATMYLLJ.mjs → chunk-6WCPV6G2.mjs} +1 -1
  36. package/dist/{chunk-BTAG7LI7.cjs → chunk-73MC7ZL6.cjs} +2 -2
  37. package/dist/chunk-75RZHGLS.cjs +135 -0
  38. package/dist/{chunk-VKNHTSAP.cjs → chunk-7GLPRTTF.cjs} +2 -2
  39. package/dist/{chunk-7M52YUMY.cjs → chunk-7L5V3KQO.cjs} +2 -2
  40. package/dist/{chunk-LI2LMOLR.mjs → chunk-C35ZBVRD.mjs} +12 -3
  41. package/dist/{chunk-YQVSHTMR.mjs → chunk-CP6X4AEU.mjs} +1 -1
  42. package/dist/{chunk-QZCT2CQ4.mjs → chunk-CXEN47J3.mjs} +64 -2
  43. package/dist/{chunk-ATK2R4CH.cjs → chunk-D227TIEN.cjs} +14 -4
  44. package/dist/{chunk-ROUTX2E5.cjs → chunk-DBNKI4NF.cjs} +12 -3
  45. package/dist/{chunk-UX5S4JEO.cjs → chunk-EFCQPQMG.cjs} +3 -3
  46. package/dist/{chunk-K3F2E6GS.cjs → chunk-EJQT6KZN.cjs} +2 -2
  47. package/dist/{chunk-3LUF2PE2.cjs → chunk-EK4QAEFZ.cjs} +67 -5
  48. package/dist/{chunk-VVBO3QH7.mjs → chunk-ENLZ4R3Y.mjs} +10 -1
  49. package/dist/{chunk-XXJU7FCC.cjs → chunk-EUV4YR3V.cjs} +2 -2
  50. package/dist/{chunk-WNNYOOIB.mjs → chunk-F6Z3Y5KL.mjs} +1 -1
  51. package/dist/{chunk-PQDFUSXD.cjs → chunk-F7JZENPF.cjs} +33 -32
  52. package/dist/{chunk-TDFPACVX.cjs → chunk-FTFYRMQQ.cjs} +18 -18
  53. package/dist/{chunk-657WJNRY.mjs → chunk-G5RT7EXW.mjs} +1 -1
  54. package/dist/{chunk-MOKLYNHV.cjs → chunk-GFHLGIYC.cjs} +6 -6
  55. package/dist/{chunk-AWC4VUZL.cjs → chunk-GQ3Z3IZI.cjs} +14 -14
  56. package/dist/{chunk-75WGQVQA.cjs → chunk-HITLGIAO.cjs} +10 -1
  57. package/dist/{chunk-GNSDTTWZ.mjs → chunk-HMIJDL7S.mjs} +1 -1
  58. package/dist/{chunk-PXKIEXZD.mjs → chunk-HUMR6LSU.mjs} +1 -1
  59. package/dist/{chunk-SJVKK4JE.cjs → chunk-ICUQICNC.cjs} +912 -718
  60. package/dist/{chunk-P64MIF5B.cjs → chunk-IPXLADVO.cjs} +387 -25
  61. package/dist/{chunk-KROWKCUH.cjs → chunk-JGLC4TO3.cjs} +8 -1
  62. package/dist/{chunk-2NQQ5H5G.cjs → chunk-M7MKQXAF.cjs} +2 -1
  63. package/dist/chunk-NRDBW4MP.mjs +45 -0
  64. package/dist/chunk-OFZUJMCU.mjs +601 -0
  65. package/dist/{chunk-VCCUOMQN.mjs → chunk-OKZUAXHF.mjs} +1 -1
  66. package/dist/{chunk-EM6SBQKM.cjs → chunk-OMVAU7NT.cjs} +27 -2
  67. package/dist/{chunk-O27L4YAA.mjs → chunk-PDOCJ6RY.mjs} +2 -2
  68. package/dist/{chunk-36MK5YCW.cjs → chunk-PFQKNERH.cjs} +346 -206
  69. package/dist/{chunk-HR5KPHC2.mjs → chunk-Q3VLETLE.mjs} +1 -1
  70. package/dist/{chunk-LR5QSC2P.mjs → chunk-QAU5JD57.mjs} +211 -71
  71. package/dist/{chunk-LHODW25H.mjs → chunk-QORUJDIV.mjs} +2 -2
  72. package/dist/{chunk-UBO4SGH4.mjs → chunk-RHAZ22ZN.mjs} +2 -1
  73. package/dist/{chunk-ZHPHJPQP.cjs → chunk-RU3M2FIK.cjs} +18 -14
  74. package/dist/{chunk-JDPAKVS4.mjs → chunk-SAZVVAJH.mjs} +3 -3
  75. package/dist/{chunk-6VVL3MHY.mjs → chunk-SC2WYWPF.mjs} +1 -1
  76. package/dist/{chunk-QCFFHV5H.mjs → chunk-SMHH4VDG.mjs} +1 -1
  77. package/dist/{chunk-U4PTAHW3.mjs → chunk-SOMHP6GF.mjs} +7 -11
  78. package/dist/{chunk-VHANUNEG.mjs → chunk-UAORZ7QA.mjs} +2 -2
  79. package/dist/{chunk-NGVORZVZ.mjs → chunk-UJD4PHYB.mjs} +15 -11
  80. package/dist/{chunk-U74I55WB.cjs → chunk-ULAWS2PA.cjs} +13 -3
  81. package/dist/{chunk-MPEYMSCF.cjs → chunk-VFQT3LAO.cjs} +5 -5
  82. package/dist/{chunk-Z2YLTERK.cjs → chunk-VZJR7UTG.cjs} +6 -6
  83. package/dist/chunk-WWFTAUFG.cjs +45 -0
  84. package/dist/{chunk-ZUSJDQ2Q.mjs → chunk-WWIKMBRN.mjs} +1 -1
  85. package/dist/{chunk-QGYRXFU2.cjs → chunk-X6W5FFH6.cjs} +8 -8
  86. package/dist/{chunk-MIDIZJZC.cjs → chunk-XBML5KMG.cjs} +8 -8
  87. package/dist/{chunk-G26MUMKL.cjs → chunk-XCACDAZZ.cjs} +4 -4
  88. package/dist/{chunk-CLJYVZAD.mjs → chunk-XCMCS4DA.mjs} +11 -1
  89. package/dist/{chunk-XF7Q24PF.mjs → chunk-Y7RKTKYI.mjs} +25 -0
  90. package/dist/{chunk-ODBZYBAB.cjs → chunk-YC6V7PWE.cjs} +1 -1
  91. package/dist/{chunk-F6OHXPWR.mjs → chunk-YFILVET3.mjs} +8 -1
  92. package/dist/{chunk-DZ4DTRJ5.cjs → chunk-YKX5BK66.cjs} +7 -7
  93. package/dist/chunk-YSLWRWWP.cjs +601 -0
  94. package/dist/{chunk-3VSKDFAT.mjs → chunk-YULD7ICZ.mjs} +1 -1
  95. package/dist/chunk-ZLAT2CWY.mjs +135 -0
  96. package/dist/{chunk-T5CERMEH.cjs → chunk-ZXGAFZDO.cjs} +2 -2
  97. package/dist/{client-plugins-CLObcuCq.d.mts → client-plugins-CvIslxWi.d.mts} +207 -7
  98. package/dist/{client-plugins-DZjHC4Mi.d.ts → client-plugins-HIyulDym.d.ts} +207 -7
  99. package/dist/client-plugins.d.mts +4 -5
  100. package/dist/client-plugins.d.ts +4 -5
  101. package/dist/client.cjs +5 -5
  102. package/dist/client.d.mts +8 -9
  103. package/dist/client.d.ts +8 -9
  104. package/dist/client.mjs +4 -4
  105. package/dist/config.d.mts +4 -5
  106. package/dist/config.d.ts +4 -5
  107. package/dist/{devtools-HU6Y2MNV.cjs → devtools-EAUY43BS.cjs} +9 -9
  108. package/dist/{devtools-RNXCTS4R.mjs → devtools-EE5RIBTH.mjs} +8 -8
  109. package/dist/docs.cjs +12 -12
  110. package/dist/docs.d.mts +41 -4
  111. package/dist/docs.d.ts +41 -4
  112. package/dist/docs.mjs +11 -11
  113. package/dist/i18n/client.d.mts +2 -2
  114. package/dist/i18n/client.d.ts +2 -2
  115. package/dist/i18n/index.d.mts +3 -3
  116. package/dist/i18n/index.d.ts +3 -3
  117. package/dist/i18n/server.d.mts +5 -5
  118. package/dist/i18n/server.d.ts +5 -5
  119. package/dist/image/server.cjs +3 -3
  120. package/dist/image/server.mjs +2 -2
  121. package/dist/image/sharp.cjs +10 -10
  122. package/dist/image/sharp.mjs +2 -2
  123. package/dist/{index-a-8Z5kZU.d.mts → index-BJJfLxJo.d.mts} +2 -2
  124. package/dist/{index-BWVfxIsO.d.ts → index-CwoOP-MW.d.ts} +2 -2
  125. package/dist/index.cjs +38 -35
  126. package/dist/index.d.mts +19 -20
  127. package/dist/index.d.ts +19 -20
  128. package/dist/index.mjs +37 -34
  129. package/dist/integrations.cjs +3 -3
  130. package/dist/integrations.d.mts +4 -5
  131. package/dist/integrations.d.ts +4 -5
  132. package/dist/integrations.mjs +2 -2
  133. package/dist/internal/app-markdown-runtime.cjs +4 -4
  134. package/dist/internal/app-markdown-runtime.d.mts +5 -6
  135. package/dist/internal/app-markdown-runtime.d.ts +5 -6
  136. package/dist/internal/app-markdown-runtime.mjs +3 -3
  137. package/dist/internal/build-runtime.cjs +26 -26
  138. package/dist/internal/build-runtime.d.mts +6 -7
  139. package/dist/internal/build-runtime.d.ts +6 -7
  140. package/dist/internal/build-runtime.mjs +25 -25
  141. package/dist/internal/cli-runtime.cjs +13 -13
  142. package/dist/internal/cli-runtime.mjs +12 -12
  143. package/dist/internal/client-error-overlay.cjs +6 -6
  144. package/dist/internal/client-error-overlay.mjs +2 -2
  145. package/dist/internal/client-runtime.cjs +2 -2
  146. package/dist/internal/client-runtime.mjs +1 -1
  147. package/dist/internal/compression-runtime.d.mts +4 -5
  148. package/dist/internal/compression-runtime.d.ts +4 -5
  149. package/dist/internal/config-runtime.cjs +9 -9
  150. package/dist/internal/config-runtime.d.mts +5 -6
  151. package/dist/internal/config-runtime.d.ts +5 -6
  152. package/dist/internal/config-runtime.mjs +8 -8
  153. package/dist/internal/isolated-boundary.cjs +3 -2
  154. package/dist/internal/isolated-boundary.d.mts +1 -0
  155. package/dist/internal/isolated-boundary.d.ts +1 -0
  156. package/dist/internal/isolated-boundary.mjs +2 -1
  157. package/dist/internal/metadata-image-runtime.cjs +3 -3
  158. package/dist/internal/metadata-image-runtime.mjs +2 -2
  159. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  160. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  161. package/dist/internal/production-runtime.cjs +47 -23
  162. package/dist/internal/production-runtime.d.mts +58 -18
  163. package/dist/internal/production-runtime.d.ts +58 -18
  164. package/dist/internal/production-runtime.mjs +43 -19
  165. package/dist/internal/server-tree.cjs +12 -0
  166. package/dist/internal/server-tree.d.mts +27 -0
  167. package/dist/internal/server-tree.d.ts +27 -0
  168. package/dist/internal/server-tree.mjs +12 -0
  169. package/dist/markdown.cjs +3 -3
  170. package/dist/markdown.d.mts +4 -5
  171. package/dist/markdown.d.ts +4 -5
  172. package/dist/markdown.mjs +2 -2
  173. package/dist/{metadata-Cjs8JMRM.d.ts → metadata-BnLDsUOS.d.ts} +16 -2
  174. package/dist/{metadata-2HSU2i_w.d.mts → metadata-WGpBYcGn.d.mts} +16 -2
  175. package/dist/middleware.cjs +4 -4
  176. package/dist/middleware.d.mts +6 -7
  177. package/dist/middleware.d.ts +6 -7
  178. package/dist/middleware.mjs +3 -3
  179. package/dist/navigation.cjs +5 -5
  180. package/dist/navigation.d.mts +7 -8
  181. package/dist/navigation.d.ts +7 -8
  182. package/dist/navigation.mjs +4 -4
  183. package/dist/{nitro-4XGPNIK4.mjs → nitro-MXRDCXWZ.mjs} +2 -2
  184. package/dist/{nitro-HSAQFXSS.cjs → nitro-OVPLKPE2.cjs} +3 -3
  185. package/dist/{observability-BupkiN0m.d.mts → observability-CoXunYhS.d.mts} +4 -3
  186. package/dist/{observability-BupkiN0m.d.ts → observability-CoXunYhS.d.ts} +4 -3
  187. package/dist/observability.d.mts +1 -1
  188. package/dist/observability.d.ts +1 -1
  189. package/dist/plugin.cjs +22 -22
  190. package/dist/plugin.d.mts +4 -5
  191. package/dist/plugin.d.ts +4 -5
  192. package/dist/plugin.mjs +21 -21
  193. package/dist/{production-runtime-CysZl3EV.d.mts → production-runtime-0sRnuYc-.d.mts} +4 -4
  194. package/dist/{production-runtime-BU5ETAK9.d.ts → production-runtime-Crq6CJ-2.d.ts} +4 -4
  195. package/dist/query/client.cjs +6 -6
  196. package/dist/query/client.mjs +2 -2
  197. package/dist/{render-plan-D72O1qm4.d.ts → render-plan-8ozZh2Qv.d.ts} +1 -1
  198. package/dist/{render-plan-CKr4ltOd.d.mts → render-plan-gs9GGPzw.d.mts} +1 -1
  199. package/dist/renderer/react/server.cjs +10 -4
  200. package/dist/renderer/react/server.d.mts +2 -1
  201. package/dist/renderer/react/server.d.ts +2 -1
  202. package/dist/renderer/react/server.mjs +7 -1
  203. package/dist/renderer-client.cjs +5 -5
  204. package/dist/renderer-client.d.mts +6 -7
  205. package/dist/renderer-client.d.ts +6 -7
  206. package/dist/renderer-client.mjs +2 -2
  207. package/dist/renderer.d.mts +2 -0
  208. package/dist/renderer.d.ts +2 -0
  209. package/dist/{request-DbyOYI2j.d.ts → request-B5G8rLBH.d.ts} +1 -1
  210. package/dist/{request-Be83WafN.d.mts → request-fkhiynXe.d.mts} +1 -1
  211. package/dist/request.d.mts +5 -6
  212. package/dist/request.d.ts +5 -6
  213. package/dist/{resolver-PPEeiJ6M.d.ts → resolver-DadfRL6F.d.ts} +1 -1
  214. package/dist/{resolver-DhW0CqZN.d.mts → resolver-khasx3fU.d.mts} +1 -1
  215. package/dist/{route-rendering-BG56SzvJ.d.mts → route-rendering-CLnS7AZj.d.mts} +1 -1
  216. package/dist/{route-rendering-CtVMpV-k.d.ts → route-rendering-lS5nUMua.d.ts} +1 -1
  217. package/dist/{router-D94-SDlW.d.ts → router-4iuiYnOW.d.ts} +1 -1
  218. package/dist/{router-ALUvm8gC.d.mts → router-ifU8Dui1.d.mts} +1 -1
  219. package/dist/routes.d.mts +4 -5
  220. package/dist/routes.d.ts +4 -5
  221. package/dist/{runtime-BirxPwbZ.d.ts → runtime-BgDQzBiu.d.ts} +2 -2
  222. package/dist/{runtime-AOJge4vQ.d.mts → runtime-CV2UCV-5.d.mts} +2 -2
  223. package/dist/server-action-security.cjs +3 -3
  224. package/dist/server-action-security.mjs +2 -2
  225. package/dist/server-fn.cjs +4 -4
  226. package/dist/server-fn.mjs +3 -3
  227. package/dist/server-plugins.d.mts +5 -6
  228. package/dist/server-plugins.d.ts +5 -6
  229. package/dist/server-query.cjs +5 -5
  230. package/dist/server-query.mjs +4 -4
  231. package/dist/server.cjs +41 -41
  232. package/dist/server.d.mts +13 -14
  233. package/dist/server.d.ts +13 -14
  234. package/dist/server.mjs +24 -24
  235. package/dist/{spa-router-DbxNRKOB.d.mts → spa-router-Bq7VCOwx.d.mts} +3 -3
  236. package/dist/{spa-router-CxK3USIz.d.ts → spa-router-DaJk5Re4.d.ts} +3 -3
  237. package/dist/testing.cjs +7 -7
  238. package/dist/testing.d.mts +4 -5
  239. package/dist/testing.d.ts +4 -5
  240. package/dist/testing.mjs +5 -5
  241. package/dist/{types-Z0aotQ8w.d.mts → types-CnH8DOqo.d.mts} +1 -1
  242. package/dist/{types-Z0aotQ8w.d.ts → types-CnH8DOqo.d.ts} +1 -1
  243. package/dist/{utils-311Y8eoK.d.ts → utils-BXLmFsVR.d.ts} +1 -1
  244. package/dist/{utils-4wVRcpOw.d.mts → utils-XJn0c9bj.d.mts} +1 -1
  245. package/dist/version.cjs +2 -2
  246. package/dist/version.mjs +1 -1
  247. package/dist/vite.cjs +22 -22
  248. package/dist/vite.d.mts +4 -5
  249. package/dist/vite.d.ts +4 -5
  250. package/dist/vite.mjs +21 -21
  251. package/dist/{workflows-CR9ex-gz.d.ts → workflows-jZ4BcdoZ.d.mts} +1 -1
  252. package/dist/{workflows-CR9ex-gz.d.mts → workflows-jZ4BcdoZ.d.ts} +1 -1
  253. package/dist/workflows.cjs +3 -3
  254. package/dist/workflows.d.mts +1 -1
  255. package/dist/workflows.d.ts +1 -1
  256. package/dist/workflows.mjs +2 -2
  257. package/package.json +9 -1
  258. package/dist/chunk-M64YUMA4.cjs +0 -58
  259. package/dist/chunk-QLQ32WC4.mjs +0 -58
  260. package/dist/types-DFbjpjXX.d.mts +0 -105
  261. package/dist/types-DFbjpjXX.d.ts +0 -105
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  compileFarmDocsAdapterEdgeManifest,
12
12
  createFarmDocsAPIHandler
13
- } from "./chunk-U4PTAHW3.mjs";
13
+ } from "./chunk-SOMHP6GF.mjs";
14
14
  import {
15
15
  FARM_DOCS_LAST_MODIFIED_MANIFEST,
16
16
  createFarmDocsHandler,
@@ -20,7 +20,7 @@ import {
20
20
  loadFarmDocsPage,
21
21
  resolveFarmDocsContentDir,
22
22
  toFarmDocsMarkdownPage
23
- } from "./chunk-O27L4YAA.mjs";
23
+ } from "./chunk-PDOCJ6RY.mjs";
24
24
  import {
25
25
  generateFarmDocsSearchClientRuntime,
26
26
  isFarmDocsSearchEnabled,
@@ -37,7 +37,7 @@ import {
37
37
  getDeployTargetForPreset,
38
38
  hasCustomFarmRouteContext,
39
39
  resolveDeployOutputPath
40
- } from "./chunk-ZKP7C2B6.mjs";
40
+ } from "./chunk-6DU6UFUE.mjs";
41
41
  import {
42
42
  resolveFarmInstrumentationFile
43
43
  } from "./chunk-ZZSRYEYU.mjs";
@@ -47,7 +47,6 @@ import {
47
47
  import {
48
48
  DEFAULT_NOT_FOUND_STYLES,
49
49
  FARM_LAYOUT_ELEMENT_CLIENT_SOURCE,
50
- HOISTED_HEAD_ELEMENT,
51
50
  PluginManager,
52
51
  SHARP_INSTALL_HINT,
53
52
  collectFarmWebMCPTools,
@@ -57,6 +56,7 @@ import {
57
56
  createMarkdownPageHydrationPlanner,
58
57
  describeSuppressedAsyncHydration,
59
58
  enforceFarmIsolatedHydrationRouteBudget,
59
+ farmDocsClientConfigPlugin,
60
60
  farmFontImportsPlugin,
61
61
  farmPluginMayAffectRuntimePath,
62
62
  generateClientCachePersistenceCode,
@@ -74,20 +74,26 @@ import {
74
74
  resolveFarmClientCacheAdapterEntry,
75
75
  resolveFarmImageProviderForRuntime,
76
76
  resolveFarmIsolatedClientHydrationMode,
77
- resolveFarmNotFoundComponentPath
78
- } from "./chunk-XV5DJTBX.mjs";
77
+ resolveFarmNotFoundComponentPath,
78
+ usesFarmServerTree
79
+ } from "./chunk-4KU5Q7C2.mjs";
79
80
  import {
80
81
  findRequestBoundSourceBlockers,
81
82
  generateFarmTypeArtifacts,
82
83
  parseRouteRenderingDirective,
83
84
  resolveRouteRenderingConfigFromFile
84
- } from "./chunk-AQZFOP7S.mjs";
85
+ } from "./chunk-2G2NNLE2.mjs";
85
86
  import {
86
87
  FARM_API_CATALOG_PATH,
87
88
  FARM_APP_MANIFEST_PATH,
89
+ HOISTED_HEAD_ELEMENT,
90
+ getRouteDirectoryDepth,
91
+ getRouteGroupScope,
88
92
  resolveFarmApiCatalogInput,
89
- resolveFarmAppManifestInput
90
- } from "./chunk-GOABMOX3.mjs";
93
+ resolveFarmAppManifestInput,
94
+ routeBoundaryCoversDirectory,
95
+ stripRouteGroups
96
+ } from "./chunk-6ETPZTJI.mjs";
91
97
  import {
92
98
  isFarmPreviewDeploymentEnvironment
93
99
  } from "./chunk-BOYNDCZL.mjs";
@@ -97,7 +103,7 @@ import {
97
103
  import {
98
104
  generateFarmDocsAdapterClientRuntime,
99
105
  getFarmDocsAdapterConfigModule
100
- } from "./chunk-VVBO3QH7.mjs";
106
+ } from "./chunk-ENLZ4R3Y.mjs";
101
107
  import {
102
108
  resolveFarmDocsFontAssets,
103
109
  toFarmDocsPublicFontAssets
@@ -119,7 +125,7 @@ import {
119
125
  } from "./chunk-DAATZTKJ.mjs";
120
126
  import {
121
127
  applyFarmCspHashesToHtml
122
- } from "./chunk-NGVORZVZ.mjs";
128
+ } from "./chunk-UJD4PHYB.mjs";
123
129
  import {
124
130
  applyFarmCronVercelCrons,
125
131
  createFarmCronCloudflareConfig,
@@ -131,27 +137,27 @@ import {
131
137
  } from "./chunk-4OOBRCJX.mjs";
132
138
  import {
133
139
  isFarmMarkdownPageFile
134
- } from "./chunk-AGC75XAE.mjs";
140
+ } from "./chunk-4JHOT46A.mjs";
135
141
  import {
136
142
  resolveFarmMdxComponentsModulePath,
137
143
  resolveMdxConfig
138
144
  } from "./chunk-FA2W42OV.mjs";
139
145
  import {
140
146
  getFarmMarkdownAlternatePath
141
- } from "./chunk-ZUSJDQ2Q.mjs";
147
+ } from "./chunk-WWIKMBRN.mjs";
142
148
  import {
143
149
  applyFarmWorkflowVercelCrons,
144
150
  prepareFarmWorkflowsForNitro
145
- } from "./chunk-3ATMYLLJ.mjs";
151
+ } from "./chunk-6WCPV6G2.mjs";
146
152
  import {
147
153
  getFarmIntegrationPluginServerRuntime,
148
154
  getIntegrationProviders
149
- } from "./chunk-GNSDTTWZ.mjs";
155
+ } from "./chunk-HMIJDL7S.mjs";
150
156
  import {
151
157
  appendMiddlewareDirectory,
152
158
  appendMiddlewareRoutePath,
153
159
  compareMiddlewareRouteLocations
154
- } from "./chunk-7Y6ZNFPX.mjs";
160
+ } from "./chunk-6TJOML4E.mjs";
155
161
  import {
156
162
  compileMiddlewareConfig,
157
163
  matchesCompiledMiddlewareConfig,
@@ -159,7 +165,7 @@ import {
159
165
  } from "./chunk-JG6DJF5A.mjs";
160
166
  import {
161
167
  APIRouteManager
162
- } from "./chunk-LMJ7VRHZ.mjs";
168
+ } from "./chunk-22LTEMGQ.mjs";
163
169
  import {
164
170
  readFarmI18nCatalogs
165
171
  } from "./chunk-QCFBDFRS.mjs";
@@ -1618,7 +1624,7 @@ async function discoverMiddlewareRoutes(appDir) {
1618
1624
  });
1619
1625
  }
1620
1626
  for (const entry of entries) {
1621
- if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name.startsWith("_")) {
1627
+ if (!entry.isDirectory() || entry.name.startsWith(".")) {
1622
1628
  continue;
1623
1629
  }
1624
1630
  await walk(
@@ -1677,6 +1683,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1677
1683
  const markdownSourcePath = entry.markdownSourcePath || (isFarmMarkdownPageFile(entry.modulePath) ? entry.modulePath : void 0);
1678
1684
  pageRoutes.push({
1679
1685
  pattern,
1686
+ ...entry.directory ? { directory: entry.directory } : {},
1680
1687
  modulePath: entry.modulePath,
1681
1688
  ...markdownSourcePath ? {
1682
1689
  source: readFileSync(markdownSourcePath, "utf8"),
@@ -1689,6 +1696,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1689
1696
  (entry) => ({
1690
1697
  name: entry.name,
1691
1698
  ownerPattern: entry.ownerPattern,
1699
+ ...entry.ownerDirectory ? { ownerDirectory: entry.ownerDirectory } : {},
1692
1700
  pattern: entry.pattern,
1693
1701
  modulePath: entry.modulePath,
1694
1702
  containerId: entry.containerId,
@@ -2036,7 +2044,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2036
2044
  };
2037
2045
  }
2038
2046
  });
2039
- const layoutAppliesToRoute = /* @__PURE__ */ __name((layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern}/`), "layoutAppliesToRoute");
2047
+ const layoutAppliesToRoute = routeBoundaryCoversDirectory;
2048
+ const routeDirectory = /* @__PURE__ */ __name((route) => route.directory ?? route.pattern, "routeDirectory");
2040
2049
  const adapterOwnsDocsRuntime = Boolean(
2041
2050
  isReactRenderer(config.renderer) && config.docs?.enabled && config.docs.adapter?.server && config.docs.adapter.react
2042
2051
  );
@@ -2070,8 +2079,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2070
2079
  })),
2071
2080
  [
2072
2081
  ...routePlans.map(({ route, metadata }) => ({
2073
- pattern: route.pattern,
2074
- depth: route.pattern.split("/").filter(Boolean).length,
2082
+ pattern: routeDirectory(route),
2083
+ depth: getRouteDirectoryDepth(routeDirectory(route)),
2075
2084
  metadata
2076
2085
  })),
2077
2086
  ...syntheticDocsPatterns.map((pattern) => ({
@@ -2092,7 +2101,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2092
2101
  layoutAppliesToRoute
2093
2102
  );
2094
2103
  for (const layout of clientLayouts) {
2095
- const matchesBuiltRoute = pageRoutes.some((route) => layoutAppliesToRoute(layout.pattern, route.pattern)) || Boolean(adapterDocsEntry && layoutAppliesToRoute(layout.pattern, adapterDocsEntry));
2104
+ const matchesBuiltRoute = pageRoutes.some((route) => layoutAppliesToRoute(layout.pattern, routeDirectory(route))) || Boolean(adapterDocsEntry && layoutAppliesToRoute(layout.pattern, adapterDocsEntry));
2096
2105
  if (matchesBuiltRoute && layout.suppressedAsyncHydration) {
2097
2106
  logger.warn(`\u26A0\uFE0F ${describeSuppressedAsyncHydration(layout.pattern, layout.fallbackReason)}`);
2098
2107
  }
@@ -2114,7 +2123,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2114
2123
  if (isAdapterDocsRoute(route.pattern)) continue;
2115
2124
  try {
2116
2125
  const applicableClientLayouts = clientLayouts.filter(
2117
- (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layoutAppliesToRoute(layout.pattern, route.pattern)
2126
+ (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layoutAppliesToRoute(layout.pattern, routeDirectory(route))
2118
2127
  );
2119
2128
  if (metadata.suppressedAsyncHydration) {
2120
2129
  logger.warn(
@@ -2141,7 +2150,9 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2141
2150
  isolatedBoundaries: [
2142
2151
  ...metadata.hasIsolatedClientBoundaries ? metadata.isolatedBoundaries : [],
2143
2152
  ...applicableClientLayouts.filter((layout) => layout.hasIsolatedClientBoundaries).flatMap((layout) => layout.isolatedBoundaries)
2144
- ]
2153
+ ],
2154
+ // The server renders a server tree only below a hydrating layout.
2155
+ ...usesFarmServerTree(metadata) && applicableClientLayouts.some((layout) => layout.shouldHydrate) ? { serverTree: true } : {}
2145
2156
  });
2146
2157
  logger.info(`\u{1F4F1} Found hydratable route: ${route.pattern} -> ${route.modulePath}`);
2147
2158
  }
@@ -2298,6 +2309,9 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2298
2309
  ...rendererVitePlugins,
2299
2310
  ...config.vite.plugins || [],
2300
2311
  farmServerOnlyEntriesPlugin(),
2312
+ farmDocsClientConfigPlugin(
2313
+ adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0
2314
+ ),
2301
2315
  // Plugin to redirect @farm.js/core imports to client-only exports
2302
2316
  {
2303
2317
  name: "farm-client-only-imports",
@@ -3151,8 +3165,10 @@ __farmConfigureApp(__farmAppSetup);` : `import React, { createRoot, hydrateRoot
3151
3165
  if (!layout.hasIsolatedClientBoundaries) {
3152
3166
  layoutImportStatements.push(`import Layout${index} from "${relativePath}";`);
3153
3167
  }
3168
+ const groupScope = getRouteGroupScope(layout.pattern);
3169
+ const groupFields = groupScope ? `, urlPattern: ${JSON.stringify(stripRouteGroups(layout.pattern))}, groupScope: ${JSON.stringify(groupScope)}` : "";
3154
3170
  layoutRegistrations.push(
3155
- ` { pattern: ${JSON.stringify(layout.pattern)}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3171
+ ` { pattern: ${JSON.stringify(layout.pattern)}${groupFields}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3156
3172
  );
3157
3173
  });
3158
3174
  const layoutImports = layoutImportStatements.join("\n");
@@ -3497,7 +3513,8 @@ document.addEventListener("click", function(e) {
3497
3513
  }
3498
3514
  const load = page.pageShouldHydrate ? `() => import(${JSON.stringify(toImportPath(page.modulePath))}).then((module) => module.default)` : "null";
3499
3515
  routeEntries.push(` {
3500
- pattern: ${JSON.stringify(page.pattern)},
3516
+ pattern: ${JSON.stringify(page.pattern)},${page.directory ? `
3517
+ directory: ${JSON.stringify(page.directory)},` : ""}
3501
3518
  pageShouldHydrate: ${JSON.stringify(page.pageShouldHydrate)},
3502
3519
  ${page.hasIsolatedClientBoundaries ? "hasIsolatedClientBoundaries: true," : ""}
3503
3520
  islandStrategy: ${JSON.stringify(page.islandStrategy)},
@@ -3506,20 +3523,22 @@ document.addEventListener("click", function(e) {
3506
3523
  }`);
3507
3524
  });
3508
3525
  const isolatedHydrationEnabled = isolatedBoundaryModules.size > 0;
3509
- const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";` : "";
3526
+ const serverTreeEnabled = isolatedHydrationEnabled && clientPages.some((page) => page.serverTree);
3527
+ const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";${serverTreeEnabled ? '\nimport { createFarmServerTreeElement } from "@farm.js/core/internal/server-tree";' : ""}` : "";
3510
3528
  const isolatedHydrationRuntime = isolatedHydrationEnabled ? `const farmIsolatedBoundaryLoaders = {
3511
3529
  ${Array.from(isolatedBoundaryModules.entries()).map(
3512
3530
  ([reference, modulePath]) => ` ${JSON.stringify(reference)}: () => import(${JSON.stringify(modulePath)}),`
3513
3531
  ).join("\n")}
3514
3532
  };
3533
+ async function loadFarmIsolatedBoundary(reference) {
3534
+ const loader = farmIsolatedBoundaryLoaders[reference];
3535
+ if (!loader) throw new Error("isolated client boundary loader was not found: " + reference);
3536
+ return loader();
3537
+ }
3515
3538
  const farmIsolatedHydrationRuntime = createFarmIsolatedHydrationRuntime({
3516
3539
  ReactRuntime: React,
3517
3540
  hydrateRoot,
3518
- load: async function(reference) {
3519
- const loader = farmIsolatedBoundaryLoaders[reference];
3520
- if (!loader) throw new Error("isolated client boundary loader was not found: " + reference);
3521
- return loader();
3522
- },
3541
+ load: loadFarmIsolatedBoundary,
3523
3542
  schedule: scheduleFarmIslandHydration,
3524
3543
  wrap: wrapWithIntegrationProviders,
3525
3544
  });
@@ -3533,7 +3552,21 @@ function disposeFarmIsolatedClientBoundaries(scope) {
3533
3552
 
3534
3553
  async function hydrateFarmIsolatedClientBoundaries(scope = document, signal) {
3535
3554
  await farmIsolatedHydrationRuntime.hydrate(scope, signal);
3536
- }` : "";
3555
+ }
3556
+ ${serverTreeEnabled ? `
3557
+ // A server-tree page (an async page below a hydrating layout) rebuilds in the layout's root.
3558
+ async function createFarmServerTreePageElement(source, pathname) {
3559
+ try {
3560
+ return await createFarmServerTreeElement(React, source, {
3561
+ load: loadFarmIsolatedBoundary,
3562
+ ServerHtml: FarmServerPage,
3563
+ key: pathname,
3564
+ });
3565
+ } catch (error) {
3566
+ console.warn("[Farm.js] Could not rebuild the server tree of " + pathname + "; its server HTML was kept.", error);
3567
+ return null;
3568
+ }
3569
+ }` : "async function createFarmServerTreePageElement() { return null; }"}` : `async function createFarmServerTreePageElement() { return null; }`;
3537
3570
  const routeClientGraphRuntime = isolatedHydrationEnabled ? `function wrapFarmRouteClientGraph(element) {
3538
3571
  return wrapFarmIsolatedClientGraph(React, element);
3539
3572
  }` : `function wrapFarmRouteClientGraph(element) { return element; }`;
@@ -3600,11 +3633,24 @@ ${layoutRegistrations.join(",\n")}
3600
3633
  function getApplicableLayouts(pathname) {
3601
3634
  const applicable = [];
3602
3635
  const normalizedPath = getFarmRoutePathname(pathname).replace(/\\/$/, '') || '/';
3636
+ let directory;
3603
3637
 
3604
3638
  for (const layout of layoutRoutes) {
3605
- if (layout.pattern === '/' || isFarmRouteActive(layout.pattern, normalizedPath, { exact: false })) {
3606
- applicable.push(layout);
3639
+ // Route groups add no URL segment: match the layout's URL, then keep a
3640
+ // grouped layout to the pages inside its group directory.
3641
+ const urlPattern = layout.urlPattern || layout.pattern;
3642
+ if (urlPattern !== '/' && !isFarmRouteActive(urlPattern, normalizedPath, { exact: false })) continue;
3643
+ if (layout.groupScope) {
3644
+ if (directory === undefined) {
3645
+ const matched = matchRoute(pathname);
3646
+ directory = matched ? matched.route.directory || matched.route.pattern : null;
3647
+ }
3648
+ if (
3649
+ typeof directory !== 'string' ||
3650
+ (directory !== layout.groupScope && !directory.startsWith(layout.groupScope + '/'))
3651
+ ) continue;
3607
3652
  }
3653
+ applicable.push(layout);
3608
3654
  }
3609
3655
 
3610
3656
  // Sort by depth (root first)
@@ -3673,6 +3719,16 @@ async function loadRouteComponent(route) {
3673
3719
  return route.Component;
3674
3720
  }
3675
3721
 
3722
+ // The props the server rendered this document with, as the page receives them:
3723
+ // middleware data arrives as a plain object and is a Map again here.
3724
+ function reviveServerPageProps(serverProps) {
3725
+ if (!serverProps || typeof serverProps !== "object") return {};
3726
+ const middleware = serverProps.middleware;
3727
+ return middleware && middleware.data && !(middleware.data instanceof Map)
3728
+ ? { ...serverProps, middleware: { ...middleware, data: new Map(Object.entries(middleware.data)) } }
3729
+ : serverProps;
3730
+ }
3731
+
3676
3732
  async function createMatchedHydrationRoute(matched, pathname, searchParams, serverHtml, serverProps) {
3677
3733
  const hydrateLayouts = hasHydratableLayout(pathname);
3678
3734
  const params = matched.params;
@@ -3686,12 +3742,8 @@ async function createMatchedHydrationRoute(matched, pathname, searchParams, serv
3686
3742
  // rejected guard, deferred data) its server-rendered HTML is kept.
3687
3743
  if (Component.__farmServerProps === true) {
3688
3744
  if (!serverProps || serverProps.__farmRoutePropsResolved !== true) return null;
3689
- const middleware = serverProps.middleware;
3690
3745
  const props = {
3691
- ...serverProps,
3692
- ...(middleware && middleware.data && !(middleware.data instanceof Map)
3693
- ? { middleware: { ...middleware, data: new Map(Object.entries(middleware.data)) } }
3694
- : {}),
3746
+ ...reviveServerPageProps(serverProps),
3695
3747
  searchParams: Promise.resolve(serverProps.search ?? searchParams),
3696
3748
  };
3697
3749
  pageElement = React.createElement(Component, props);
@@ -3702,16 +3754,26 @@ async function createMatchedHydrationRoute(matched, pathname, searchParams, serv
3702
3754
  );
3703
3755
  return null;
3704
3756
  } else {
3705
- const props = { params: params, searchParams: Promise.resolve(searchParams) };
3757
+ // Keep what the server rendered with, such as middleware data, so the
3758
+ // first render matches the HTML. A navigation passes the fetched document's props.
3759
+ const props = {
3760
+ ...reviveServerPageProps(serverProps),
3761
+ params: params,
3762
+ searchParams: Promise.resolve(searchParams),
3763
+ };
3706
3764
  pageElement = React.createElement(Component, props);
3707
3765
  }
3708
3766
  } else if (hydrateLayouts) {
3709
3767
  const serverPage = document.getElementById("__farm_page__");
3710
- pageElement = createLayoutPageBoundary(
3711
- matched.route,
3712
- null,
3713
- typeof serverHtml === "string" ? serverHtml : serverPage ? serverPage.innerHTML : "",
3714
- );
3768
+ const pageSource = typeof serverHtml === "string" ? serverHtml : serverPage;
3769
+ const serverTree = pageSource ? await createFarmServerTreePageElement(pageSource, pathname) : null;
3770
+ pageElement = serverTree
3771
+ ? createLayoutPageBoundary(matched.route, serverTree)
3772
+ : createLayoutPageBoundary(
3773
+ matched.route,
3774
+ null,
3775
+ typeof serverHtml === "string" ? serverHtml : serverPage ? serverPage.innerHTML : "",
3776
+ );
3715
3777
  }
3716
3778
 
3717
3779
  if (!pageElement) return null;
@@ -5299,6 +5361,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5299
5361
  const servesAgentRobotsTxt = Boolean(config.agent?.crawlers?.enabled) && !applicationMetadataRoutes.some(
5300
5362
  (metadata) => metadata.kind === "robots" && metadata.pattern === "/"
5301
5363
  );
5364
+ const servesAiCatalog = config.agent?.aiCatalog !== false;
5302
5365
  const hasPluginRuntime = hasRuntimeIntegrationConfig || hasServerRuntimePlugins;
5303
5366
  const hasInfraAnalyticsRuntime = config.analytics !== false && resolveFarmInstrumentationRuntime(preset) === "nodejs";
5304
5367
  const hasPrecompiledDocs = Boolean(farmDocsPrecompiledManifest);
@@ -5313,7 +5376,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5313
5376
  );
5314
5377
  const hasReactSyncRender = isReactRenderer(config.renderer);
5315
5378
  const rendererServerImports = isReactRenderer(config.renderer) ? `import * as React from "react";
5316
- import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRuntime ? '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";' : ""}` : `import React, * as ReactDOMServer from ${JSON.stringify(config.renderer.server)};${generateFarmRendererAppSetupServerCode(config)}`;
5379
+ import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRuntime ? '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";\nimport { renderFarmServerTreePage } from "@farm.js/core/internal/server-tree";' : ""}` : `import React, * as ReactDOMServer from ${JSON.stringify(config.renderer.server)};${generateFarmRendererAppSetupServerCode(config)}`;
5317
5380
  const routeClientGraphServerRuntime = hasIsolatedClientGraphRuntime ? `function wrapFarmRouteClientGraph(element) {
5318
5381
  return wrapFarmIsolatedClientGraph(React, element);
5319
5382
  }
@@ -5322,9 +5385,17 @@ import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRunti
5322
5385
  // components render as their own islands instead of joining the layout's React tree.
5323
5386
  function isolateFarmRouteServerPage(element) {
5324
5387
  return isolateFarmServerPageGraph(React, element);
5388
+ }
5389
+
5390
+ // An async page below a hydrating layout renders as a serialized tree the browser rebuilds in
5391
+ // the layout's React root, so its client components read the layout's context.
5392
+ function renderFarmRouteServerTree(element) {
5393
+ return renderFarmServerTreePage(React, element, { isolate: isolateFarmRouteServerPage });
5325
5394
  }` : `function wrapFarmRouteClientGraph(element) { return element; }
5326
5395
 
5327
- function isolateFarmRouteServerPage(element) { return element; }`;
5396
+ function isolateFarmRouteServerPage(element) { return element; }
5397
+
5398
+ function renderFarmRouteServerTree(element) { return element; }`;
5328
5399
  const hasGeneratedMetadataImages = metadataImageRoutes.some(
5329
5400
  (image) => image.sourceType === "module"
5330
5401
  );
@@ -5370,7 +5441,6 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5370
5441
  config.renderer,
5371
5442
  Boolean(unsupportedIntegrationProvider)
5372
5443
  );
5373
- const layoutAppliesToRoute = /* @__PURE__ */ __name((layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern}/`), "layoutAppliesToRoute");
5374
5444
  const layoutHydrationPlans = layoutRoutes.map((layout) => ({
5375
5445
  ...layout,
5376
5446
  hydration: getCachedClientModuleHydrationPlan(
@@ -5406,11 +5476,12 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5406
5476
  metadata: layout.hydration
5407
5477
  })),
5408
5478
  pageRoutes.map((route) => ({
5409
- pattern: route.pattern,
5410
- depth: route.pattern.split("/").filter(Boolean).length,
5479
+ // Compared by directory so a grouped layout applies only inside its group.
5480
+ pattern: route.directory ?? route.pattern,
5481
+ depth: getRouteDirectoryDepth(route.directory ?? route.pattern),
5411
5482
  metadata: pageHydrationPlans.get(route.modulePath)
5412
5483
  })),
5413
- layoutAppliesToRoute
5484
+ routeBoundaryCoversDirectory
5414
5485
  );
5415
5486
  const providerServerImports = [
5416
5487
  providerServerModules.hasClerkProvider ? `import { ClerkProvider as FarmClerkProvider } from "@clerk/react";` : "",
@@ -5443,7 +5514,8 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5443
5514
  if (isFarmMarkdownPageFile(route.modulePath)) {
5444
5515
  pageRegistrations.push(`
5445
5516
  {
5446
- pattern: ${JSON.stringify(route.pattern)},
5517
+ pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5518
+ directory: ${JSON.stringify(route.directory)},` : ""}
5447
5519
  module: createFarmMarkdownRouteModule({
5448
5520
  source: ${JSON.stringify(route.source ?? "")},
5449
5521
  filePath: ${JSON.stringify(toBakedMarkdownSourcePath(config.root, route.modulePath))},
@@ -5466,10 +5538,11 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5466
5538
  const renderingDirective = parseRouteRenderingDirectiveFromDisk(route.modulePath);
5467
5539
  pageRegistrations.push(`
5468
5540
  {
5469
- pattern: ${JSON.stringify(route.pattern)},
5541
+ pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5542
+ directory: ${JSON.stringify(route.directory)},` : ""}
5470
5543
  module: ${varName},
5471
5544
  shouldHydrate: ${JSON.stringify(clientMetadata.shouldHydrate)},
5472
- islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${renderingDirective ? `
5545
+ islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${usesFarmServerTree(clientMetadata) ? "\n serverTree: true," : ""}${renderingDirective ? `
5473
5546
  rendering: ${JSON.stringify(renderingDirective)},` : ""}
5474
5547
  ${route.source !== void 0 ? `markdownSource: {
5475
5548
  source: ${JSON.stringify(route.source)},
@@ -5510,7 +5583,8 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5510
5583
  routeSlotRegistrations.push(`
5511
5584
  {
5512
5585
  name: ${JSON.stringify(slot.name)},
5513
- ownerPattern: ${JSON.stringify(slot.ownerPattern)},
5586
+ ownerPattern: ${JSON.stringify(slot.ownerPattern)},${slot.ownerDirectory ? `
5587
+ ownerDirectory: ${JSON.stringify(slot.ownerDirectory)},` : ""}
5514
5588
  pattern: ${JSON.stringify(slot.pattern)},
5515
5589
  containerId: ${JSON.stringify(slot.containerId)},
5516
5590
  interception: ${JSON.stringify(slot.interception)},
@@ -5525,9 +5599,12 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5525
5599
  errorImports.push(
5526
5600
  `import * as ${varName} from ${toVirtualEntryImportSpecifier(errorRoute.modulePath)};`
5527
5601
  );
5602
+ const groupScope = getRouteGroupScope(errorRoute.pattern);
5528
5603
  errorRegistrations.push(`
5529
5604
  {
5530
- pattern: ${JSON.stringify(errorRoute.pattern)},
5605
+ pattern: ${JSON.stringify(stripRouteGroups(errorRoute.pattern))},${groupScope ? `
5606
+ groupScope: ${JSON.stringify(groupScope)},
5607
+ directoryDepth: ${getRouteDirectoryDepth(errorRoute.pattern)},` : ""}
5531
5608
  module: ${varName},
5532
5609
  }`);
5533
5610
  });
@@ -5605,14 +5682,18 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5605
5682
  createDefaultErrorMarkup,
5606
5683
  createFarmInstrumentationLifecycle,
5607
5684
  createFarmLayoutSelector,
5685
+ isInFarmRouteGroupScope,
5608
5686
  createFarmCacheKey,
5609
5687
  createFarmMetadataRouteResponse,
5610
5688
  createFarmAgentRobots,
5689
+ createFarmAiCatalogResponse,
5611
5690
  createFarmApiCatalogResponse,
5612
5691
  createFarmAppManifestResponse,
5613
5692
  collectFarmLlmsTxtPages,
5614
5693
  createFarmDefaultLlmsTxt,
5615
5694
  createFarmLlmsMarkdownReader,
5695
+ listFarmMCPLlmsTxtLinks,
5696
+ registerFarmMCPServer,
5616
5697
  renderFarmLlmsFullTxt,
5617
5698
  createFarmLlmsFullRenderer,
5618
5699
  createFarmThemeDocumentParts,
@@ -5633,6 +5714,9 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5633
5714
  mergeRouteRenderingDirectiveConfig,
5634
5715
  manageFarmLinkHeaderPreloads,
5635
5716
  mergeMetadata,
5717
+ mergeModuleViewport,
5718
+ ensureFarmDocumentMeta,
5719
+ renderViewportHead,
5636
5720
  matchesFarmIfNoneMatch,
5637
5721
  normalizeRevalidatePath,
5638
5722
  reportFarmPreloadWarnings,
@@ -6108,6 +6192,8 @@ const farmDocsHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsP
6108
6192
  getApplicableLayouts(getFarmRoutePathname(pathname)).map((layout) => layout.module),
6109
6193
  ),
6110
6194
  loadReactModule: async () => FarmDocsAdapterReact,
6195
+ // Lists the docs MCP endpoint in /.well-known/ai-catalog.json for the server's lifetime.
6196
+ registerMCPServer: registerFarmMCPServer,
6111
6197
  })` : `createFarmDocsHandler(farmDocsResolvedConfig, {
6112
6198
  root: farmDocsRuntimeRoot,
6113
6199
  srcDir: ${JSON.stringify(config.srcDir)},
@@ -6160,7 +6246,7 @@ for (const route of pageRoutes) {
6160
6246
  // Layout routes bundled at build time (sorted by depth, root first)
6161
6247
  const layoutRoutes = [${layoutRegistrations.join(",")}
6162
6248
  ];
6163
- const selectApplicableLayouts = createFarmLayoutSelector(layoutRoutes);
6249
+ const selectApplicableLayouts = createFarmLayoutSelector(layoutRoutes, getMatchedPageDirectory);
6164
6250
 
6165
6251
  const routeSlots = [${routeSlotRegistrations.join(",")}
6166
6252
  ];
@@ -6809,6 +6895,7 @@ ${generateRuntimePathMatcherSource()}
6809
6895
  function getMatchingErrorBoundary(pathname) {
6810
6896
  const pathSegments = splitRuntimePath(pathname);
6811
6897
  let bestMatch = null;
6898
+ let directory;
6812
6899
 
6813
6900
  for (const errorRoute of errorRoutes) {
6814
6901
  const patternDepth = splitRuntimePath(errorRoute.pattern).length;
@@ -6818,9 +6905,18 @@ function getMatchingErrorBoundary(pathname) {
6818
6905
  : "/" + pathSegments.slice(0, patternDepth).join("/");
6819
6906
  const params = matchRuntimePathPattern(errorRoute.pattern, candidatePath);
6820
6907
  if (params === null) continue;
6908
+ if (errorRoute.groupScope) {
6909
+ if (directory === undefined) directory = getMatchedPageDirectory(pathname);
6910
+ if (!isInFarmRouteGroupScope(directory, errorRoute.groupScope)) continue;
6911
+ }
6821
6912
 
6822
- if (!bestMatch || patternDepth > bestMatch.depth) {
6823
- bestMatch = { route: errorRoute, params, depth: patternDepth };
6913
+ const directoryDepth = errorRoute.directoryDepth ?? patternDepth;
6914
+ if (
6915
+ !bestMatch ||
6916
+ patternDepth > bestMatch.depth ||
6917
+ (patternDepth === bestMatch.depth && directoryDepth > bestMatch.directoryDepth)
6918
+ ) {
6919
+ bestMatch = { route: errorRoute, params, depth: patternDepth, directoryDepth };
6824
6920
  }
6825
6921
  }
6826
6922
 
@@ -7044,6 +7140,10 @@ function createFarmLlmsTxtContext(request, full) {
7044
7140
  pages,
7045
7141
  config: farmLlmsTxtConfig,
7046
7142
  rootMetadata: rootLayout && rootLayout.module && rootLayout.module.metadata,
7143
+ ${servesAiCatalog ? `mcp: listFarmMCPLlmsTxtLinks(origin, {
7144
+ basePath: ${JSON.stringify(config.basePath)},
7145
+ apiServerBasePath: farmLocalAPIBasePath,
7146
+ }),` : ""}
7047
7147
  }),
7048
7148
  // llms-full.txt reads each page's .md mirror through this same handler,
7049
7149
  // with a fresh request so the caller's cookies never shape its content.
@@ -7393,11 +7493,18 @@ function getFarmPluginRequestOptions(request) {
7393
7493
  return { kind: "request", route };
7394
7494
  }
7395
7495
 
7496
+ /** The directory of the page a pathname selects, or null; route groups confine layouts to it. */
7497
+ function getMatchedPageDirectory(pathname) {
7498
+ const match = matchPageRoute(pathname);
7499
+ return match ? match.route.directory || match.route.pattern : null;
7500
+ }
7501
+
7396
7502
  /**
7397
- * Get applicable layouts for a page path (from root to most specific)
7503
+ * Get applicable layouts for a page path (from root to most specific). Pass the
7504
+ * selected page's directory when it is known, or null when no page applies.
7398
7505
  */
7399
- function getApplicableLayouts(pathname) {
7400
- const applicable = selectApplicableLayouts(pathname);
7506
+ function getApplicableLayouts(pathname, directory) {
7507
+ const applicable = selectApplicableLayouts(pathname, directory);
7401
7508
  // buildSSRInMemory already emits these immutable descriptors in stable depth
7402
7509
  // order. Filtering preserves that order, including equal-depth ties.
7403
7510
  return applicable;
@@ -7758,6 +7865,20 @@ async function handleFarmRequestInContext(
7758
7865
  const middlewareHeaders = ${hasServerRuntimeIntegrations ? "withFarmIntegrationSetCookies(undefined, farmIntegrationSetCookies)" : "undefined"};
7759
7866
  `}
7760
7867
 
7868
+ ${servesAiCatalog ? `
7869
+ // agent.aiCatalog: the AI catalog of MCP servers and each server's card. Cards
7870
+ // live below the MCP endpoint, so this answers before the docs runtime and the
7871
+ // API routes, as in dev.
7872
+ const farmAiCatalogResponse = createFarmAiCatalogResponse(
7873
+ request,
7874
+ { basePath: ${JSON.stringify(config.basePath)}, apiServerBasePath: farmLocalAPIBasePath },
7875
+ url,
7876
+ );
7877
+ if (farmAiCatalogResponse) {
7878
+ return applyProductionMiddlewareHeaders(farmAiCatalogResponse, middlewareHeaders);
7879
+ }
7880
+ ` : ""}
7881
+
7761
7882
  ${config.docs?.enabled ? `
7762
7883
  // Docs responses are served after app middleware so route guards and
7763
7884
  // middleware headers apply to the docs engine like any other page content.
@@ -8064,7 +8185,10 @@ async function handleFarmRequestInContext(
8064
8185
  const pageMetadata = route.module.metadata || {};
8065
8186
 
8066
8187
  // Get applicable layouts for this page
8067
- const applicableLayouts = getApplicableLayouts(routePathname);
8188
+ const applicableLayouts = getApplicableLayouts(
8189
+ routePathname,
8190
+ route.directory || route.pattern,
8191
+ );
8068
8192
  const shouldHydrateLayout = applicableLayouts.some(
8069
8193
  (layout) => layout.shouldHydrate === true,
8070
8194
  );
@@ -8297,7 +8421,9 @@ async function handleFarmRequestInContext(
8297
8421
  if (route.shouldHydrate && !shouldHydrateLayout) {
8298
8422
  pageElement = wrapFarmRouteClientGraph(pageElement);
8299
8423
  } else if (shouldHydrateLayout && !route.shouldHydrate) {
8300
- pageElement = isolateFarmRouteServerPage(pageElement);
8424
+ pageElement = route.serverTree
8425
+ ? await renderFarmRouteServerTree(pageElement)
8426
+ : isolateFarmRouteServerPage(pageElement);
8301
8427
  }
8302
8428
 
8303
8429
  pageElement = React.createElement(
@@ -8324,7 +8450,7 @@ async function handleFarmRequestInContext(
8324
8450
  if (LayoutComponent) {
8325
8451
  const slotProps = {};
8326
8452
  for (const slot of renderedRouteSlots) {
8327
- if (slot.ownerPattern !== layout.pattern) continue;
8453
+ if ((slot.ownerDirectory || slot.ownerPattern) !== layout.pattern) continue;
8328
8454
  slotProps[slot.name] = React.createElement(
8329
8455
  "div",
8330
8456
  {
@@ -8391,6 +8517,9 @@ async function handleFarmRequestInContext(
8391
8517
  await layout.module.generateMetadata({ params: pageProps.params }),
8392
8518
  );
8393
8519
  }
8520
+ mergedMetadata = await mergeModuleViewport(mergedMetadata, layout.module, {
8521
+ params: pageProps.params,
8522
+ });
8394
8523
  }
8395
8524
  mergedMetadata = mergeMetadata(mergedMetadata, pageMetadata);
8396
8525
  if (!routeStateRejected && typeof route.module.generateMetadata === "function") {
@@ -8399,6 +8528,11 @@ async function handleFarmRequestInContext(
8399
8528
  await route.module.generateMetadata(pageProps),
8400
8529
  );
8401
8530
  }
8531
+ mergedMetadata = await mergeModuleViewport(
8532
+ mergedMetadata,
8533
+ routeStateRejected ? { viewport: route.module.viewport } : route.module,
8534
+ pageProps,
8535
+ );
8402
8536
 
8403
8537
  if (!mergedMetadata.manifest) {
8404
8538
  const manifestMatch = getMatchingApplicationMetadataRoute(routePathname, "manifest");
@@ -8442,6 +8576,7 @@ async function handleFarmRequestInContext(
8442
8576
  const title = renderedMetadata.title;
8443
8577
  const metaTags = renderedMetadata.tags;
8444
8578
  const hasFavicon = renderedMetadata.hasFavicon;
8579
+ const viewportTags = renderedMetadata.viewport;
8445
8580
 
8446
8581
  const hasPrivateRequestHeaders = hasPrivateFarmRequestHeaders(
8447
8582
  request,
@@ -8493,7 +8628,7 @@ async function handleFarmRequestInContext(
8493
8628
  const streamPrefix = '<!DOCTYPE html>\\n<html lang="en">\\n<head>\\n' +
8494
8629
  farmThemeDocument.head + '\\n' +
8495
8630
  ' <meta charset="utf-8">\\n' +
8496
- ' <meta name="viewport" content="width=device-width, initial-scale=1">\\n' +
8631
+ ' ' + viewportTags + '\\n' +
8497
8632
  (hasFavicon ? '' : ' <link rel="icon" href="data:,">\\n') +
8498
8633
  ' <title>' + title + '</title>' + metaTags + '\\n' +
8499
8634
  ' <link rel="stylesheet" href="/__farm_client_css_href__">\\n' +
@@ -8624,6 +8759,9 @@ async function handleFarmRequestInContext(
8624
8759
  ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
8625
8760
  );
8626
8761
 
8762
+ // Last, so the charset (and the viewport, unless the layout wrote one) open the head.
8763
+ fullHtml = ensureFarmDocumentMeta(fullHtml, viewportTags);
8764
+
8627
8765
  // Add DOCTYPE if not present
8628
8766
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
8629
8767
  fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
@@ -8634,7 +8772,7 @@ async function handleFarmRequestInContext(
8634
8772
  <html lang="en">
8635
8773
  <head>
8636
8774
  <meta charset="utf-8">
8637
- <meta name="viewport" content="width=device-width, initial-scale=1">
8775
+ \${viewportTags}
8638
8776
  \${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8639
8777
  \${suppressDefaultTitle ? "" : "<title>" + title + "</title>"}\${metaTags}\${rendererHead ? "\\n " + rendererHead : ""}
8640
8778
  <link rel="stylesheet" href="/__farm_client_css_href__">
@@ -8884,7 +9022,8 @@ async function handleFarmRequestInContext(
8884
9022
  try {
8885
9023
  // Wrap 404 page with root layout if available
8886
9024
  let notFoundElement = createFarmNotFoundElement(pathname);
8887
- const applicableLayouts = getApplicableLayouts("/");
9025
+ // No page matched, so a layout inside a route group cannot apply.
9026
+ const applicableLayouts = getApplicableLayouts("/", null);
8888
9027
 
8889
9028
  // Wrap with layouts (from innermost to outermost)
8890
9029
  for (let i = applicableLayouts.length - 1; i >= 0; i--) {
@@ -8928,6 +9067,7 @@ async function handleFarmRequestInContext(
8928
9067
  () => ' ' + renderFarmClientBootstrapScript() + '\\n' +
8929
9068
  ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
8930
9069
  );
9070
+ fullHtml = ensureFarmDocumentMeta(fullHtml, notFoundMetadata.viewport);
8931
9071
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
8932
9072
  fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
8933
9073
  }
@@ -8936,7 +9076,7 @@ async function handleFarmRequestInContext(
8936
9076
  <html lang="en">
8937
9077
  <head>
8938
9078
  <meta charset="UTF-8">
8939
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
9079
+ \${notFoundMetadata.viewport}
8940
9080
  \${notFoundMetadata.hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8941
9081
  <link rel="stylesheet" href="/__farm_client_css_href__">
8942
9082
  <title>\${notFoundMetadata.title}</title>\${notFoundMetadata.tags}
@@ -10606,7 +10746,7 @@ function resolveLegacyPageEntry(config, root, srcDir) {
10606
10746
  __name(resolveLegacyPageEntry, "resolveLegacyPageEntry");
10607
10747
  async function buildNitro(config, routeManager, apiRouteManager, serverRenderer, preset, root, distDir, pluginManager) {
10608
10748
  const [{ createNitroConfig }, { createNitro, build: nitroBuild }] = await Promise.all([
10609
- import("./nitro-4XGPNIK4.mjs"),
10749
+ import("./nitro-MXRDCXWZ.mjs"),
10610
10750
  import("nitro/builder")
10611
10751
  ]);
10612
10752
  let nitroConfig = await createNitroConfig(