@riverbankcms/sdk 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +298 -2
  2. package/dist/cli/index.js +2409 -595
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/cli/init-docs/content/agents-section.md +11 -0
  5. package/dist/cli/init-docs/content/cli-reference.md +15 -1
  6. package/dist/cli/init-docs/content/workflow-add-block.md +7 -0
  7. package/dist/cli/init-docs/content/workflow-block-extensions.md +361 -0
  8. package/dist/cli/init-docs/content/workflow-cmsify-page.md +357 -0
  9. package/dist/cli/init-docs/content/workflow-content-types.md +328 -0
  10. package/dist/cli/init-docs/content/workflow-create-page.md +9 -0
  11. package/dist/cli/init-docs/content/workflow-custom-block.md +446 -0
  12. package/dist/client/client.d.mts +2 -2
  13. package/dist/client/client.d.ts +2 -2
  14. package/dist/client/client.js +386 -45
  15. package/dist/client/client.js.map +1 -1
  16. package/dist/client/client.mjs +386 -45
  17. package/dist/client/client.mjs.map +1 -1
  18. package/dist/client/hooks.d.mts +2 -2
  19. package/dist/client/hooks.d.ts +2 -2
  20. package/dist/client/hooks.js +40 -26
  21. package/dist/client/hooks.js.map +1 -1
  22. package/dist/client/hooks.mjs +40 -26
  23. package/dist/client/hooks.mjs.map +1 -1
  24. package/dist/client/rendering/client.js +210 -128
  25. package/dist/client/rendering/client.js.map +1 -1
  26. package/dist/client/rendering/client.mjs +202 -114
  27. package/dist/client/rendering/client.mjs.map +1 -1
  28. package/dist/client/usePage--LiGLbVz.d.mts +7195 -0
  29. package/dist/client/usePage-BwQJlxpe.d.mts +7218 -0
  30. package/dist/client/usePage-Ds-ow1-d.d.ts +7195 -0
  31. package/dist/client/usePage-Dsi39Exp.d.ts +6915 -0
  32. package/dist/client/usePage-Duc2GC-H.d.ts +7218 -0
  33. package/dist/client/usePage-DyzrgxqR.d.mts +7215 -0
  34. package/dist/client/usePage-Im82JRRe.d.mts +6915 -0
  35. package/dist/client/usePage-lTWkuVMZ.d.ts +7215 -0
  36. package/dist/server/{Layout-l2v4Qa6E.d.ts → Layout-BHGokJmV.d.ts} +1 -1
  37. package/dist/server/{Layout-D4J009eS.d.mts → Layout-CXkMcTR4.d.mts} +1 -1
  38. package/dist/server/chunk-274Y2CUE.js +341 -0
  39. package/dist/server/chunk-274Y2CUE.js.map +1 -0
  40. package/dist/server/{chunk-RVDS7VSP.js → chunk-2WL52ZOE.js} +8 -8
  41. package/dist/server/{chunk-RVDS7VSP.js.map → chunk-2WL52ZOE.js.map} +1 -1
  42. package/dist/server/{chunk-TT5JWA4X.js → chunk-5HGVBSWA.js} +9 -9
  43. package/dist/server/{chunk-TT5JWA4X.js.map → chunk-5HGVBSWA.js.map} +1 -1
  44. package/dist/server/{chunk-YXA4GAAQ.mjs → chunk-6VTKALLN.mjs} +2 -6
  45. package/dist/server/{chunk-YXA4GAAQ.mjs.map → chunk-6VTKALLN.mjs.map} +1 -1
  46. package/dist/server/chunk-7WJGJY3B.js +7 -0
  47. package/dist/server/chunk-7WJGJY3B.js.map +1 -0
  48. package/dist/server/chunk-AGAOKSPY.mjs +22 -0
  49. package/dist/server/chunk-AGAOKSPY.mjs.map +1 -0
  50. package/dist/server/{chunk-BYBJA6SP.mjs → chunk-BOYBN4KN.mjs} +37 -23
  51. package/dist/server/chunk-BOYBN4KN.mjs.map +1 -0
  52. package/dist/server/{chunk-LNOUXALA.mjs → chunk-CKZDJBMC.mjs} +126 -17
  53. package/dist/server/chunk-CKZDJBMC.mjs.map +1 -0
  54. package/dist/server/{chunk-RBJFXNDM.mjs → chunk-E4R5ILRE.mjs} +4 -4
  55. package/dist/server/{chunk-WM646WI3.js → chunk-EC2AA2IP.js} +275 -297
  56. package/dist/server/chunk-EC2AA2IP.js.map +1 -0
  57. package/dist/server/{chunk-2KCF2DNK.js → chunk-F4U4LC5D.js} +8 -8
  58. package/dist/server/{chunk-2KCF2DNK.js.map → chunk-F4U4LC5D.js.map} +1 -1
  59. package/dist/server/{chunk-ARNCLSQT.mjs → chunk-H44G72AB.mjs} +2 -2
  60. package/dist/server/{chunk-7BVRA5MY.js → chunk-JVLQDZTZ.js} +9 -9
  61. package/dist/server/{chunk-7BVRA5MY.js.map → chunk-JVLQDZTZ.js.map} +1 -1
  62. package/dist/server/{chunk-OSF34JTQ.mjs → chunk-KKUR3PDT.mjs} +4 -4
  63. package/dist/server/chunk-NTG7XP3E.js +264 -0
  64. package/dist/server/chunk-NTG7XP3E.js.map +1 -0
  65. package/dist/server/{chunk-P4K63SBZ.mjs → chunk-OSTUHBFE.mjs} +3 -3
  66. package/dist/server/{chunk-EIVISR62.js → chunk-P4O3WSAR.js} +2 -6
  67. package/dist/server/chunk-P4O3WSAR.js.map +1 -0
  68. package/dist/server/chunk-PAHSKNY5.mjs +264 -0
  69. package/dist/server/chunk-PAHSKNY5.mjs.map +1 -0
  70. package/dist/server/chunk-PSN6HXUD.js +22 -0
  71. package/dist/server/chunk-PSN6HXUD.js.map +1 -0
  72. package/dist/server/{chunk-65A5HAUZ.mjs → chunk-QS6ZTLLB.mjs} +243 -265
  73. package/dist/server/chunk-QS6ZTLLB.mjs.map +1 -0
  74. package/dist/server/{chunk-P3NNN73G.js → chunk-R6T3Z4W5.js} +3 -3
  75. package/dist/server/{chunk-P3NNN73G.js.map → chunk-R6T3Z4W5.js.map} +1 -1
  76. package/dist/server/{chunk-EIJ27EZQ.js → chunk-RIROJYPX.js} +10 -6
  77. package/dist/server/chunk-RIROJYPX.js.map +1 -0
  78. package/dist/server/chunk-SVEQVEA5.mjs +341 -0
  79. package/dist/server/chunk-SVEQVEA5.mjs.map +1 -0
  80. package/dist/server/{chunk-AEFWG657.mjs → chunk-TBN35TGI.mjs} +6 -6
  81. package/dist/server/{chunk-AEFWG657.mjs.map → chunk-TBN35TGI.mjs.map} +1 -1
  82. package/dist/server/{chunk-4YQJUL5W.mjs → chunk-TBX6CXBM.mjs} +8 -4
  83. package/dist/server/chunk-TBX6CXBM.mjs.map +1 -0
  84. package/dist/server/{chunk-YYO3RIFO.js → chunk-U2F4BWKW.js} +37 -23
  85. package/dist/server/chunk-U2F4BWKW.js.map +1 -0
  86. package/dist/server/{chunk-NFEGQTCC.mjs → chunk-WMJKH4XE.mjs} +8 -1
  87. package/dist/server/chunk-WWGVFOLS.mjs +7 -0
  88. package/dist/server/chunk-WWGVFOLS.mjs.map +1 -0
  89. package/dist/server/{chunk-T26N3P26.js → chunk-X4REO3S7.js} +4 -4
  90. package/dist/server/{chunk-T26N3P26.js.map → chunk-X4REO3S7.js.map} +1 -1
  91. package/dist/server/{chunk-C6FIJC7T.mjs → chunk-YUD7ONZG.mjs} +2 -2
  92. package/dist/server/{chunk-4CV4JOE5.js → chunk-Z6ZWNWWR.js} +9 -2
  93. package/dist/server/chunk-Z6ZWNWWR.js.map +1 -0
  94. package/dist/server/{chunk-7UPVCT3K.js → chunk-ZJXFRSTC.js} +270 -161
  95. package/dist/server/chunk-ZJXFRSTC.js.map +1 -0
  96. package/dist/server/{components-vtYEmmPF.d.mts → components-Bqn4xmR6.d.mts} +75 -6
  97. package/dist/server/{components-D2uCKCj7.d.ts → components-C7j9yzAt.d.ts} +75 -6
  98. package/dist/server/components.d.mts +6 -6
  99. package/dist/server/components.d.ts +6 -6
  100. package/dist/server/components.js +9 -7
  101. package/dist/server/components.js.map +1 -1
  102. package/dist/server/components.mjs +8 -6
  103. package/dist/server/config-validation.d.mts +3 -3
  104. package/dist/server/config-validation.d.ts +3 -3
  105. package/dist/server/config-validation.js +6 -6
  106. package/dist/server/config-validation.mjs +5 -5
  107. package/dist/server/config.d.mts +5 -5
  108. package/dist/server/config.d.ts +5 -5
  109. package/dist/server/config.js +6 -6
  110. package/dist/server/config.mjs +5 -5
  111. package/dist/server/data.d.mts +3 -3
  112. package/dist/server/data.d.ts +3 -3
  113. package/dist/server/data.js +4 -4
  114. package/dist/server/data.mjs +3 -3
  115. package/dist/server/env.js +1 -1
  116. package/dist/server/env.mjs +1 -1
  117. package/dist/server/{index-BxrAuL9K.d.ts → index-Bns_1a4N.d.ts} +2 -2
  118. package/dist/server/{index-CH_dvF6n.d.ts → index-CHp2kyp0.d.ts} +2 -2
  119. package/dist/server/{index-2qnY7VH_.d.mts → index-CPDT8kn9.d.mts} +2 -2
  120. package/dist/server/{index-DfWg1Qle.d.mts → index-Cm9nMPkf.d.mts} +2 -2
  121. package/dist/server/index.d.mts +195 -217
  122. package/dist/server/index.d.ts +195 -217
  123. package/dist/server/index.js +10 -289
  124. package/dist/server/index.js.map +1 -1
  125. package/dist/server/index.mjs +11 -290
  126. package/dist/server/index.mjs.map +1 -1
  127. package/dist/server/{loadContent-DECnsp4k.d.ts → loadContent-DD7J5_WO.d.ts} +26 -4
  128. package/dist/server/{loadContent-Du5kS8UM.d.mts → loadContent-DTEgYI-l.d.mts} +26 -4
  129. package/dist/server/{loadPage-VBorKlWv.d.mts → loadPage-B578Xg2W.d.mts} +3 -3
  130. package/dist/server/{loadPage-BZohBxxf.d.ts → loadPage-Dkiimbsg.d.ts} +3 -3
  131. package/dist/server/loadPage-IBX7FXGH.mjs +11 -0
  132. package/dist/server/loadPage-KG74OG4V.js +11 -0
  133. package/dist/server/{loadPage-AXNAERDS.js.map → loadPage-KG74OG4V.js.map} +1 -1
  134. package/dist/server/metadata.d.mts +5 -5
  135. package/dist/server/metadata.d.ts +5 -5
  136. package/dist/server/metadata.js +1 -1
  137. package/dist/server/metadata.mjs +1 -1
  138. package/dist/server/navigation.d.mts +4 -8
  139. package/dist/server/navigation.d.ts +4 -8
  140. package/dist/server/navigation.js +3 -7
  141. package/dist/server/navigation.js.map +1 -1
  142. package/dist/server/navigation.mjs +2 -6
  143. package/dist/server/next/revalidate.js +1 -1
  144. package/dist/server/next/revalidate.mjs +1 -1
  145. package/dist/server/next/tags.js +1 -1
  146. package/dist/server/next/tags.mjs +1 -1
  147. package/dist/server/next.d.mts +7 -7
  148. package/dist/server/next.d.ts +7 -7
  149. package/dist/server/next.js +23 -16
  150. package/dist/server/next.js.map +1 -1
  151. package/dist/server/next.mjs +15 -8
  152. package/dist/server/next.mjs.map +1 -1
  153. package/dist/server/prebuild-loader.d.mts +87 -0
  154. package/dist/server/prebuild-loader.d.ts +87 -0
  155. package/dist/server/prebuild-loader.js +15 -0
  156. package/dist/server/prebuild-loader.js.map +1 -0
  157. package/dist/server/prebuild-loader.mjs +15 -0
  158. package/dist/server/prebuild-loader.mjs.map +1 -0
  159. package/dist/server/prebuild-types.d.mts +201 -0
  160. package/dist/server/prebuild-types.d.ts +201 -0
  161. package/dist/server/prebuild-types.js +1 -0
  162. package/dist/server/prebuild-types.js.map +1 -0
  163. package/dist/server/prebuild-types.mjs +1 -0
  164. package/dist/server/prebuild-types.mjs.map +1 -0
  165. package/dist/server/prebuild.d.mts +46 -0
  166. package/dist/server/prebuild.d.ts +46 -0
  167. package/dist/server/prebuild.js +10 -0
  168. package/dist/server/prebuild.js.map +1 -0
  169. package/dist/server/prebuild.mjs +10 -0
  170. package/dist/server/prebuild.mjs.map +1 -0
  171. package/dist/server/rendering/server.d.mts +5 -5
  172. package/dist/server/rendering/server.d.ts +5 -5
  173. package/dist/server/rendering/server.js +9 -9
  174. package/dist/server/rendering/server.mjs +8 -8
  175. package/dist/server/rendering.d.mts +9 -9
  176. package/dist/server/rendering.d.ts +9 -9
  177. package/dist/server/rendering.js +13 -11
  178. package/dist/server/rendering.js.map +1 -1
  179. package/dist/server/rendering.mjs +12 -10
  180. package/dist/server/routing.d.mts +5 -5
  181. package/dist/server/routing.d.ts +5 -5
  182. package/dist/server/routing.js +2 -2
  183. package/dist/server/routing.mjs +2 -2
  184. package/dist/server/{schema-Z6-afHJG.d.mts → schema-DYtW0zEu.d.mts} +40 -0
  185. package/dist/server/{schema-Z6-afHJG.d.ts → schema-DYtW0zEu.d.ts} +40 -0
  186. package/dist/server/server.d.mts +6 -6
  187. package/dist/server/server.d.ts +6 -6
  188. package/dist/server/server.js +10 -7
  189. package/dist/server/server.js.map +1 -1
  190. package/dist/server/server.mjs +9 -6
  191. package/dist/server/theme-bridge.js +9 -9
  192. package/dist/server/theme-bridge.mjs +3 -3
  193. package/dist/server/theme.js +1 -1
  194. package/dist/server/theme.mjs +1 -1
  195. package/dist/server/{types-DT30Qy7x.d.mts → types-B6P_iaDz.d.mts} +296 -2
  196. package/dist/server/{types-CgSO0yxg.d.ts → types-C4jfCjaP.d.ts} +296 -2
  197. package/dist/server/{types-D0rPF8l5.d.ts → types-CSvCkmYi.d.mts} +13 -4
  198. package/dist/server/{types-D8XqwoVd.d.ts → types-DVesWaB7.d.ts} +1 -1
  199. package/dist/server/{types-CJfJwcuL.d.mts → types-M0CviVW2.d.mts} +1 -1
  200. package/dist/server/{types-BRQ_6yOc.d.mts → types-gKcrQV09.d.ts} +13 -4
  201. package/dist/server/{validation-Pv3Zs6dP.d.mts → validation-BA1TKthZ.d.mts} +2 -2
  202. package/dist/server/{validation-D1LaY1kQ.d.ts → validation-js7BCPN8.d.ts} +2 -2
  203. package/dist/server/webhooks.js +1 -1
  204. package/dist/server/webhooks.mjs +1 -1
  205. package/dist/styles/index.css +419 -0
  206. package/package.json +17 -3
  207. package/dist/server/chunk-4CV4JOE5.js.map +0 -1
  208. package/dist/server/chunk-4YQJUL5W.mjs.map +0 -1
  209. package/dist/server/chunk-65A5HAUZ.mjs.map +0 -1
  210. package/dist/server/chunk-7UPVCT3K.js.map +0 -1
  211. package/dist/server/chunk-BYBJA6SP.mjs.map +0 -1
  212. package/dist/server/chunk-EIJ27EZQ.js.map +0 -1
  213. package/dist/server/chunk-EIVISR62.js.map +0 -1
  214. package/dist/server/chunk-LNOUXALA.mjs.map +0 -1
  215. package/dist/server/chunk-WM646WI3.js.map +0 -1
  216. package/dist/server/chunk-YYO3RIFO.js.map +0 -1
  217. package/dist/server/loadPage-AXNAERDS.js +0 -11
  218. package/dist/server/loadPage-XR7ORQ2E.mjs +0 -11
  219. package/src/styles/index.css +0 -10
  220. /package/dist/server/{chunk-RBJFXNDM.mjs.map → chunk-E4R5ILRE.mjs.map} +0 -0
  221. /package/dist/server/{chunk-ARNCLSQT.mjs.map → chunk-H44G72AB.mjs.map} +0 -0
  222. /package/dist/server/{chunk-OSF34JTQ.mjs.map → chunk-KKUR3PDT.mjs.map} +0 -0
  223. /package/dist/server/{chunk-P4K63SBZ.mjs.map → chunk-OSTUHBFE.mjs.map} +0 -0
  224. /package/dist/server/{chunk-NFEGQTCC.mjs.map → chunk-WMJKH4XE.mjs.map} +0 -0
  225. /package/dist/server/{chunk-C6FIJC7T.mjs.map → chunk-YUD7ONZG.mjs.map} +0 -0
  226. /package/dist/server/{loadPage-XR7ORQ2E.mjs.map → loadPage-IBX7FXGH.mjs.map} +0 -0
