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,290 @@
1
+ ---
2
+ import { ClientRouter } from 'astro:transitions';
3
+ import Header from '@/components/Header.astro';
4
+ import Footer from '@/components/Footer.astro';
5
+ import { getBrandConfig } from '@/utils/api/brandConfig';
6
+ import { freshInstallStore } from '@/stores/backend';
7
+ import type { MenuNode } from '@/types/tractstack';
8
+ import type { ImpressionNode } from '@/types/compositorTypes';
9
+ export interface Props {
10
+ title: string;
11
+ slug?: string;
12
+ menu?: MenuNode | null;
13
+ created?: string;
14
+ canonicalURL?: string;
15
+ pubDatetime?: Date;
16
+ modDatetime?: Date | null;
17
+ ogImage?: string;
18
+ isContext?: boolean;
19
+ isStoryKeep?: boolean;
20
+ isEditor?: boolean;
21
+ isEditable?: boolean;
22
+ brandConfig?: any;
23
+ storyfragmentId?: string;
24
+ sessionId?: string;
25
+ impressions?: ImpressionNode[];
26
+ }
27
+
28
+ const {
29
+ title,
30
+ description = '',
31
+ slug = '',
32
+ menu = null,
33
+ created,
34
+ canonicalURL = Astro.url.pathname,
35
+ pubDatetime,
36
+ modDatetime,
37
+ ogImage,
38
+ isContext = false,
39
+ isStoryKeep = false,
40
+ isEditor = false,
41
+ isEditable = false,
42
+ brandConfig: propBrandConfig,
43
+ storyfragmentId = '',
44
+ sessionId = '',
45
+ impressions = [],
46
+ } = Astro.props;
47
+
48
+ const isDev = import.meta.env.DEV;
49
+
50
+ // Get site status from the store
51
+ const isInitialized = !freshInstallStore.get().needsSetup;
52
+
53
+ // Conditionally set asset paths based on initialization status
54
+ const cssBasePath = isInitialized ? '/media/css' : '/styles';
55
+ const fontBasePath = isInitialized ? '/media/fonts' : '/fonts';
56
+ const mainStylesUrl =
57
+ isStoryKeep || isDev
58
+ ? `${cssBasePath}/storykeep.css`
59
+ : `${cssBasePath}/frontend.css`;
60
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
61
+ const tenantId =
62
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
63
+
64
+ // Social media and SEO setup
65
+ const brandConfig = propBrandConfig || (await getBrandConfig(tenantId));
66
+ const defaultFavIcon = brandConfig.FAVICON || `/favicon.ico`;
67
+ const defaultSocialImageURL = ogImage || brandConfig.OG || `/og.png`;
68
+ const defaultSocialLogoURL = brandConfig.OGLOGO || `/oglogo.png`;
69
+ const defaultSocialTitle =
70
+ typeof title === `string` && title
71
+ ? title
72
+ : typeof brandConfig.OGTITLE === `string`
73
+ ? brandConfig.OGTITLE
74
+ : `TractStack dynamic website`;
75
+ const defaultSocialAuthor = brandConfig.OGAUTHOR || `TractStack`;
76
+ const defaultSocialDesc =
77
+ description ||
78
+ brandConfig.OGDESC ||
79
+ `No-code website builder and content marketing platform`;
80
+ const buildVersion = (() => {
81
+ if (modDatetime) return modDatetime.getTime();
82
+ if (pubDatetime) return pubDatetime.getTime();
83
+ return Date.now();
84
+ })();
85
+ const socialImageWithVersion = `${defaultSocialImageURL}?v=${buildVersion}`;
86
+ const socialLogoWithVersion = `${defaultSocialLogoURL}?v=${buildVersion}`;
87
+ const gtagId = brandConfig?.GTAG || false;
88
+ const gtagUrl =
89
+ typeof gtagId === `string` && gtagId.length > 1
90
+ ? `https://www.googletagmanager.com/gtag/js?id=${gtagId}`
91
+ : null;
92
+ const fullCanonicalUrl = brandConfig?.SITE_URL
93
+ ? canonicalURL.startsWith('/')
94
+ ? `${brandConfig.SITE_URL.replace(/\/$/, '')}${canonicalURL}`
95
+ : `${brandConfig.SITE_URL.replace(/\/$/, '')}/${canonicalURL}`
96
+ : canonicalURL;
97
+ ---
98
+
99
+ <!doctype html>
100
+ <html lang="en" class="motion-safe:scroll-smooth">
101
+ <head>
102
+ <meta charset="UTF-8" />
103
+ <meta
104
+ name="viewport"
105
+ content="width=device-width, initial-scale=1.0, viewport-fit=cover"
106
+ />
107
+ <meta name="description" content={defaultSocialDesc} />
108
+ <meta name="author" content={defaultSocialAuthor} />
109
+ <meta name="generator" content={Astro.generator} />
110
+ <link rel="icon" type="image/svg+xml" href={defaultFavIcon} />
111
+ <link rel="canonical" href={fullCanonicalUrl} />
112
+ <title>{defaultSocialTitle}</title>
113
+ <link rel="stylesheet" href={`${cssBasePath}/custom.css`} />
114
+ <link rel="stylesheet" href={mainStylesUrl} />
115
+ <link rel="sitemap" href="/sitemap.xml" />
116
+
117
+ <meta name="storyfragment-id" content={storyfragmentId} />
118
+ <meta name="session-id" content={sessionId} />
119
+
120
+ <meta name="title" content={defaultSocialTitle} />
121
+ <meta
122
+ property="og:site_name"
123
+ content={brandConfig?.OGAUTHOR || brandConfig?.OGTITLE || 'TractStack'}
124
+ />
125
+ <meta property="og:image:width" content="1200" />
126
+ <meta property="og:image:height" content="630" />
127
+ <meta
128
+ property="og:image:alt"
129
+ content={`${defaultSocialTitle} - Social Preview Image`}
130
+ />
131
+ <meta property="og:locale" content="en_US" />
132
+
133
+ <meta property="og:title" content={defaultSocialTitle} />
134
+ <meta property="og:type" content="website" />
135
+ <meta property="og:description" content={defaultSocialDesc} />
136
+ <meta property="og:url" content={fullCanonicalUrl} />
137
+ <meta property="og:image" content={socialImageWithVersion} />
138
+ <meta property="og:logo" content={socialLogoWithVersion} />
139
+
140
+ <meta property="twitter:card" content="summary_large_image" />
141
+ <meta property="twitter:url" content={fullCanonicalUrl} />
142
+ <meta property="twitter:title" content={defaultSocialTitle} />
143
+ <meta property="twitter:description" content={defaultSocialDesc} />
144
+ <meta property="twitter:image" content={socialImageWithVersion} />
145
+
146
+ {
147
+ pubDatetime && (
148
+ <meta
149
+ property="article:published_time"
150
+ content={pubDatetime.toISOString()}
151
+ />
152
+ )
153
+ }
154
+ {
155
+ modDatetime && (
156
+ <meta
157
+ property="article:modified_time"
158
+ content={modDatetime.toISOString()}
159
+ />
160
+ )
161
+ }
162
+
163
+ {gtagUrl && <script async src={gtagUrl} is:inline />}
164
+ <script is:inline define:vars={{ gtagId: brandConfig?.GTAG || '' }}>
165
+ (function () {
166
+ if (gtagId && gtagId.length > 1) {
167
+ window.dataLayer = window.dataLayer || [];
168
+ window.gtag =
169
+ window.gtag ||
170
+ function () {
171
+ window.dataLayer.push(arguments);
172
+ };
173
+
174
+ window.gtag('js', new Date());
175
+ window.gtag('config', gtagId);
176
+
177
+ document.addEventListener('astro:after-swap', () => {
178
+ window.gtag('config', gtagId);
179
+ });
180
+ }
181
+ })();
182
+ </script>
183
+
184
+ <ClientRouter />
185
+
186
+ <script
187
+ is:inline
188
+ type="text/javascript"
189
+ src="//assets.mediadelivery.net/playerjs/player-0.1.0.min.js"></script>
190
+
191
+ <script
192
+ src="https://unpkg.com/htmx.org@2.0.4"
193
+ crossorigin="anonymous"
194
+ is:inline
195
+ is:persist></script>
196
+
197
+ <script
198
+ define:vars={{
199
+ goBackend,
200
+ tenantId,
201
+ fontBasePath,
202
+ storyfragmentId,
203
+ sessionId,
204
+ }}
205
+ is:inline
206
+ >
207
+ function createTractstackConfig() {
208
+ window.TRACTSTACK_CONFIG = {
209
+ configured: true,
210
+ backendUrl: goBackend,
211
+ tenantId: tenantId,
212
+ fontBasePath: fontBasePath,
213
+ storyfragmentId: storyfragmentId,
214
+ sessionId: sessionId,
215
+ };
216
+ }
217
+
218
+ function updateTractstackConfig() {
219
+ // Get current values from meta tags
220
+ const storyfragmentMeta = document.querySelector(
221
+ 'meta[name="storyfragment-id"]'
222
+ );
223
+ const sessionMeta = document.querySelector('meta[name="session-id"]');
224
+
225
+ const currentStoryfragmentId = storyfragmentMeta
226
+ ? storyfragmentMeta.content
227
+ : null;
228
+ const currentSessionId = sessionMeta ? sessionMeta.content : sessionId;
229
+ if (window.TRACTSTACK_CONFIG && currentStoryfragmentId) {
230
+ window.TRACTSTACK_CONFIG.storyfragmentId = currentStoryfragmentId;
231
+ window.TRACTSTACK_CONFIG.sessionId = currentSessionId;
232
+ } else {
233
+ createTractstackConfig();
234
+ }
235
+ }
236
+
237
+ // Check if config exists.
238
+ // If not, create it. This handles the very first load.
239
+ if (!window.TRACTSTACK_CONFIG) {
240
+ createTractstackConfig();
241
+ }
242
+
243
+ // Update on subsequent loads, or set for the first time if script runs after initial setup
244
+ document.addEventListener('astro:page-load', updateTractstackConfig);
245
+ </script>
246
+ </head>
247
+ <body class="font-main w-full">
248
+ {
249
+ !isEditor && (
250
+ <Header
251
+ title={title}
252
+ slug={slug}
253
+ brandConfig={brandConfig}
254
+ isContext={isContext}
255
+ isStoryKeep={isStoryKeep}
256
+ isEditable={isEditable}
257
+ sessionId={sessionId}
258
+ menu={menu}
259
+ storyfragmentId={storyfragmentId}
260
+ impressions={impressions}
261
+ />
262
+ )
263
+ }
264
+ <div
265
+ id="loading-indicator"
266
+ class="bg-myorange fixed left-0 top-0 z-50 h-1 w-full scale-x-0 transform transition-transform duration-300 ease-out"
267
+ >
268
+ </div>
269
+ <div id="content" class="transition-opacity duration-300">
270
+ <slot />
271
+ </div>
272
+ {
273
+ !isEditor && (
274
+ <Footer
275
+ slug={slug}
276
+ brandConfig={brandConfig}
277
+ isContext={isContext}
278
+ menu={menu}
279
+ created={created}
280
+ backToTop={true}
281
+ />
282
+ )
283
+ }
284
+ <script type="module" is:inline is:persist>
285
+ import '/src/client/sse.js';
286
+ import '/src/client/belief-events.js';
287
+ import '/src/client/analytics-events.js';
288
+ </script>
289
+ </body>
290
+ </html>
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Calls the backend's /api/v1/auth/visit endpoint to create a new session.
3
+ * This function is decoupled from Astro-specific objects.
4
+ * @param tenantId The tenant ID to use for the backend request.
5
+ * @returns A promise that resolves to the new session ID from the backend.
6
+ */
7
+ export async function createBackendSession(tenantId: string): Promise<string> {
8
+ const goBackend =
9
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
10
+
11
+ try {
12
+ const response = await fetch(`${goBackend}/api/v1/auth/visit`, {
13
+ method: 'POST',
14
+ headers: {
15
+ 'X-Tenant-ID': tenantId,
16
+ 'Content-Type': 'application/json',
17
+ },
18
+ body: JSON.stringify({}),
19
+ });
20
+
21
+ if (!response.ok) {
22
+ const errorBody = await response.text();
23
+ console.error(
24
+ `Backend session creation failed: ${response.status}`,
25
+ errorBody
26
+ );
27
+ throw new Error(`Backend session creation failed: ${response.status}`);
28
+ }
29
+
30
+ const result = await response.json();
31
+ if (!result.sessionId) {
32
+ console.error('Backend did not return a sessionId on warming', result);
33
+ throw new Error('Backend did not return a sessionId');
34
+ }
35
+ return result.sessionId;
36
+ } catch (error) {
37
+ console.warn(
38
+ 'Backend session creation failed, using client-side SSR fallback for session ID'
39
+ );
40
+ return `ssr-fallback-${Date.now()}-${Math.random()
41
+ .toString(36)
42
+ .substring(2, 11)}`;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Get or create a session ID with proper validation
48
+ * This is the main function that should be used in [...slug].astro
49
+ */
50
+ export async function getOrSetSessionId(
51
+ astro: {
52
+ cookies: {
53
+ get: (name: string) => { value?: string } | undefined;
54
+ set: (name: string, value: string, options?: any) => void;
55
+ };
56
+ },
57
+ tenantId: string
58
+ ): Promise<string> {
59
+ // Check if we already have a session ID in the cookie
60
+ let sessionId = astro.cookies.get('tractstack_session_id')?.value;
61
+
62
+ if (sessionId) {
63
+ // Validate session exists in backend before using it
64
+ const isValid = await validateSessionWithBackend(sessionId, tenantId);
65
+ if (!isValid) {
66
+ console.warn(`Session ${sessionId} invalid, creating new session`);
67
+ sessionId = ''; // Force new session creation
68
+ }
69
+ }
70
+
71
+ if (!sessionId) {
72
+ // Call backend to generate collision-free session ID AND warm session
73
+ sessionId = await createBackendSession(tenantId);
74
+
75
+ // Set cookie with backend-provided session ID
76
+ astro.cookies.set('tractstack_session_id', sessionId, {
77
+ httpOnly: false, // Client needs to read for SSE handshake
78
+ secure: import.meta.env.PROD,
79
+ sameSite: 'lax',
80
+ path: '/',
81
+ maxAge: 60 * 60 * 24, // 24 hours
82
+ });
83
+
84
+ // console.log(`Created new session: ${sessionId}`);
85
+ //} else {
86
+ // console.log(`Using existing session: ${sessionId}`);
87
+ }
88
+
89
+ return sessionId;
90
+ }
91
+
92
+ /**
93
+ * Validate that a session exists in the backend cache
94
+ * This prevents using stale session IDs after server restarts
95
+ */
96
+ async function validateSessionWithBackend(
97
+ sessionId: string,
98
+ tenantId: string
99
+ ): Promise<boolean> {
100
+ const goBackend =
101
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
102
+
103
+ try {
104
+ // Use a lightweight endpoint to check if session exists
105
+ const response = await fetch(`${goBackend}/api/v1/auth/visit`, {
106
+ method: 'POST',
107
+ headers: {
108
+ 'X-Tenant-ID': tenantId,
109
+ 'Content-Type': 'application/json',
110
+ },
111
+ body: JSON.stringify({
112
+ sessionId: sessionId,
113
+ }),
114
+ });
115
+
116
+ if (!response.ok) {
117
+ return false;
118
+ }
119
+
120
+ const result = await response.json();
121
+ return result.success === true;
122
+ } catch (error) {
123
+ console.warn('Session validation failed:', error);
124
+ return false;
125
+ }
126
+ }
@@ -0,0 +1,56 @@
1
+ import { handleFailedResponse } from '@/utils/backend';
2
+ import type { ImpressionNode } from '@/types/compositorTypes';
3
+
4
+ export interface StoryData {
5
+ id: string;
6
+ title: string;
7
+ slug: string;
8
+ paneIds: string[];
9
+ codeHookTargets: Record<string, string>;
10
+ impressions: ImpressionNode[];
11
+ fragments: Record<string, string>;
12
+ menu: any;
13
+ isHome: boolean;
14
+ created: string;
15
+ }
16
+
17
+ export async function getStoryData(
18
+ astro: any,
19
+ lookup: string,
20
+ sessionId: string,
21
+ tenantId: string
22
+ ): Promise<StoryData> {
23
+ const goBackend =
24
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
25
+ const endpoint = lookup
26
+ ? `${goBackend}/api/v1/nodes/storyfragments/slug/${lookup}/personalized-payload`
27
+ : `${goBackend}/api/v1/nodes/storyfragments/home/personalized-payload`;
28
+
29
+ const response = await fetch(endpoint, {
30
+ headers: {
31
+ 'X-Tenant-ID': tenantId,
32
+ 'X-TractStack-Session-ID': sessionId,
33
+ },
34
+ });
35
+
36
+ const failedResponse = await handleFailedResponse(
37
+ response,
38
+ goBackend,
39
+ tenantId,
40
+ astro.url.pathname
41
+ );
42
+ if (failedResponse) {
43
+ throw new Response(null, {
44
+ status: failedResponse.status,
45
+ statusText: failedResponse.statusText,
46
+ });
47
+ }
48
+
49
+ const storyData = await response.json();
50
+
51
+ if (storyData.isHome && lookup !== '') {
52
+ throw astro.redirect('/');
53
+ }
54
+
55
+ return storyData;
56
+ }
@@ -0,0 +1,52 @@
1
+ import type { APIContext, MiddlewareNext } from '@/types/astro';
2
+
3
+ interface Locals {
4
+ tenant?: {
5
+ id: string;
6
+ domain: string | null;
7
+ isMultiTenant: boolean;
8
+ isLocalhost: boolean;
9
+ };
10
+ }
11
+
12
+ export async function onRequest(
13
+ context: APIContext & { locals: Locals },
14
+ next: MiddlewareNext
15
+ ) {
16
+ const isMultiTenantEnabled =
17
+ import.meta.env.PUBLIC_ENABLE_MULTI_TENANT === 'true';
18
+
19
+ // Only set tenant in locals if we have a trusted subdomain (production multi-tenant)
20
+ if (isMultiTenantEnabled && !import.meta.env.DEV) {
21
+ const hostname =
22
+ context.request.headers.get('x-forwarded-host') ||
23
+ context.request.headers.get('host');
24
+
25
+ if (hostname) {
26
+ // Parse production subdomain pattern: {tenantId}.sandbox.{platform}.com
27
+ const parts = hostname.split('.');
28
+ if (
29
+ parts.length >= 4 &&
30
+ parts[1] === 'sandbox' &&
31
+ ['freewebpress', 'tractstack'].includes(parts[2]) &&
32
+ parts[3] === 'com'
33
+ ) {
34
+ // Only set locals.tenant when we have a trusted subdomain
35
+ context.locals.tenant = {
36
+ id: parts[0],
37
+ domain: hostname,
38
+ isMultiTenant: true,
39
+ isLocalhost: false,
40
+ };
41
+
42
+ // Set header for backend communication
43
+ context.request.headers.set('X-Tenant-ID', parts[0]);
44
+ }
45
+ }
46
+ }
47
+
48
+ // If no trusted subdomain detected, leave locals.tenant undefined
49
+ // This allows the cascading check to fall through to PUBLIC_TENANTID
50
+
51
+ return next();
52
+ }
@@ -0,0 +1,54 @@
1
+ ---
2
+ const { pathname } = Astro.url;
3
+
4
+ if (pathname.startsWith('/.')) {
5
+ return new Response(null, { status: 404, statusText: 'Not Found' });
6
+ }
7
+
8
+ const assetExtensions = [
9
+ '.webp',
10
+ '.png',
11
+ '.jpg',
12
+ '.jpeg',
13
+ '.gif',
14
+ '.svg',
15
+ '.css',
16
+ '.js',
17
+ '.woff',
18
+ '.woff2',
19
+ '.ttf',
20
+ ];
21
+
22
+ const isAsset = assetExtensions.some((ext) => pathname.endsWith(ext));
23
+
24
+ if (isAsset || pathname === '/') {
25
+ // For a missing asset, we can send a minimal 404 response.
26
+ // The browser will handle the error gracefully (e.g., not display the image).
27
+ if (isAsset) {
28
+ return new Response(null, { status: 404, statusText: 'Not Found' });
29
+ }
30
+ // For a 404 at the root, we show the simple error page below.
31
+ } else {
32
+ // If it's not an asset and not the homepage, it's a missing page.
33
+ // Redirect to the homepage.
34
+ return Astro.redirect('/');
35
+ }
36
+ ---
37
+
38
+ <!doctype html>
39
+ <html lang="en">
40
+ <head>
41
+ <meta charset="UTF-8" />
42
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
43
+ <title>404 - Page Not Found</title>
44
+ </head>
45
+ <body>
46
+ <div
47
+ style="text-align: center; padding: 50px; font-family: Arial, sans-serif;"
48
+ >
49
+ <h1>404 - Page Not Found</h1>
50
+ <p>The page could not be found.</p>
51
+ <a href="/" style="color: #0066cc;">Go to Home</a>
52
+ </div>
53
+ </body>
54
+ </html>