astro-tractstack 2.0.0-rc.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 (427) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +56 -0
  3. package/astro.d.ts +64 -0
  4. package/bin/create-tractstack.js +483 -0
  5. package/dist/config.js +80 -0
  6. package/dist/index.js +2129 -0
  7. package/package.json +89 -0
  8. package/templates/artpacks/kCz/captainBreakfast_1080px.webp +0 -0
  9. package/templates/artpacks/kCz/captainBreakfast_1920px.webp +0 -0
  10. package/templates/artpacks/kCz/captainBreakfast_600px.webp +0 -0
  11. package/templates/artpacks/kCz/cleanDrips_1080px.webp +0 -0
  12. package/templates/artpacks/kCz/cleanDrips_1920px.webp +0 -0
  13. package/templates/artpacks/kCz/cleanDrips_600px.webp +0 -0
  14. package/templates/artpacks/kCz/crispwaves_1080px.webp +0 -0
  15. package/templates/artpacks/kCz/crispwaves_1920px.webp +0 -0
  16. package/templates/artpacks/kCz/crispwaves_600px.webp +0 -0
  17. package/templates/artpacks/kCz/dragonSkin_1080px.webp +0 -0
  18. package/templates/artpacks/kCz/dragonSkin_1920px.webp +0 -0
  19. package/templates/artpacks/kCz/dragonSkin_600px.webp +0 -0
  20. package/templates/artpacks/kCz/dragon_1080px.webp +0 -0
  21. package/templates/artpacks/kCz/dragon_1920px.webp +0 -0
  22. package/templates/artpacks/kCz/dragon_600px.webp +0 -0
  23. package/templates/artpacks/kCz/nightcity_1080px.webp +0 -0
  24. package/templates/artpacks/kCz/nightcity_1920px.webp +0 -0
  25. package/templates/artpacks/kCz/nightcity_600px.webp +0 -0
  26. package/templates/artpacks/kCz/pattern1_1080px.webp +0 -0
  27. package/templates/artpacks/kCz/pattern1_1920px.webp +0 -0
  28. package/templates/artpacks/kCz/pattern1_600px.webp +0 -0
  29. package/templates/artpacks/kCz/pattern2_1080px.webp +0 -0
  30. package/templates/artpacks/kCz/pattern2_1920px.webp +0 -0
  31. package/templates/artpacks/kCz/pattern2_600px.webp +0 -0
  32. package/templates/artpacks/kCz/skindrips_1080px.webp +0 -0
  33. package/templates/artpacks/kCz/skindrips_1920px.webp +0 -0
  34. package/templates/artpacks/kCz/skindrips_600px.webp +0 -0
  35. package/templates/artpacks/kCz/slimetime_1080px.webp +0 -0
  36. package/templates/artpacks/kCz/slimetime_1920px.webp +0 -0
  37. package/templates/artpacks/kCz/slimetime_600px.webp +0 -0
  38. package/templates/artpacks/kCz/snake_1080px.webp +0 -0
  39. package/templates/artpacks/kCz/snake_1920px.webp +0 -0
  40. package/templates/artpacks/kCz/snake_600px.webp +0 -0
  41. package/templates/artpacks/kCz/toxicshock_1080px.webp +0 -0
  42. package/templates/artpacks/kCz/toxicshock_1920px.webp +0 -0
  43. package/templates/artpacks/kCz/toxicshock_600px.webp +0 -0
  44. package/templates/artpacks/kCz/tractstack_1080px.webp +0 -0
  45. package/templates/artpacks/kCz/tractstack_1920px.webp +0 -0
  46. package/templates/artpacks/kCz/tractstack_600px.webp +0 -0
  47. package/templates/artpacks/kCz/tripdrips_1080px.webp +0 -0
  48. package/templates/artpacks/kCz/tripdrips_1920px.webp +0 -0
  49. package/templates/artpacks/kCz/tripdrips_600px.webp +0 -0
  50. package/templates/artpacks/kCz/wavedrips_1080px.webp +0 -0
  51. package/templates/artpacks/kCz/wavedrips_1920px.webp +0 -0
  52. package/templates/artpacks/kCz/wavedrips_600px.webp +0 -0
  53. package/templates/artpacks/t8k/beach_1080px.webp +0 -0
  54. package/templates/artpacks/t8k/beach_1920px.webp +0 -0
  55. package/templates/artpacks/t8k/beach_600px.webp +0 -0
  56. package/templates/artpacks/t8k/blast_1080px.webp +0 -0
  57. package/templates/artpacks/t8k/blast_1920px.webp +0 -0
  58. package/templates/artpacks/t8k/blast_600px.webp +0 -0
  59. package/templates/artpacks/t8k/bokeh_1080px.webp +0 -0
  60. package/templates/artpacks/t8k/bokeh_1920px.webp +0 -0
  61. package/templates/artpacks/t8k/bokeh_600px.webp +0 -0
  62. package/templates/artpacks/t8k/cartoon_1080px.webp +0 -0
  63. package/templates/artpacks/t8k/cartoon_1920px.webp +0 -0
  64. package/templates/artpacks/t8k/cartoon_600px.webp +0 -0
  65. package/templates/artpacks/t8k/darkeggshell_1080px.webp +0 -0
  66. package/templates/artpacks/t8k/darkeggshell_1920px.webp +0 -0
  67. package/templates/artpacks/t8k/darkeggshell_600px.webp +0 -0
  68. package/templates/artpacks/t8k/explosion_1080px.webp +0 -0
  69. package/templates/artpacks/t8k/explosion_1920px.webp +0 -0
  70. package/templates/artpacks/t8k/explosion_600px.webp +0 -0
  71. package/templates/artpacks/t8k/floral_1080px.webp +0 -0
  72. package/templates/artpacks/t8k/floral_1920px.webp +0 -0
  73. package/templates/artpacks/t8k/floral_600px.webp +0 -0
  74. package/templates/artpacks/t8k/flower_1080px.webp +0 -0
  75. package/templates/artpacks/t8k/flower_1920px.webp +0 -0
  76. package/templates/artpacks/t8k/flower_600px.webp +0 -0
  77. package/templates/artpacks/t8k/foliage_1080px.webp +0 -0
  78. package/templates/artpacks/t8k/foliage_1920px.webp +0 -0
  79. package/templates/artpacks/t8k/foliage_600px.webp +0 -0
  80. package/templates/artpacks/t8k/mist_1080px.webp +0 -0
  81. package/templates/artpacks/t8k/mist_1920px.webp +0 -0
  82. package/templates/artpacks/t8k/mist_600px.webp +0 -0
  83. package/templates/artpacks/t8k/portal_1080px.webp +0 -0
  84. package/templates/artpacks/t8k/portal_1920px.webp +0 -0
  85. package/templates/artpacks/t8k/portal_600px.webp +0 -0
  86. package/templates/artpacks/t8k/storytime_1080px.webp +0 -0
  87. package/templates/artpacks/t8k/storytime_1920px.webp +0 -0
  88. package/templates/artpacks/t8k/storytime_600px.webp +0 -0
  89. package/templates/artpacks/t8k/tacky_1080px.webp +0 -0
  90. package/templates/artpacks/t8k/tacky_1920px.webp +0 -0
  91. package/templates/artpacks/t8k/tacky_600px.webp +0 -0
  92. package/templates/artpacks/t8k/wallpaper_1080px.webp +0 -0
  93. package/templates/artpacks/t8k/wallpaper_1920px.webp +0 -0
  94. package/templates/artpacks/t8k/wallpaper_600px.webp +0 -0
  95. package/templates/brand/favicon.ico +0 -0
  96. package/templates/brand/logo.svg +19 -0
  97. package/templates/brand/static.jpg +0 -0
  98. package/templates/brand/wordmark.svg +4 -0
  99. package/templates/css/custom.css +51 -0
  100. package/templates/css/frontend.css +3519 -0
  101. package/templates/css/storykeep.css +92872 -0
  102. package/templates/custom/minimal/CodeHook.astro +53 -0
  103. package/templates/custom/minimal/CustomRoutes.astro +46 -0
  104. package/templates/custom/with-examples/CodeHook.astro +49 -0
  105. package/templates/custom/with-examples/CustomHero.astro +13 -0
  106. package/templates/custom/with-examples/CustomRoutes.astro +39 -0
  107. package/templates/custom/with-examples/pages/Collections.astro +110 -0
  108. package/templates/env.example +8 -0
  109. package/templates/fonts/Inter-Black.woff2 +0 -0
  110. package/templates/fonts/Inter-Bold.woff2 +0 -0
  111. package/templates/fonts/Inter-Regular.woff2 +0 -0
  112. package/templates/icons/h2.svg +1 -0
  113. package/templates/icons/h3.svg +1 -0
  114. package/templates/icons/h4.svg +1 -0
  115. package/templates/icons/h5.svg +1 -0
  116. package/templates/icons/image.svg +7 -0
  117. package/templates/icons/text.svg +6 -0
  118. package/templates/socials/codepen.svg +1 -0
  119. package/templates/socials/discord.svg +1 -0
  120. package/templates/socials/facebook.svg +1 -0
  121. package/templates/socials/github.svg +1 -0
  122. package/templates/socials/instagram.svg +1 -0
  123. package/templates/socials/linkedin.svg +1 -0
  124. package/templates/socials/mail.svg +1 -0
  125. package/templates/socials/rumble.svg +1 -0
  126. package/templates/socials/tiktok.svg +1 -0
  127. package/templates/socials/twitch.svg +1 -0
  128. package/templates/socials/twitter.svg +1 -0
  129. package/templates/socials/x.svg +1 -0
  130. package/templates/socials/youtube.svg +1 -0
  131. package/templates/src/client/analytics-events.ts +213 -0
  132. package/templates/src/client/belief-events.ts +205 -0
  133. package/templates/src/client/sse.ts +667 -0
  134. package/templates/src/components/Footer.astro +246 -0
  135. package/templates/src/components/Fragment.astro +70 -0
  136. package/templates/src/components/Header.astro +458 -0
  137. package/templates/src/components/Menu.tsx +196 -0
  138. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +692 -0
  139. package/templates/src/components/codehooks/BunnyVideoWrapper.astro +78 -0
  140. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +1020 -0
  141. package/templates/src/components/codehooks/EpinetTableView.tsx +594 -0
  142. package/templates/src/components/codehooks/EpinetWrapper.tsx +424 -0
  143. package/templates/src/components/codehooks/FeaturedContent.astro +273 -0
  144. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +738 -0
  145. package/templates/src/components/codehooks/ListContent.astro +460 -0
  146. package/templates/src/components/codehooks/ListContentSetup.tsx +649 -0
  147. package/templates/src/components/codehooks/SankeyDiagram.tsx +359 -0
  148. package/templates/src/components/compositor/Compositor.tsx +144 -0
  149. package/templates/src/components/compositor/Node.tsx +415 -0
  150. package/templates/src/components/compositor/NodeWithGuid.tsx +25 -0
  151. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +87 -0
  152. package/templates/src/components/compositor/elements/Belief.tsx +148 -0
  153. package/templates/src/components/compositor/elements/BgImage.tsx +118 -0
  154. package/templates/src/components/compositor/elements/BgVisualBreak.tsx +102 -0
  155. package/templates/src/components/compositor/elements/BunnyVideo.tsx +63 -0
  156. package/templates/src/components/compositor/elements/IdentifyAs.tsx +66 -0
  157. package/templates/src/components/compositor/elements/PlayButton.tsx +19 -0
  158. package/templates/src/components/compositor/elements/SignUp.tsx +179 -0
  159. package/templates/src/components/compositor/elements/Svg.tsx +33 -0
  160. package/templates/src/components/compositor/elements/ToggleBelief.tsx +36 -0
  161. package/templates/src/components/compositor/elements/YouTubeWrapper.tsx +33 -0
  162. package/templates/src/components/compositor/nodes/BgPaneWrapper.tsx +35 -0
  163. package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +189 -0
  164. package/templates/src/components/compositor/nodes/Markdown.tsx +179 -0
  165. package/templates/src/components/compositor/nodes/Pane.tsx +277 -0
  166. package/templates/src/components/compositor/nodes/Pane_eraser.tsx +69 -0
  167. package/templates/src/components/compositor/nodes/Pane_layout.tsx +77 -0
  168. package/templates/src/components/compositor/nodes/RenderChildren.tsx +19 -0
  169. package/templates/src/components/compositor/nodes/StoryFragment.tsx +35 -0
  170. package/templates/src/components/compositor/nodes/TagElement.tsx +14 -0
  171. package/templates/src/components/compositor/nodes/Widget.tsx +115 -0
  172. package/templates/src/components/compositor/nodes/tagElements/NodeA.tsx +4 -0
  173. package/templates/src/components/compositor/nodes/tagElements/NodeA_eraser.tsx +26 -0
  174. package/templates/src/components/compositor/nodes/tagElements/NodeAnchorComponent.tsx +248 -0
  175. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +684 -0
  176. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_eraser.tsx +62 -0
  177. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_insert.tsx +120 -0
  178. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_settings.tsx +62 -0
  179. package/templates/src/components/compositor/nodes/tagElements/NodeButton.tsx +5 -0
  180. package/templates/src/components/compositor/nodes/tagElements/NodeButton_eraser.tsx +26 -0
  181. package/templates/src/components/compositor/nodes/tagElements/NodeImg.tsx +28 -0
  182. package/templates/src/components/compositor/nodes/tagElements/NodeText.tsx +18 -0
  183. package/templates/src/components/compositor/nodes/tagElements/TabIndicator.tsx +51 -0
  184. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +128 -0
  185. package/templates/src/components/compositor/preview/ListContentPreview.tsx +213 -0
  186. package/templates/src/components/compositor/preview/OgImagePreview.tsx +223 -0
  187. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +199 -0
  188. package/templates/src/components/compositor/preview/PanesPreviewGenerator.tsx +123 -0
  189. package/templates/src/components/compositor/preview/VisualBreakPreview.tsx +154 -0
  190. package/templates/src/components/edit/Header.tsx +181 -0
  191. package/templates/src/components/edit/PanelSwitch.tsx +446 -0
  192. package/templates/src/components/edit/SettingsPanel.tsx +70 -0
  193. package/templates/src/components/edit/ToolBar.tsx +101 -0
  194. package/templates/src/components/edit/ToolMode.tsx +121 -0
  195. package/templates/src/components/edit/context/ContextPaneConfig.tsx +91 -0
  196. package/templates/src/components/edit/context/ContextPaneConfig_slug.tsx +174 -0
  197. package/templates/src/components/edit/context/ContextPaneConfig_title.tsx +186 -0
  198. package/templates/src/components/edit/pane/AddPanePanel.tsx +136 -0
  199. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +470 -0
  200. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +264 -0
  201. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +623 -0
  202. package/templates/src/components/edit/pane/AddPanePanel_newAICopy.tsx +107 -0
  203. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +217 -0
  204. package/templates/src/components/edit/pane/AddPanePanel_newCopyMode.tsx +109 -0
  205. package/templates/src/components/edit/pane/AddPanePanel_newCustomCopy.tsx +39 -0
  206. package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +445 -0
  207. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +245 -0
  208. package/templates/src/components/edit/pane/PageGen.tsx +485 -0
  209. package/templates/src/components/edit/pane/PageGenSelector.tsx +238 -0
  210. package/templates/src/components/edit/pane/PageGenSpecial.tsx +362 -0
  211. package/templates/src/components/edit/pane/PageGen_preview.tsx +495 -0
  212. package/templates/src/components/edit/pane/PanePanel_impression.tsx +258 -0
  213. package/templates/src/components/edit/pane/PanePanel_path.tsx +268 -0
  214. package/templates/src/components/edit/pane/PanePanel_slug.tsx +219 -0
  215. package/templates/src/components/edit/pane/PanePanel_title.tsx +142 -0
  216. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +182 -0
  217. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +439 -0
  218. package/templates/src/components/edit/panels/StyleElementPanel.tsx +177 -0
  219. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +349 -0
  220. package/templates/src/components/edit/panels/StyleElementPanel_remove.tsx +159 -0
  221. package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +320 -0
  222. package/templates/src/components/edit/panels/StyleImagePanel.tsx +460 -0
  223. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +296 -0
  224. package/templates/src/components/edit/panels/StyleImagePanel_remove.tsx +153 -0
  225. package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +312 -0
  226. package/templates/src/components/edit/panels/StyleLiElementPanel.tsx +273 -0
  227. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +301 -0
  228. package/templates/src/components/edit/panels/StyleLiElementPanel_remove.tsx +132 -0
  229. package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +313 -0
  230. package/templates/src/components/edit/panels/StyleLinkPanel.tsx +346 -0
  231. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +265 -0
  232. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +240 -0
  233. package/templates/src/components/edit/panels/StyleLinkPanel_remove.tsx +94 -0
  234. package/templates/src/components/edit/panels/StyleLinkPanel_update.tsx +110 -0
  235. package/templates/src/components/edit/panels/StyleParentPanel.tsx +263 -0
  236. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +275 -0
  237. package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +112 -0
  238. package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +87 -0
  239. package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +141 -0
  240. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +428 -0
  241. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +292 -0
  242. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +190 -0
  243. package/templates/src/components/edit/panels/StyleWidgetPanel_remove.tsx +152 -0
  244. package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +308 -0
  245. package/templates/src/components/edit/state/SaveModal.tsx +811 -0
  246. package/templates/src/components/edit/state/StylesMemory.tsx +310 -0
  247. package/templates/src/components/edit/storyfragment/StoryFragmentConfigPanel.tsx +289 -0
  248. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_menu.tsx +320 -0
  249. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +888 -0
  250. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +269 -0
  251. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_title.tsx +190 -0
  252. package/templates/src/components/edit/widgets/BeliefWidget.tsx +183 -0
  253. package/templates/src/components/edit/widgets/BunnyWidget.tsx +134 -0
  254. package/templates/src/components/edit/widgets/IdentifyAsWidget.tsx +193 -0
  255. package/templates/src/components/edit/widgets/SignupWidget.tsx +177 -0
  256. package/templates/src/components/edit/widgets/ToggleWidget.tsx +152 -0
  257. package/templates/src/components/edit/widgets/YouTubeWidget.tsx +65 -0
  258. package/templates/src/components/fields/ActionBuilderTimeSelector.tsx +353 -0
  259. package/templates/src/components/fields/ArtpackImage.tsx +480 -0
  260. package/templates/src/components/fields/BackgroundImage.tsx +530 -0
  261. package/templates/src/components/fields/BackgroundImageWrapper.tsx +192 -0
  262. package/templates/src/components/fields/BooleanParam.tsx +67 -0
  263. package/templates/src/components/fields/BunnyMomentSelector.tsx +56 -0
  264. package/templates/src/components/fields/ColorPickerCombo.tsx +284 -0
  265. package/templates/src/components/fields/ImageUpload.tsx +405 -0
  266. package/templates/src/components/fields/MultiParam.tsx +75 -0
  267. package/templates/src/components/fields/PaneBreakCollectionSelector.tsx +97 -0
  268. package/templates/src/components/fields/PaneBreakShapeSelector.tsx +134 -0
  269. package/templates/src/components/fields/SelectedTailwindClass.tsx +44 -0
  270. package/templates/src/components/fields/SingleParam.tsx +73 -0
  271. package/templates/src/components/fields/ViewportComboBox.tsx +252 -0
  272. package/templates/src/components/form/ActionBuilderField.tsx +282 -0
  273. package/templates/src/components/form/ActionBuilderSlugSelector.tsx +182 -0
  274. package/templates/src/components/form/BooleanToggle.tsx +94 -0
  275. package/templates/src/components/form/ColorPicker.tsx +153 -0
  276. package/templates/src/components/form/DateTimeInput.tsx +638 -0
  277. package/templates/src/components/form/EnumSelect.tsx +88 -0
  278. package/templates/src/components/form/FileUpload.tsx +465 -0
  279. package/templates/src/components/form/MagicPathBuilder.tsx +546 -0
  280. package/templates/src/components/form/NumberInput.tsx +101 -0
  281. package/templates/src/components/form/ParagraphArrayInput.tsx +207 -0
  282. package/templates/src/components/form/StringArrayInput.tsx +163 -0
  283. package/templates/src/components/form/StringInput.tsx +88 -0
  284. package/templates/src/components/form/UnsavedChangesBar.tsx +295 -0
  285. package/templates/src/components/form/advanced/APIConfigSection.tsx +69 -0
  286. package/templates/src/components/form/advanced/AuthConfigSection.tsx +97 -0
  287. package/templates/src/components/form/brand/BrandAssetsSection.tsx +93 -0
  288. package/templates/src/components/form/brand/BrandColorsSection.tsx +201 -0
  289. package/templates/src/components/form/brand/SEOSection.tsx +101 -0
  290. package/templates/src/components/form/brand/SiteConfigSection.tsx +61 -0
  291. package/templates/src/components/form/brand/SocialLinksSection.tsx +393 -0
  292. package/templates/src/components/profile/ProfileConsent.tsx +65 -0
  293. package/templates/src/components/profile/ProfileCreate.tsx +462 -0
  294. package/templates/src/components/profile/ProfileEdit.tsx +409 -0
  295. package/templates/src/components/profile/ProfileSwitch.tsx +255 -0
  296. package/templates/src/components/profile/ProfileUnlock.tsx +221 -0
  297. package/templates/src/components/storykeep/Dashboard.tsx +160 -0
  298. package/templates/src/components/storykeep/Dashboard_Activity.tsx +56 -0
  299. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +165 -0
  300. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +451 -0
  301. package/templates/src/components/storykeep/Dashboard_Branding.tsx +95 -0
  302. package/templates/src/components/storykeep/Dashboard_Content.tsx +191 -0
  303. package/templates/src/components/storykeep/controls/UsageCell.tsx +71 -0
  304. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +378 -0
  305. package/templates/src/components/storykeep/controls/content/BeliefTable.tsx +329 -0
  306. package/templates/src/components/storykeep/controls/content/ContentBrowser.tsx +385 -0
  307. package/templates/src/components/storykeep/controls/content/ContentSummary.tsx +149 -0
  308. package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +397 -0
  309. package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +260 -0
  310. package/templates/src/components/storykeep/controls/content/ManageContent.tsx +439 -0
  311. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +239 -0
  312. package/templates/src/components/storykeep/controls/content/MenuTable.tsx +332 -0
  313. package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +724 -0
  314. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +355 -0
  315. package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +222 -0
  316. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +482 -0
  317. package/templates/src/components/storykeep/state/BrandingWrapper.tsx +42 -0
  318. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +350 -0
  319. package/templates/src/components/storykeep/widgets/ResponsiveLine.tsx +319 -0
  320. package/templates/src/components/storykeep/widgets/Wizard.tsx +278 -0
  321. package/templates/src/components/tenant/RegistrationForm.tsx +447 -0
  322. package/templates/src/components/widgets/BunnyVideoHero.astro +775 -0
  323. package/templates/src/components/widgets/Impression.tsx +102 -0
  324. package/templates/src/components/widgets/ImpressionWrapper.tsx +214 -0
  325. package/templates/src/constants/beliefs.ts +61 -0
  326. package/templates/src/constants/brandThemes.ts +133 -0
  327. package/templates/src/constants/prompts.json +55 -0
  328. package/templates/src/constants/shapes.ts +556 -0
  329. package/templates/src/constants/stopWords.ts +116 -0
  330. package/templates/src/constants/tailwindColors.json +344 -0
  331. package/templates/src/constants.ts +274 -0
  332. package/templates/src/hooks/useFormState.ts +203 -0
  333. package/templates/src/layouts/Layout.astro +290 -0
  334. package/templates/src/lib/session.ts +126 -0
  335. package/templates/src/lib/storyData.ts +56 -0
  336. package/templates/src/middleware.ts +52 -0
  337. package/templates/src/pages/404.astro +54 -0
  338. package/templates/src/pages/[...slug]/edit.astro +216 -0
  339. package/templates/src/pages/[...slug].astro +148 -0
  340. package/templates/src/pages/api/auth/decode.ts +101 -0
  341. package/templates/src/pages/api/auth/login.ts +122 -0
  342. package/templates/src/pages/api/auth/logout.ts +37 -0
  343. package/templates/src/pages/api/auth/profile.ts +76 -0
  344. package/templates/src/pages/api/orphan-analysis.ts +106 -0
  345. package/templates/src/pages/api/tailwind.ts +116 -0
  346. package/templates/src/pages/collections/[param1].astro +65 -0
  347. package/templates/src/pages/context/[...contextSlug]/edit.astro +207 -0
  348. package/templates/src/pages/context/[...contextSlug].astro +161 -0
  349. package/templates/src/pages/llms.txt.ts +122 -0
  350. package/templates/src/pages/maint.astro +183 -0
  351. package/templates/src/pages/media/[...slug].astro +67 -0
  352. package/templates/src/pages/robots.txt.ts +36 -0
  353. package/templates/src/pages/sandbox/activate.astro +258 -0
  354. package/templates/src/pages/sandbox/register.astro +44 -0
  355. package/templates/src/pages/sandbox/success.astro +179 -0
  356. package/templates/src/pages/sitemap.xml.ts +119 -0
  357. package/templates/src/pages/storykeep/advanced.astro +69 -0
  358. package/templates/src/pages/storykeep/branding.astro +57 -0
  359. package/templates/src/pages/storykeep/content.astro +71 -0
  360. package/templates/src/pages/storykeep/init.astro +36 -0
  361. package/templates/src/pages/storykeep/login.astro +266 -0
  362. package/templates/src/pages/storykeep/logout.astro +84 -0
  363. package/templates/src/pages/storykeep/profile.astro +98 -0
  364. package/templates/src/pages/storykeep.astro +81 -0
  365. package/templates/src/stores/analytics.ts +171 -0
  366. package/templates/src/stores/backend.ts +16 -0
  367. package/templates/src/stores/navigation.ts +149 -0
  368. package/templates/src/stores/nodes.ts +2390 -0
  369. package/templates/src/stores/nodesHistory.ts +85 -0
  370. package/templates/src/stores/notificationSystem.ts +41 -0
  371. package/templates/src/stores/orphanAnalysis.ts +409 -0
  372. package/templates/src/stores/storykeep.ts +247 -0
  373. package/templates/src/types/astro.ts +86 -0
  374. package/templates/src/types/compositorTypes.ts +456 -0
  375. package/templates/src/types/formTypes.ts +281 -0
  376. package/templates/src/types/multiTenant.ts +77 -0
  377. package/templates/src/types/nodeProps.ts +66 -0
  378. package/templates/src/types/tractstack.ts +445 -0
  379. package/templates/src/utils/aai/getTitleSlug.ts +72 -0
  380. package/templates/src/utils/actions/actionButton.ts +101 -0
  381. package/templates/src/utils/actions/lispLexer.ts +57 -0
  382. package/templates/src/utils/actions/preParse_Action.ts +85 -0
  383. package/templates/src/utils/actions/preParse_Bunny.ts +50 -0
  384. package/templates/src/utils/actions/preParse_Clicked.ts +87 -0
  385. package/templates/src/utils/actions/preParse_Impression.ts +71 -0
  386. package/templates/src/utils/api/advancedConfig.ts +66 -0
  387. package/templates/src/utils/api/advancedHelpers.ts +134 -0
  388. package/templates/src/utils/api/beliefConfig.ts +87 -0
  389. package/templates/src/utils/api/beliefHelpers.ts +196 -0
  390. package/templates/src/utils/api/brandConfig.ts +126 -0
  391. package/templates/src/utils/api/brandHelpers.ts +155 -0
  392. package/templates/src/utils/api/fileHelpers.ts +306 -0
  393. package/templates/src/utils/api/menuConfig.ts +57 -0
  394. package/templates/src/utils/api/menuHelpers.ts +156 -0
  395. package/templates/src/utils/api/resourceConfig.ts +158 -0
  396. package/templates/src/utils/api/resourceHelpers.ts +72 -0
  397. package/templates/src/utils/api/tenantConfig.ts +97 -0
  398. package/templates/src/utils/api/tenantHelpers.ts +172 -0
  399. package/templates/src/utils/api.ts +183 -0
  400. package/templates/src/utils/auth.ts +150 -0
  401. package/templates/src/utils/backend.ts +243 -0
  402. package/templates/src/utils/compositor/TemplateMarkdowns.ts +118 -0
  403. package/templates/src/utils/compositor/TemplateNodes.ts +138 -0
  404. package/templates/src/utils/compositor/TemplatePanes.ts +100 -0
  405. package/templates/src/utils/compositor/allowInsert.ts +100 -0
  406. package/templates/src/utils/compositor/domHelpers.ts +37 -0
  407. package/templates/src/utils/compositor/handleClickEvent.ts +131 -0
  408. package/templates/src/utils/compositor/nodesHelper.ts +491 -0
  409. package/templates/src/utils/compositor/nodesMarkdownGenerator.ts +292 -0
  410. package/templates/src/utils/compositor/processMarkdown.ts +431 -0
  411. package/templates/src/utils/compositor/reduceNodesClassNames.ts +192 -0
  412. package/templates/src/utils/compositor/tailwindClasses.ts +1795 -0
  413. package/templates/src/utils/compositor/tailwindColors.ts +227 -0
  414. package/templates/src/utils/compositor/templateMarkdownStyles.ts +1265 -0
  415. package/templates/src/utils/compositor/typeGuards.ts +193 -0
  416. package/templates/src/utils/etl/extractor.ts +119 -0
  417. package/templates/src/utils/etl/index.ts +88 -0
  418. package/templates/src/utils/etl/loader.ts +36 -0
  419. package/templates/src/utils/etl/transformer.ts +286 -0
  420. package/templates/src/utils/helpers.ts +435 -0
  421. package/templates/src/utils/layout.ts +209 -0
  422. package/templates/src/utils/profileStorage.ts +306 -0
  423. package/templates/src/utils/useInterval.ts +27 -0
  424. package/templates/tailwind.config.cjs +169 -0
  425. package/utils/create-resolver.ts +10 -0
  426. package/utils/inject-files.ts +2140 -0
  427. package/utils/validate-config.ts +43 -0