package/README.md CHANGED
@@ -101,7 +101,7 @@ The SDK provides a multi-layer resilience strategy to keep your site running eve
101
101
  1. **In-Memory Cache** - Fast cache with configurable TTL
102
102
  2. **Stale-If-Error** - Serves stale cached data when live fetch fails
103
103
  3. **Circuit Breaker** - Fail-fast after repeated failures (5 by default)
104
- 4. **Prebuild Fallback** - Static build artifacts as last resort
104
+ 4. **Prebuild Fallback** - Static build artifacts as last resort (site, pages, entries, navigation, forms)
105
105
  5. **Retry with Backoff** - Automatic retry for transient errors
106
106
 
107
107
  **Basic Configuration:**
@@ -960,6 +960,125 @@ Blocks can automatically load their data (e.g., blog posts, products) if they ha
960
960
  />
961
961
  ```
962
962
 
963
+ ## Image Resolution
964
+
965
+ Resolve `Media` objects to optimized image URLs. Essential for custom blocks that display images.
966
+
967
+ ### Basic Usage
968
+
969
+ ```tsx
970
+ import { resolveImageUrl, ImagePresets } from '@riverbankcms/sdk/rendering';
971
+ import type { Media } from '@riverbankcms/sdk/rendering';
972
+
973
+ function MyCustomBlock({ content }: { content: { image: Media } }) {
974
+ // Use a preset for common sizes
975
+ const imageUrl = resolveImageUrl(content.image, ImagePresets.card);
976
+
977
+ return <img src={imageUrl} alt={content.image.alt ?? ''} />;
978
+ }
979
+ ```
980
+
981
+ ### Image Presets
982
+
983
+ Use presets for consistent, optimized image sizes:
984
+
985
+ ```tsx
986
+ import { resolveImageUrl, ImagePresets } from '@riverbankcms/sdk/rendering';
987
+
988
+ // Thumbnail (200px width, 80% quality) - for lists, previews
989
+ resolveImageUrl(media, ImagePresets.thumbnail)
990
+
991
+ // Card (600px width, 80% quality) - for cards, grids
992
+ resolveImageUrl(media, ImagePresets.card)
993
+
994
+ // Hero (1200px width, 85% quality) - for above-fold content
995
+ resolveImageUrl(media, ImagePresets.hero)
996
+
997
+ // Full (1920px width, 85% quality) - for backgrounds, large displays
998
+ resolveImageUrl(media, ImagePresets.full)
999
+ ```
1000
+
1001
+ ### Custom Dimensions
1002
+
1003
+ Specify exact dimensions when presets don't fit:
1004
+
1005
+ ```tsx
1006
+ // Width only (height auto-calculated to maintain aspect ratio)
1007
+ resolveImageUrl(media, { width: 800, quality: 85 })
1008
+
1009
+ // Height only (width auto-calculated)
1010
+ resolveImageUrl(media, { height: 400, quality: 80 })
1011
+
1012
+ // Both dimensions
1013
+ resolveImageUrl(media, { width: 800, height: 600, quality: 85 })
1014
+ ```
1015
+
1016
+ ### Original Resolution
1017
+
1018
+ For rare cases like downloads or print, request the original:
1019
+
1020
+ ```tsx
1021
+ // Full resolution - no transforms applied
1022
+ resolveImageUrl(media, { original: true })
1023
+ ```
1024
+
1025
+ ### Complete Custom Block Example
1026
+
1027
+ ```tsx
1028
+ import { resolveImageUrl, ImagePresets, RichText } from '@riverbankcms/sdk/rendering';
1029
+ import type { SystemBlockComponentProps, Media } from '@riverbankcms/sdk/rendering';
1030
+
1031
+ type TeamMemberContent = {
1032
+ name: string;
1033
+ role?: string;
1034
+ photo?: Media;
1035
+ bio?: string;
1036
+ };
1037
+
1038
+ export function TeamMember({ content }: SystemBlockComponentProps<TeamMemberContent>) {
1039
+ const photoUrl = content.photo
1040
+ ? resolveImageUrl(content.photo, ImagePresets.card)
1041
+ : undefined;
1042
+
1043
+ return (
1044
+ <div className="flex items-start gap-6 p-6">
1045
+ {photoUrl && (
1046
+ <img
1047
+ src={photoUrl}
1048
+ alt={content.photo?.alt || content.name}
1049
+ className="h-24 w-24 rounded-full object-cover"
1050
+ />
1051
+ )}
1052
+ <div>
1053
+ <h3 className="text-xl font-bold">{content.name}</h3>
1054
+ {content.role && <p className="text-gray-600">{content.role}</p>}
1055
+ {content.bio && <RichText content={content.bio} />}
1056
+ </div>
1057
+ </div>
1058
+ );
1059
+ }
1060
+ ```
1061
+
1062
+ ### How It Works
1063
+
1064
+ Images stored in Supabase are served via the transform endpoint when dimensions are specified:
1065
+
1066
+ ```
1067
+ # Without transforms (original resolution - 3000px+)
1068
+ https://xxx.supabase.co/storage/v1/object/public/media/sites/abc/originals/photo.jpg
1069
+
1070
+ # With transforms (optimized - 600px)
1071
+ https://xxx.supabase.co/storage/v1/render/image/public/media/sites/abc/originals/photo.jpg?width=600&quality=80
1072
+ ```
1073
+
1074
+ This reduces image payload significantly (often 10x smaller) while maintaining visual quality.
1075
+
1076
+ ### Notes
1077
+
1078
+ - SVG files are returned as direct URLs (transforms don't apply to vectors)
1079
+ - External URLs (`src` field) are returned as-is (can't be transformed)
1080
+ - The `Media` type includes `storagePath`, `storageBucket`, `src`, `alt`, and transform metadata
1081
+
963
1082
  ## Metadata Generation
964
1083
 
965
1084
  Generate SEO-optimized metadata for Next.js pages from Riverbank CMS data.
@@ -1069,6 +1188,76 @@ resolutions.forEach(({ path, resolution }) => {
1069
1188
  });
1070
1189
  ```
1071
1190
 
1191
+ ## Forms
1192
+
1193
+ Fetch form definitions for rendering in your frontend. Forms include schema (field definitions) and settings (submit behavior, notifications).
1194
+
1195
+ ### Fetching Forms
1196
+
1197
+ ```tsx
1198
+ import { createRiverbankClient } from '@riverbankcms/sdk';
1199
+
1200
+ const client = createRiverbankClient({
1201
+ apiKey: process.env.RIVERBANK_API_KEY!,
1202
+ baseUrl: process.env.NEXT_PUBLIC_DASHBOARD_URL + '/api',
1203
+ });
1204
+
1205
+ // Fetch all forms for a site
1206
+ const { forms } = await client.getForms({
1207
+ siteId: 'your-site-id',
1208
+ });
1209
+
1210
+ // Each form includes:
1211
+ // - id: Form UUID
1212
+ // - slug: URL-friendly identifier
1213
+ // - name: Display name
1214
+ // - schema: Field definitions
1215
+ // - settings: Submit behavior, notifications
1216
+ ```
1217
+
1218
+ ### Forms with Prebuild Fallback
1219
+
1220
+ Forms support the same resilience features as other content. When prebuild is configured, forms are cached at build time and served as a fallback when the CMS is unavailable:
1221
+
1222
+ ```tsx
1223
+ const client = createRiverbankClient({
1224
+ apiKey: process.env.RIVERBANK_API_KEY!,
1225
+ baseUrl: process.env.RIVERBANK_BASE_URL!,
1226
+ resilience: {
1227
+ prebuildDir: '.riverbank-cache', // Forms are cached here
1228
+ },
1229
+ });
1230
+
1231
+ // If CMS is down, cached forms are returned
1232
+ const { forms } = await client.getForms({ siteId });
1233
+ ```
1234
+
1235
+ Note: While forms can be rendered from cache during CMS outages, form submissions will fail since they require the live API.
1236
+
1237
+ ### Rendering Forms
1238
+
1239
+ Forms provide schema and settings for building form UI:
1240
+
1241
+ ```tsx
1242
+ function DynamicForm({ form }) {
1243
+ const handleSubmit = async (data) => {
1244
+ await fetch('/api/forms/submit', {
1245
+ method: 'POST',
1246
+ body: JSON.stringify({ formId: form.id, data }),
1247
+ });
1248
+ };
1249
+
1250
+ return (
1251
+ <form onSubmit={handleSubmit}>
1252
+ {form.schema.fields.map((field) => (
1253
+ <FormField key={field.name} field={field} />
1254
+ ))}
1255
+ <button type="submit">Submit</button>
1256
+ </form>
1257
+ );
1258
+ }
1259
+ ```
1260
+
1072
1261
  ## Analytics