@@ -0,0 +1,106 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const prerender = false;
4
+
5
+ export const GET: APIRoute = async ({ request }) => {
6
+ const goBackend =
7
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
8
+
9
+ try {
10
+ // Forward authentication cookies to the backend
11
+ const cookieHeader = request.headers.get('cookie') || '';
12
+
13
+ // Create abort controller for request timeout
14
+ const controller = new AbortController();
15
+ const timeoutId = setTimeout(() => controller.abort(), 30000); // 30s timeout for analysis
16
+
17
+ try {
18
+ const goResponse = await fetch(
19
+ `${goBackend}/api/v1/admin/orphan-analysis`,
20
+ {
21
+ method: 'GET',
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ Cookie: cookieHeader,
25
+ 'X-Tenant-ID': request.headers.get('X-Tenant-ID') || 'default',
26
+ Origin: request.headers.get('Origin') || 'http://localhost:4321',
27
+ },
28
+ signal: controller.signal,
29
+ }
30
+ );
31
+
32
+ clearTimeout(timeoutId);
33
+
34
+ if (!goResponse.ok) {
35
+ console.error(
36
+ 'Orphan Analysis API: Go backend error:',
37
+ goResponse.status
38
+ );
39
+
40
+ // Handle authentication errors
41
+ if (goResponse.status === 401 || goResponse.status === 403) {
42
+ return new Response(
43
+ JSON.stringify({
44
+ error: 'Authentication required',
45
+ status: 'error',
46
+ }),
47
+ {
48
+ status: goResponse.status,
49
+ headers: { 'Content-Type': 'application/json' },
50
+ }
51
+ );
52
+ }
53
+
54
+ return new Response(
55
+ JSON.stringify({
56
+ error: 'Backend error',
57
+ status: 'error',
58
+ }),
59
+ {
60
+ status: goResponse.status,
61
+ headers: { 'Content-Type': 'application/json' },
62
+ }
63
+ );
64
+ }
65
+
66
+ const responseData = await goResponse.json();
67
+
68
+ return new Response(JSON.stringify(responseData), {
69
+ status: 200,
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ 'Cache-Control': 'public, max-age=300', // Cache for 5 minutes
73
+ },
74
+ });
75
+ } catch (fetchError) {
76
+ clearTimeout(timeoutId);
77
+
78
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
79
+ console.error('Orphan analysis request timeout');
80
+ return new Response(
81
+ JSON.stringify({
82
+ error: 'Analysis timeout - this may indicate a large dataset',
83
+ status: 'error',
84
+ }),
85
+ {
86
+ status: 408,
87
+ headers: { 'Content-Type': 'application/json' },
88
+ }
89
+ );
90
+ }
91
+ throw fetchError;
92
+ }
93
+ } catch (error) {
94
+ console.error('Orphan Analysis API Proxy: Error:', error);
95
+ return new Response(
96
+ JSON.stringify({
97
+ error: 'Proxy error',
98
+ status: 'error',
99
+ }),
100
+ {
101
+ status: 500,
102
+ headers: { 'Content-Type': 'application/json' },
103
+ }
104
+ );
105
+ }
106
+ };
@@ -0,0 +1,116 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+ import { createTailwindcss } from '@mhsdesign/jit-browser-tailwindcss';
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+
6
+ export const POST: APIRoute = async ({ request }) => {
7
+ try {
8
+ const { dirtyPaneIds, dirtyClasses } = await request.json();
9
+
10
+ const tenantId =
11
+ request.headers.get('X-Tenant-ID') ||
12
+ import.meta.env.PUBLIC_TENANTID ||
13
+ 'default';
14
+ const isMultiTenant =
15
+ import.meta.env.PUBLIC_ENABLE_MULTI_TENANT === 'true' &&
16
+ tenantId !== 'default';
17
+
18
+ if (isMultiTenant) {
19
+ return new Response('CSS generation disabled in multi-tenant mode', {
20
+ status: 403,
21
+ });
22
+ }
23
+
24
+ // Read tailwind config from project root
25
+ const configPath = path.join(process.cwd(), 'tailwind.config.cjs');
26
+ const configContent = await fs.readFile(configPath, 'utf-8');
27
+ const tailwindConfig = new Function(
28
+ 'module',
29
+ 'exports',
30
+ configContent + '; return module.exports;'
31
+ )({ exports: {} }, {});
32
+
33
+ const goBackend =
34
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
35
+
36
+ // Authenticate with Go backend
37
+ const authResponse = await fetch(`${goBackend}/api/v1/auth/login`, {
38
+ method: 'POST',
39
+ headers: {
40
+ 'Content-Type': 'application/json',
41
+ 'X-Tenant-ID': tenantId,
42
+ },
43
+ body: JSON.stringify({
44
+ password: import.meta.env.ADMIN_PASSWORD || 'letmein',
45
+ }),
46
+ });
47
+
48
+ if (!authResponse.ok) {
49
+ throw new Error('Failed to authenticate with Go backend');
50
+ }
51
+
52
+ const { token } = await authResponse.json();
53
+
54
+ // Get classes from Go backend (includes whitelist + clean panes)
55
+ const classesResponse = await fetch(
56
+ `${goBackend}/api/v1/tailwind/classes`,
57
+ {
58
+ method: 'POST',
59
+ headers: {
60
+ 'Content-Type': 'application/json',
61
+ Authorization: `Bearer ${token}`,
62
+ 'X-Tenant-ID': tenantId,
63
+ },
64
+ body: JSON.stringify({ excludePaneIds: dirtyPaneIds || [] }),
65
+ }
66
+ );
67
+
68
+ if (!classesResponse.ok) {
69
+ throw new Error(
70
+ `Failed to get classes from Go backend: ${classesResponse.status}`
71
+ );
72
+ }
73
+
74
+ const { classes: cleanClasses } = await classesResponse.json();
75
+
76
+ // Combine clean classes from backend with dirty classes from frontend
77
+ const allClasses = [
78
+ ...new Set([...(cleanClasses || []), ...(dirtyClasses || [])]),
79
+ ];
80
+
81
+ // Generate CSS using JIT
82
+ const tailwindCss = createTailwindcss({ tailwindConfig });
83
+ const htmlContent = [`<span class="${allClasses.join(' ')}"></span>`];
84
+ const generatedCss = await tailwindCss.generateStylesFromContent(
85
+ `@tailwind base; @tailwind utilities;`,
86
+ htmlContent
87
+ );
88
+
89
+ // Return result (SaveModal will handle the update call logging)
90
+ return new Response(
91
+ JSON.stringify({
92
+ success: true,
93
+ classes: allClasses.length,
94
+ frontend: generatedCss.length,
95
+ stylesVer: Date.now(), // Simple version for demo
96
+ generatedCss, // Include actual CSS for potential update call
97
+ }),
98
+ {
99
+ status: 200,
100
+ headers: { 'Content-Type': 'application/json' },
101
+ }
102
+ );
103
+ } catch (error) {
104
+ console.error('Tailwind Error:', error);
105
+ return new Response(
106
+ JSON.stringify({
107
+ success: false,
108
+ error: error instanceof Error ? error.message : 'Unknown error',
109
+ }),
110
+ {
111
+ status: 500,
112
+ headers: { 'Content-Type': 'application/json' },
113
+ }
114
+ );
115
+ }
116
+ };
@@ -0,0 +1,65 @@
1
+ ---
2
+ import CustomRoutes, { routes } from '@/custom/CustomRoutes.astro';
3
+ import { preHealthCheck } from '@/utils/backend';
4
+ import type { ResourceNode } from '@/types/compositorTypes';
5
+
6
+ const tenantId =
7
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
8
+
9
+ const healthCheckRedirect = await preHealthCheck(tenantId);
10
+ if (healthCheckRedirect !== undefined) {
11
+ return healthCheckRedirect;
12
+ }
13
+
14
+ const { param1 } = Astro.params;
15
+ const route = `collections`;
16
+
17
+ // Check if route is enabled
18
+ if (!param1 || !routes[route]) {
19
+ return new Response(null, {
20
+ status: 404,
21
+ statusText: 'Not Found',
22
+ });
23
+ }
24
+
25
+ const CATEGORIES = [`collections`];
26
+
27
+ let resources = [];
28
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
29
+
30
+ try {
31
+ const resourcesResponse = await fetch(`${goBackend}/api/v1/nodes/resources`, {
32
+ method: 'POST',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ body: JSON.stringify({ categories: CATEGORIES }),
35
+ });
36
+
37
+ if (resourcesResponse.ok) {
38
+ const { resources: fetchedResources } = await resourcesResponse.json();
39
+ resources = fetchedResources || [];
40
+ }
41
+ } catch (error) {
42
+ console.error('Error fetching resources:', error);
43
+ return new Response(null, {
44
+ status: 500,
45
+ statusText: 'Internal Server Error',
46
+ });
47
+ }
48
+
49
+ // Check if the specific resource exists
50
+ const targetSlug = `${route}-${param1}`;
51
+ console.log(`check category vs categorySlug`, resources);
52
+ const resourceExists = resources.some(
53
+ (resource: ResourceNode) =>
54
+ resource.category === route && resource.slug === targetSlug
55
+ );
56
+
57
+ if (!resourceExists) {
58
+ return new Response(null, {
59
+ status: 404,
60
+ statusText: 'Not Found',
61
+ });
62
+ }
63
+ ---
64
+
65
+ <CustomRoutes route={route} slug={param1} resources={resources} />
@@ -0,0 +1,207 @@
1
+ ---
2
+ import { ulid } from 'ulid';
3
+ import Layout from '@/layouts/Layout.astro';
4
+ import Header from '@/components/Header.astro';
5
+ import { getFullContentMap } from '@/stores/analytics';
6
+ import { getBrandConfig } from '@/utils/api/brandConfig';
7
+ import { joinUrlPaths } from '@/utils/helpers';
8
+ import { handleFailedResponse } from '@/utils/backend';
9
+ import { components as codeHookComponents } from '@/custom/CodeHook.astro';
10
+ import StoryKeepHeader from '@/components/edit/Header';
11
+ import StoryKeepToolBar from '@/components/edit/ToolBar';
12
+ import StoryKeepToolMode from '@/components/edit/ToolMode';
13
+ import SettingsPanel from '@/components/edit/SettingsPanel';
14
+ import { Compositor } from '@/components/compositor/Compositor';
15
+ import { requireAdminOrEditor } from '@/utils/auth';
16
+ import { preHealthCheck } from '@/utils/backend';
17
+
18
+ const tenantId =
19
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
20
+
21
+ const healthCheckRedirect = await preHealthCheck(tenantId);
22
+ if (healthCheckRedirect !== undefined) {
23
+ return healthCheckRedirect;
24
+ }
25
+
26
+ const { contextSlug } = Astro.params;
27
+ if (!contextSlug) return Astro.redirect('/404');
28
+
29
+ // Authentication check - redirect to login if not authenticated
30
+ const authCheck = requireAdminOrEditor(Astro);
31
+ if (authCheck) {
32
+ return authCheck;
33
+ }
34
+
35
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
36
+
37
+ const brandConfig = await getBrandConfig(tenantId);
38
+ if (!brandConfig.SITE_INIT) {
39
+ return Astro.redirect('/storykeep');
40
+ }
41
+
42
+ let loadData;
43
+ let contextPane;
44
+ let title;
45
+ let contextPaneID;
46
+
47
+ // Handle create mode
48
+ if (contextSlug === 'create') {
49
+ // Create empty context pane in memory
50
+ const emptyContextPane = {
51
+ id: ulid(),
52
+ nodeType: 'Pane' as const,
53
+ parentId: null,
54
+ title: '',
55
+ slug: '',
56
+ isContextPane: true,
57
+ created: new Date(),
58
+ changed: new Date(),
59
+ isDecorative: false,
60
+ };
61
+
62
+ loadData = {
63
+ paneNodes: [emptyContextPane],
64
+ };
65
+
66
+ contextPane = emptyContextPane;
67
+ title = 'Create New Context Page - TractStack Editor';
68
+ contextPaneID = emptyContextPane.id;
69
+ } else {
70
+ // Existing backend fetch logic - use full-payload endpoint
71
+ const endpoint = `${goBackend}/api/v1/nodes/panes/slug/${contextSlug}/full-payload`;
72
+
73
+ try {
74
+ const response = await fetch(endpoint, {
75
+ headers: {
76
+ 'X-Tenant-ID': tenantId,
77
+ Cookie: Astro.request.headers.get('cookie') || '',
78
+ },
79
+ });
80
+
81
+ const failedResponse = await handleFailedResponse(
82
+ response,
83
+ goBackend,
84
+ tenantId,
85
+ Astro.url.pathname
86
+ );
87
+ if (failedResponse) {
88
+ return failedResponse;
89
+ }
90
+
91
+ loadData = await response.json();
92
+ } catch (error) {
93
+ console.error('Error fetching context pane full payload:', error);
94
+ return Astro.redirect(
95
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
96
+ );
97
+ }
98
+
99
+ // Extract data from the response (same pattern as storyfragment)
100
+ contextPane = loadData?.paneNodes?.at(0);
101
+ title = contextPane?.title || `Context Editor`;
102
+ contextPaneID = contextPane?.id;
103
+ }
104
+
105
+ const canonicalURL = `/context/${contextSlug}`;
106
+
107
+ // Extract dates if available
108
+ const pubDatetime = contextPane?.created
109
+ ? new Date(contextPane.created)
110
+ : undefined;
111
+ const modDatetime = contextPane?.changed ? new Date(contextPane.changed) : null;
112
+
113
+ // Social image from the context pane
114
+ const ogImage = contextPane?.socialImagePath
115
+ ? joinUrlPaths(brandConfig?.SITE_URL || ``, contextPane.socialImagePath)
116
+ : undefined;
117
+
118
+ const fullContentMap = await getFullContentMap(tenantId);
119
+ const urlParams: Record<string, string | boolean> = {};
120
+ for (const [key, value] of Astro.url.searchParams) {
121
+ urlParams[key] = value === '' ? true : value;
122
+ }
123
+ ---
124
+
125
+ <Layout
126
+ title={title}
127
+ slug={contextSlug}
128
+ canonicalURL={canonicalURL}
129
+ pubDatetime={pubDatetime}
130
+ modDatetime={modDatetime}
131
+ ogImage={ogImage}
132
+ brandConfig={brandConfig}
133
+ storyfragmentId={contextPaneID}
134
+ isEditor={true}
135
+ >
136
+ <!-- Standard Header (scrollable) -->
137
+ <Header
138
+ title={title}
139
+ slug={contextSlug}
140
+ brandConfig={brandConfig}
141
+ isContext={true}
142
+ isStoryKeep={true}
143
+ isEditable={false}
144
+ menu={null}
145
+ />
146
+
147
+ <!-- StoryKeep Editor Header (scroll-aware positioning) -->
148
+ <section
149
+ id="storykeepHeader"
150
+ role="banner"
151
+ class="z-101 bg-mywhite left-0 right-0 drop-shadow transition-all duration-200"
152
+ >
153
+ <StoryKeepHeader slug={contextSlug} isContext={true} client:only="react" />
154
+ </section>
155
+
156
+ <div class="flex min-h-screen">
157
+ <!-- Tool Navigation (mobile bottom, desktop side) -->
158
+ <StoryKeepToolMode isContext={true} client:only="react" />
159
+
160
+ <!-- Main Content Area -->
161
+ <main id="mainContent" class="relative flex-1">
162
+ <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
163
+ <div
164
+ class="h-fit min-h-screen"
165
+ style={{
166
+ backgroundImage:
167
+ 'repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(0,0,0,0.05) 10px, rgba(0,0,0,0.05) 20px)',
168
+ }}
169
+ >
170
+ <Compositor
171
+ id={contextPaneID}
172
+ nodes={loadData}
173
+ config={brandConfig}
174
+ fullContentMap={fullContentMap}
175
+ fullCanonicalURL={canonicalURL}
176
+ urlParams={urlParams}
177
+ availableCodeHooks={Object.keys(codeHookComponents)}
178
+ client:only="react"
179
+ />
180
+ </div>
181
+ </div>
182
+ </main>
183
+ </div>
184
+
185
+ <!-- Floating Controls (Settings Panel & HUD OR ToolBar) -->
186
+ <aside
187
+ id="settingsControls"
188
+ class="z-101 pointer-events-none fixed bottom-24 right-0 flex max-h-screen flex-col items-end gap-2 overflow-y-auto p-4 md:bottom-0"
189
+ >
190
+ <div class="pointer-events-auto">
191
+ <StoryKeepToolBar client:only="react" />
192
+ </div>
193
+ <div class="pointer-events-auto">
194
+ <SettingsPanel
195
+ config={brandConfig}
196
+ availableCodeHooks={['featured-content', 'list-content', 'bunny-video']}
197
+ client:only="react"
198
+ />
199
+ </div>
200
+ </aside>
201
+ </Layout>
202
+
203
+ <script>
204
+ import { setupLayoutObservers, setupLayoutStyles } from '@/utils/layout';
205
+ setupLayoutStyles();
206
+ setupLayoutObservers();
207
+ </script>
@@ -0,0 +1,161 @@
1
+ ---
2
+ import Layout from '@/layouts/Layout.astro';
3
+ import CodeHook from '@/custom/CodeHook.astro';
4
+ import { getBrandConfig } from '@/utils/api/brandConfig';
5
+ import { handleFailedResponse } from '@/utils/backend';
6
+ import { getFullContentMap } from '@/stores/analytics';
7
+ import { preHealthCheck } from '@/utils/backend';
8
+
9
+ const tenantId =
10
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
11
+
12
+ const healthCheckRedirect = await preHealthCheck(tenantId);
13
+ if (healthCheckRedirect !== undefined) {
14
+ return healthCheckRedirect;
15
+ }
16
+
17
+ const { contextSlug } = Astro.params || {};
18
+
19
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
20
+
21
+ // Get context pane data by slug
22
+ let contextPaneData;
23
+ try {
24
+ const response = await fetch(
25
+ `${goBackend}/api/v1/nodes/panes/slug/${contextSlug}`,
26
+ {
27
+ headers: {
28
+ 'X-Tenant-ID': tenantId,
29
+ },
30
+ }
31
+ );
32
+
33
+ const failedResponse = await handleFailedResponse(
34
+ response,
35
+ goBackend,
36
+ tenantId,
37
+ Astro.url.pathname
38
+ );
39
+ if (failedResponse) {
40
+ return failedResponse;
41
+ }
42
+
43
+ contextPaneData = await response.json();
44
+
45
+ // Verify this is actually a context pane
46
+ if (!contextPaneData.isContextPane) {
47
+ return new Response(null, {
48
+ status: 404,
49
+ statusText: 'Not Found - Not a context pane',
50
+ });
51
+ }
52
+ } catch (error) {
53
+ console.error('Error fetching context pane:', error);
54
+ return Astro.redirect(
55
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
56
+ );
57
+ }
58
+
59
+ const paneId = contextPaneData.id;
60
+ const paneTitle = contextPaneData.title || 'Context';
61
+ const codeHookTarget = contextPaneData.codeHookTarget || null;
62
+
63
+ // Get rendered fragment for the context pane
64
+ let fragmentData = '';
65
+ try {
66
+ const fragmentResponse = await fetch(
67
+ `${goBackend}/api/v1/fragments/panes/${paneId}/static`,
68
+ {
69
+ headers: {
70
+ 'X-Tenant-ID': tenantId,
71
+ },
72
+ }
73
+ );
74
+
75
+ if (fragmentResponse.ok) {
76
+ fragmentData = await fragmentResponse.text();
77
+ } else {
78
+ const failedFragmentResponse = await handleFailedResponse(
79
+ fragmentResponse,
80
+ goBackend,
81
+ tenantId,
82
+ Astro.url.pathname
83
+ );
84
+ if (failedFragmentResponse) {
85
+ return failedFragmentResponse;
86
+ }
87
+ }
88
+ } catch (error) {
89
+ console.error('Error fetching context fragment:', error);
90
+ return Astro.redirect(
91
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
92
+ );
93
+ }
94
+
95
+ // Get supporting data
96
+ const fullContentMap = await getFullContentMap(tenantId);
97
+ const brandConfig = await getBrandConfig(tenantId);
98
+
99
+ if (!brandConfig.SITE_INIT) {
100
+ return Astro.redirect('/storykeep');
101
+ }
102
+ ---
103
+
104
+ <Layout
105
+ title={paneTitle}
106
+ slug={contextSlug}
107
+ menu={null}
108
+ created={contextPaneData.created}
109
+ isContext={true}
110
+ isStoryKeep={false}
111
+ isEditable={true}
112
+ brandConfig={brandConfig}
113
+ storyfragmentId={paneId}
114
+ >
115
+ <main id="main-content" class="min-h-screen w-full">
116
+ <div
117
+ id={`pane-${paneId}`}
118
+ data-pane-id={paneId}
119
+ class="context-pane-container"
120
+ hx-get={`/api/v1/fragments/panes/${paneId}`}
121
+ hx-trigger="refresh"
122
+ hx-swap="innerHTML"
123
+ >
124
+ {
125
+ codeHookTarget ? (
126
+ <CodeHook target={codeHookTarget} fullContentMap={fullContentMap} />
127
+ ) : (
128
+ <Fragment set:html={fragmentData} />
129
+ )
130
+ }
131
+ </div>
132
+
133
+ <div class="py-12 text-center text-2xl md:text-3xl">
134
+ <button
135
+ id="context-close-btn"
136
+ class="rounded-lg bg-black px-3.5 py-2.5 text-white transition-all duration-200 hover:rotate-1 hover:bg-orange-500"
137
+ >
138
+ Close
139
+ </button>
140
+ </div>
141
+ </main>
142
+ </Layout>
143
+
144
+ <script>
145
+ document.addEventListener('DOMContentLoaded', function () {
146
+ const closeBtn = document.getElementById('context-close-btn');
147
+
148
+ if (closeBtn) {
149
+ closeBtn.addEventListener('click', function () {
150
+ // Check if we have history to go back to
151
+ if (window.history.length > 1 && document.referrer) {
152
+ // Go back to previous page
153
+ window.history.back();
154
+ } else {
155
+ // Fallback to home page
156
+ window.location.href = '/';
157
+ }
158
+ });
159
+ }
160
+ });
161
+ </script>