1073
1262
 
1074
1263
  Track page views, CTA clicks, form submissions, and custom events.
@@ -2584,7 +2773,7 @@ export default defineConfig({
2584
2773
 
2585
2774
  ## CLI
2586
2775
 
2587
- The SDK includes a CLI for syncing your local config to the dashboard.
2776
+ The SDK includes a CLI for syncing configuration and content between your local environment and the CMS.
2588
2777
 
2589
2778
  ### push-config
2590
2779
 
@@ -2616,6 +2805,113 @@ npx riverbankcms push-config \
2616
2805
  --dashboard https://www.riverbankcms.com
2617
2806
  ```
2618
2807
 
2808
+ ### pull
2809
+
2810
+ Download content from the CMS to local JSON files:
2811
+
2812
+ ```bash
2813
+ npx riverbankcms pull [scope] [type]
2814
+ ```
2815
+
2816
+ **Scopes:**
2817
+
2818
+ | Scope | Description |
2819
+ |-------|-------------|
2820
+ | (none) / `all` | Pull all content types |
2821
+ | `entries` | Pull all entries (or specific type with second argument) |
2822
+ | `pages` | Pull all pages |
2823
+ | `navigation` | Pull navigation menus |
2824
+ | `settings` | Pull site settings |
2825
+ | `forms` | Pull form definitions |
2826
+
2827
+ **Examples:**
2828
+
2829
+ ```bash
2830
+ # Pull all content
2831
+ npx riverbankcms pull
2832
+
2833
+ # Pull only forms
2834
+ npx riverbankcms pull forms
2835
+
2836
+ # Pull entries for a specific content type
2837
+ npx riverbankcms pull entries blog-post
2838
+
2839
+ # Pull from remote environment
2840
+ npx riverbankcms pull --remote
2841
+
2842
+ # Sync media files between environments
2843
+ npx riverbankcms pull --remote --sync-media
2844
+ ```
2845
+
2846
+ **Output Structure:**
2847
+
2848
+ ```
2849
+ content/
2850
+ ├── entries/
2851
+ │ └── {content-type}.json
2852
+ ├── pages/
2853
+ │ └── {identifier}.json
2854
+ ├── forms/
2855
+ │ └── {slug}.json
2856
+ ├── navigation.json
2857
+ ├── settings.json
2858
+ └── .meta/
2859
+ └── {entity}.json # Timestamps for sync detection
2860
+ ```
2861
+
2862
+ ### push
2863
+
2864
+ Push local content to the CMS with diff-based sync:
2865
+
2866
+ ```bash
2867
+ npx riverbankcms push [scope] [type]
2868
+ ```
2869
+
2870
+ **Scopes:**
2871
+
2872
+ | Scope | Description |
2873
+ |-------|-------------|
2874
+ | (none) / `all` | Push all content types |
2875
+ | `entries` | Push all entries (or specific type with second argument) |
2876
+ | `pages` | Push pages with blocks |
2877
+ | `navigation` | Push navigation menus |
2878
+ | `forms` | Push form definitions |
2879
+
2880
+ **Options:**
2881
+
2882
+ | Option | Description |
2883
+ |--------|-------------|
2884
+ | `--dry-run` | Show what would be pushed without making changes |
2885
+ | `--yes` | Skip confirmation (required for `--remote`) |
2886
+ | `--force` | Push even if remote is newer |
2887
+ | `--json-diff` | Output JSON diff (`summary` or `full`) |
2888
+
2889
+ **Examples:**
2890
+
2891
+ ```bash
2892
+ # Preview changes (dry run)
2893
+ npx riverbankcms push --dry-run
2894
+
2895
+ # Push all content
2896
+ npx riverbankcms push
2897
+
2898
+ # Push only forms
2899
+ npx riverbankcms push forms
2900
+
2901
+ # Push to production with confirmation bypass
2902
+ npx riverbankcms push --remote --yes
2903
+
2904
+ # Get JSON diff for automation
2905
+ npx riverbankcms push --dry-run --json-diff=summary
2906
+ ```
2907
+
2908
+ **Sync Behavior:**
2909
+
2910
+ - **Creates** new content if identifier/slug doesn't exist
2911
+ - **Updates** existing content based on diff
2912
+ - **Never deletes** - removing from local doesn't delete from CMS
2913
+ - **Stale detection** - warns if remote changed since last pull (use `--force` to override)
2914
+
2619
2915
  ## Next.js Catch-All Page Factory
2620
2916
 
2621
2917
  The SDK provides a `createCatchAllPage()` factory that dramatically reduces boilerplate for Next.js catch-all routes. It handles page/entry routing, preview mode, metadata generation, and error handling in ~10 lines.