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,122 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+ import { getBrandConfig } from '@/utils/api/brandConfig';
3
+
4
+ export const GET: APIRoute = async ({ request }) => {
5
+ // Get tenant ID from headers (set by middleware)
6
+ const tenantId = request.headers.get('X-Tenant-ID') || 'default';
7
+
8
+ // Fetch content map from backend
9
+ const goBackend =
10
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
11
+
12
+ let contentMap = [];
13
+ let brandConfig = null;
14
+
15
+ try {
16
+ // Fetch content map
17
+ const contentResponse = await fetch(
18
+ `${goBackend}/api/v1/content/full-map`,
19
+ {
20
+ headers: {
21
+ 'X-Tenant-ID': tenantId,
22
+ },
23
+ }
24
+ );
25
+
26
+ if (contentResponse.ok) {
27
+ const contentData = await contentResponse.json();
28
+ contentMap = contentData.data?.data || [];
29
+ }
30
+
31
+ // Fetch brand config
32
+ brandConfig = await getBrandConfig(tenantId);
33
+ } catch (error) {
34
+ console.error('Error fetching data for llms.txt:', error);
35
+ // Continue with empty data rather than failing
36
+ }
37
+
38
+ // Filter for public content (StoryFragments and context Panes)
39
+ const publicContent = contentMap.filter(
40
+ (c: any) => c.type === 'StoryFragment' || (c.type === 'Pane' && c.isContext)
41
+ );
42
+
43
+ // Build the content URLs
44
+ const siteUrl = brandConfig?.SITE_URL || 'https://example.com';
45
+ const homeSlug = brandConfig?.HOME_SLUG || 'home';
46
+
47
+ const contentUrls = publicContent
48
+ .map((c: any) => {
49
+ if (c.type === 'StoryFragment') {
50
+ return c.slug === homeSlug
51
+ ? new URL('/', siteUrl).href
52
+ : new URL(c.slug, siteUrl).href;
53
+ }
54
+ if (c.type === 'Pane' && c.isContext) {
55
+ return new URL(`context/${c.slug}`, siteUrl).href;
56
+ }
57
+ })
58
+ .filter(Boolean) as string[];
59
+
60
+ // Use the brand config values
61
+ const siteTitle = brandConfig?.OGTITLE || brandConfig?.SLOGAN || 'Website';
62
+ const siteDescription =
63
+ brandConfig?.OGDESC ||
64
+ brandConfig?.FOOTER ||
65
+ 'A website built with TractStack';
66
+ const siteName = brandConfig?.OGAUTHOR || siteTitle;
67
+ const theme = brandConfig?.THEME || 'Default';
68
+ const openDemo = brandConfig?.OPEN_DEMO || false;
69
+
70
+ const llmsTxt = `# ${siteTitle} - LLMs.txt
71
+
72
+ ## About this site
73
+ ${siteDescription}
74
+
75
+ ## Site Information
76
+ - URL: ${siteUrl}
77
+ - Title: ${siteTitle}
78
+ - Author: ${siteName}
79
+ - Description: ${siteDescription}
80
+ - Slogan: ${brandConfig?.SLOGAN || ''}
81
+ - Theme: ${theme}
82
+
83
+ ## Available Content
84
+ This site contains ${publicContent.length} publicly accessible pages:
85
+ ${contentUrls.map((url: string) => `- ${url}`).join('\n')}
86
+
87
+ ## Technical Information
88
+ - Built with: TractStack
89
+ - Theme: ${theme}
90
+ - Demo Mode Enabled: ${openDemo ? 'Yes' : 'No'}
91
+
92
+ ## Usage Guidelines
93
+ This content is available for AI training and indexing. Please respect the site's robots.txt file and terms of service.
94
+
95
+ ## Contact
96
+ For questions about this content, please visit: ${siteUrl}
97
+
98
+ ---
99
+ Generated on: ${new Date().toISOString()}
100
+ Content last updated: ${new Date().toISOString()}`.trim();
101
+
102
+ return new Response(llmsTxt, {
103
+ headers: {
104
+ 'Content-Type': 'text/plain; charset=utf-8',
105
+ 'Cache-Control': 'public, max-age=3600',
106
+ 'X-Content-Type-Options': 'nosniff',
107
+ },
108
+ });
109
+ };
110
+
111
+ export const HEAD: APIRoute = async () => {
112
+ // For HEAD requests, return the same headers but no body
113
+ return new Response(null, {
114
+ headers: {
115
+ 'Content-Type': 'text/plain; charset=utf-8',
116
+ 'Cache-Control': 'public, max-age=3600',
117
+ 'X-Content-Type-Options': 'nosniff',
118
+ },
119
+ });
120
+ };
121
+
122
+ export const prerender = false;
@@ -0,0 +1,183 @@
1
+ ---
2
+ import { getBrandConfig } from '@/utils/api/brandConfig';
3
+
4
+ const originalUrl = Astro.url.searchParams.get('from') || '/';
5
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+ const tenantId =
7
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
8
+ const brandConfig = await getBrandConfig(tenantId);
9
+ const getAssetPath = (configPath: string, fallback: string) => {
10
+ // Always prioritize brandConfig values when they exist
11
+ if (configPath && configPath !== '') {
12
+ return configPath;
13
+ }
14
+ return fallback;
15
+ };
16
+ const logo = getAssetPath(brandConfig?.LOGO, '/brand/logo.svg');
17
+ const wordmark = getAssetPath(brandConfig?.WORDMARK, '/brand/wordmark.svg');
18
+ ---
19
+
20
+ <!doctype html>
21
+ <html lang="en" class="bg-mywhite h-full">
22
+ <head>
23
+ <meta charset="UTF-8" />
24
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
25
+ <title>Service Maintenance | TractStack</title>
26
+ <link rel="stylesheet" href="/styles/custom.css" />
27
+ <link rel="stylesheet" href="/styles/storykeep.css" />
28
+ </head>
29
+ <body class="h-full">
30
+ <div class="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
31
+ <div class="mx-auto pb-6">
32
+ <div class="flex flex-col items-center justify-center gap-4">
33
+ <div class="h-16 w-auto">
34
+ <img
35
+ src={logo}
36
+ class="pointer-events-none h-full w-auto"
37
+ alt="Logo"
38
+ />
39
+ </div>
40
+ <div class="h-16 w-auto">
41
+ <img
42
+ src={wordmark}
43
+ class="pointer-events-none h-full w-auto max-w-48 md:max-w-72"
44
+ alt="Wordmark"
45
+ />
46
+ </div>
47
+ </div>
48
+
49
+ <h2
50
+ class="text-mydarkgrey mt-6 text-center text-2xl font-bold leading-9 tracking-tight"
51
+ >
52
+ Service Temporarily Unavailable
53
+ </h2>
54
+ </div>
55
+
56
+ <div class="mx-auto">
57
+ <div class="rounded-lg bg-white px-6 py-12 shadow-inner">
58
+ <div class="space-y-6 text-center">
59
+ <div class="text-myorange mx-auto h-12 w-12">
60
+ <svg
61
+ fill="none"
62
+ stroke="currentColor"
63
+ viewBox="0 0 24 24"
64
+ xmlns="http://www.w3.org/2000/svg"
65
+ >
66
+ <path
67
+ stroke-linecap="round"
68
+ stroke-linejoin="round"
69
+ stroke-width="2"
70
+ d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
71
+ ></path>
72
+ </svg>
73
+ </div>
74
+
75
+ <p class="text-mydarkgrey text-sm">
76
+ We're experiencing technical difficulties. The service will be
77
+ restored automatically.
78
+ </p>
79
+
80
+ <div
81
+ id="status-indicator"
82
+ class="border-mylightgrey inline-flex items-center rounded-md border bg-white px-4 py-2 shadow-sm"
83
+ >
84
+ <div class="text-myorange -ml-1 mr-3 h-5 w-5 animate-spin">
85
+ <svg fill="none" viewBox="0 0 24 24">
86
+ <circle
87
+ class="opacity-25"
88
+ cx="12"
89
+ cy="12"
90
+ r="10"
91
+ stroke="currentColor"
92
+ stroke-width="4"></circle>
93
+ <path
94
+ class="opacity-75"
95
+ fill="currentColor"
96
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
97
+ ></path>
98
+ </svg>
99
+ </div>
100
+ <span class="text-mydarkgrey text-sm"
101
+ >Checking service status...</span
102
+ >
103
+ </div>
104
+
105
+ <div class="text-mylightgrey text-center text-xs">
106
+ <p>
107
+ This page will automatically refresh when the service is
108
+ available
109
+ </p>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <script is:inline define:vars={{ goBackend, tenantId, originalUrl }}>
117
+ let checkCount = 0;
118
+ const maxChecks = 240;
119
+
120
+ function updateStatus(message, isChecking = true) {
121
+ const indicator = document.getElementById('status-indicator');
122
+ const spinner = indicator.querySelector('.animate-spin');
123
+ const text = indicator.querySelector('span');
124
+
125
+ if (isChecking) {
126
+ spinner.style.display = 'block';
127
+ } else {
128
+ spinner.style.display = 'none';
129
+ }
130
+
131
+ text.textContent = message;
132
+ }
133
+
134
+ async function checkBackendHealth() {
135
+ checkCount++;
136
+
137
+ try {
138
+ const response = await fetch(`${goBackend}/api/v1/health`, {
139
+ method: 'GET',
140
+ headers: {
141
+ 'X-Tenant-ID': tenantId,
142
+ },
143
+ signal: AbortSignal.timeout(5000),
144
+ });
145
+
146
+ if (response.ok) {
147
+ const data = await response.json();
148
+ if (data.healthy) {
149
+ updateStatus('Service restored! Redirecting...', false);
150
+
151
+ setTimeout(() => {
152
+ window.location.href = originalUrl;
153
+ }, 1000);
154
+ return;
155
+ }
156
+ }
157
+ } catch (error) {
158
+ console.log('Health check failed:', error.message);
159
+ }
160
+
161
+ if (checkCount < 5) {
162
+ updateStatus('Checking service status...');
163
+ } else if (checkCount < 20) {
164
+ updateStatus('Service still unavailable, continuing to check...');
165
+ } else if (checkCount < maxChecks) {
166
+ updateStatus(`Still checking... (attempt ${checkCount})`);
167
+ } else {
168
+ updateStatus(
169
+ 'Extended outage detected. Please contact support.',
170
+ false
171
+ );
172
+ return;
173
+ }
174
+
175
+ setTimeout(checkBackendHealth, 30000);
176
+ }
177
+
178
+ document.addEventListener('DOMContentLoaded', () => {
179
+ checkBackendHealth();
180
+ });
181
+ </script>
182
+ </body>
183
+ </html>
@@ -0,0 +1,67 @@
1
+ ---
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ // DO NOT USE IN PRODUCTION !!!
6
+ // this is a stop-gap for dev testing ...
7
+
8
+ // configure nginx to serve files on /media !!
9
+ // see the docs
10
+
11
+ export const prerender = false;
12
+
13
+ const MIME_TYPES: Record<string, string> = {
14
+ '.css': 'text/css',
15
+ '.js': 'application/javascript',
16
+ '.json': 'application/json',
17
+ '.svg': 'image/svg+xml',
18
+ '.png': 'image/png',
19
+ '.jpg': 'image/jpeg',
20
+ '.jpeg': 'image/jpeg',
21
+ '.gif': 'image/gif',
22
+ '.webp': 'image/webp',
23
+ '.woff': 'font/woff',
24
+ '.woff2': 'font/woff2',
25
+ '.ttf': 'font/ttf',
26
+ '.otf': 'font/otf',
27
+ '.ico': 'image/x-icon',
28
+ };
29
+
30
+ const { slug } = Astro.params;
31
+
32
+ const tenant =
33
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
34
+
35
+ const baseServerPath = import.meta.env.PRIVATE_GO_BACKEND_PATH;
36
+ if (!baseServerPath) {
37
+ console.error(
38
+ '[ERROR] PRIVATE_GO_BACKEND_PATH environment variable is not set.'
39
+ );
40
+ return new Response('Server configuration error', { status: 500 });
41
+ }
42
+
43
+ if (!slug) throw new Error(`Invalid path for tenant "${tenant}".`);
44
+
45
+ try {
46
+ // Construct the file path using the correct tenant ID
47
+ const fullPath = path.join(baseServerPath, 'config', tenant, 'media', slug);
48
+
49
+ // Security check to prevent path traversal
50
+ const tenantMediaRoot = path.join(baseServerPath, 'config', tenant, 'media');
51
+ if (!path.resolve(fullPath).startsWith(path.resolve(tenantMediaRoot))) {
52
+ throw new Error(`Invalid path for tenant "${tenant}".`);
53
+ }
54
+
55
+ const fileBuffer = await fs.readFile(fullPath);
56
+ const extension = path.extname(slug).toLowerCase();
57
+ const mimeType = MIME_TYPES[extension] || 'application/octet-stream';
58
+
59
+ return new Response(fileBuffer, {
60
+ status: 200,
61
+ headers: { 'Content-Type': mimeType },
62
+ });
63
+ } catch (error) {
64
+ console.error(`Could not serve media file: ${slug} for tenant ${tenant}.`);
65
+ return new Response(null, { status: 404, statusText: 'Not Found' });
66
+ }
67
+ ---
@@ -0,0 +1,36 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+ import { getBrandConfig } from '@/utils/api/brandConfig';
3
+
4
+ export const GET: APIRoute = async ({ request }) => {
5
+ // Get tenant ID from headers (set by middleware)
6
+ const tenantId = request.headers.get('X-Tenant-ID') || 'default';
7
+
8
+ // Fetch brand config
9
+ let brandConfig = null;
10
+
11
+ try {
12
+ brandConfig = await getBrandConfig(tenantId);
13
+ } catch (error) {
14
+ console.error('Error fetching brand config for robots.txt:', error);
15
+ // Continue with default values
16
+ }
17
+
18
+ const siteUrl = brandConfig?.SITE_URL || 'https://example.com';
19
+
20
+ const robotsTxt = `
21
+ User-agent: *
22
+ Disallow: /storykeep/
23
+ Disallow: /storykeep/*
24
+ Allow: /
25
+
26
+ Sitemap: ${new URL('sitemap.xml', siteUrl).href}
27
+ `.trim();
28
+
29
+ return new Response(robotsTxt, {
30
+ headers: {
31
+ 'Content-Type': 'text/plain; charset=utf-8',
32
+ },
33
+ });
34
+ };
35
+
36
+ export const prerender = false;
@@ -0,0 +1,258 @@
1
+ ---
2
+ import Layout from '@/layouts/Layout.astro';
3
+ import { getBrandConfig } from '@/utils/api/brandConfig';
4
+ import { preHealthCheck } from '@/utils/backend';
5
+
6
+ const tenantId = 'default'; // For registration, always use default
7
+
8
+ const healthCheckRedirect = await preHealthCheck(tenantId);
9
+ if (healthCheckRedirect !== undefined) {
10
+ return healthCheckRedirect;
11
+ }
12
+
13
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
14
+
15
+ // Check if multi-tenant is enabled
16
+ const isMultiTenantEnabled =
17
+ import.meta.env.PUBLIC_ENABLE_MULTI_TENANT === 'true';
18
+ if (!isMultiTenantEnabled) {
19
+ return Astro.redirect('/?error=multi-tenant-disabled');
20
+ }
21
+
22
+ // Dev mode detection
23
+ const isDev = import.meta.env.DEV;
24
+
25
+ // Get activation token from URL
26
+ const url = new URL(Astro.request.url);
27
+ const token = url.searchParams.get('token');
28
+
29
+ let activationResult = {
30
+ success: false,
31
+ error: null as string | null,
32
+ tenantId: null as string | null,
33
+ };
34
+
35
+ if (!token) {
36
+ activationResult.error =
37
+ 'Missing activation token. Please check your email link.';
38
+ console.log('ERROR: No token provided');
39
+ } else {
40
+ // Attempt activation
41
+ try {
42
+ // Get tenantId BEFORE calling activation
43
+ let tenantId: string;
44
+
45
+ if (isDev) {
46
+ // In dev mode, get tenant ID from URL param or use default
47
+ tenantId = url.searchParams.get('tenantId') || 'localhost';
48
+ } else {
49
+ // Extract tenant ID from current domain in production
50
+ const hostname = Astro.request.headers.get('host') || '';
51
+ const parts = hostname.split('.');
52
+ if (parts.length >= 4 && parts[1] === 'sandbox') {
53
+ tenantId = parts[0];
54
+ } else {
55
+ throw new Error('Could not determine tenant ID from domain');
56
+ }
57
+ }
58
+
59
+ // Make direct fetch call to Go backend (like other .astro files)
60
+ const response = await fetch(`${goBackend}/api/v1/tenant/activation`, {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Content-Type': 'application/json',
64
+ 'X-Tenant-ID': tenantId,
65
+ },
66
+ body: JSON.stringify({ token }),
67
+ });
68
+
69
+ const responseText = await response.text();
70
+
71
+ if (response.ok) {
72
+ activationResult.success = true;
73
+ activationResult.tenantId = tenantId;
74
+ } else {
75
+ let errorData;
76
+ try {
77
+ errorData = JSON.parse(responseText);
78
+ } catch (e) {
79
+ errorData = { error: responseText };
80
+ }
81
+ activationResult.error = errorData.error || 'Activation failed';
82
+ console.log('FAILED: Activation error:', activationResult.error);
83
+ }
84
+ } catch (error) {
85
+ activationResult.error =
86
+ error instanceof Error ? error.message : 'Activation failed';
87
+ console.log('EXCEPTION:', error);
88
+ }
89
+ }
90
+
91
+ const brandConfig = await getBrandConfig('default');
92
+ const title = activationResult.success
93
+ ? 'Tenant Activated | TractStack'
94
+ : 'Activation Error | TractStack';
95
+
96
+ // Build dashboard URL based on environment
97
+ const getDashboardUrl = (tenantId: string) => {
98
+ if (isDev) {
99
+ return '/storykeep';
100
+ }
101
+ return `https://${tenantId}.sandbox.freewebpress.com/storykeep`;
102
+ };
103
+
104
+ // Build display URL based on environment
105
+ const getDisplayUrl = (tenantId: string) => {
106
+ if (isDev) {
107
+ return 'localhost:4321';
108
+ }
109
+ return `https://${tenantId}.sandbox.freewebpress.com`;
110
+ };
111
+ ---
112
+
113
+ <Layout title={title} slug="tenant-activate" brandConfig={brandConfig}>
114
+ <main
115
+ id="main-content"
116
+ class="flex min-h-screen items-center justify-center bg-gray-50"
117
+ >
118
+ <div class="mx-auto max-w-2xl p-6">
119
+ {
120
+ activationResult.success ? (
121
+ <div class="rounded-lg bg-white p-8 text-center shadow-lg">
122
+ <div class="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-green-100">
123
+ <svg
124
+ class="h-8 w-8 text-green-600"
125
+ fill="none"
126
+ stroke="currentColor"
127
+ viewBox="0 0 24 24"
128
+ >
129
+ <path
130
+ stroke-linecap="round"
131
+ stroke-linejoin="round"
132
+ stroke-width="2"
133
+ d="M5 13l4 4L19 7"
134
+ />
135
+ </svg>
136
+ </div>
137
+
138
+ <h2 class="mb-4 text-2xl font-bold text-gray-900">
139
+ 🎉 Tenant Activated Successfully!
140
+ </h2>
141
+
142
+ <p class="mb-6 text-gray-600">
143
+ Your TractStack tenant has been activated and is ready to use.
144
+ </p>
145
+
146
+ {activationResult.tenantId && (
147
+ <div class="mb-6 rounded-lg border border-orange-200 bg-orange-50 p-4">
148
+ <p class="mb-2 text-sm font-bold text-orange-800">
149
+ Your tenant URL:
150
+ </p>
151
+ <p class="break-all font-mono text-orange-700">
152
+ {getDisplayUrl(activationResult.tenantId)}
153
+ </p>
154
+ </div>
155
+ )}
156
+
157
+ <div class="space-y-4">
158
+ {activationResult.tenantId ? (
159
+ <a
160
+ href={getDashboardUrl(activationResult.tenantId)}
161
+ class="inline-block rounded-lg bg-orange-600 px-6 py-3 font-bold text-white transition-colors hover:bg-orange-700"
162
+ id="dashboard-button"
163
+ >
164
+ Access Your Dashboard
165
+ </a>
166
+ ) : (
167
+ <div class="text-gray-500">
168
+ <p class="mb-2">Unable to determine tenant URL</p>
169
+ <p class="text-sm">Please contact support</p>
170
+ </div>
171
+ )}
172
+ </div>
173
+ </div>
174
+ ) : (
175
+ <div class="rounded-lg bg-white p-8 text-center shadow-lg">
176
+ <div class="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
177
+ <svg
178
+ class="h-8 w-8 text-red-600"
179
+ fill="none"
180
+ stroke="currentColor"
181
+ viewBox="0 0 24 24"
182
+ >
183
+ <path
184
+ stroke-linecap="round"
185
+ stroke-linejoin="round"
186
+ stroke-width="2"
187
+ d="M6 18L18 6M6 6l12 12"
188
+ />
189
+ </svg>
190
+ </div>
191
+
192
+ <h2 class="mb-4 text-2xl font-bold text-gray-900">
193
+ Activation Failed
194
+ </h2>
195
+
196
+ <p class="mb-6 text-gray-600">{activationResult.error}</p>
197
+
198
+ <div class="mb-6 rounded-lg border border-yellow-200 bg-yellow-50 p-4">
199
+ <h3 class="mb-2 text-sm font-bold text-yellow-800">
200
+ Common Issues:
201
+ </h3>
202
+ <ul class="space-y-1 text-left text-sm text-yellow-700">
203
+ <li>• The activation link may have expired</li>
204
+ <li>• The token may have already been used</li>
205
+ <li>• There may be a temporary server issue</li>
206
+ </ul>
207
+ </div>
208
+
209
+ <div class="space-y-4">
210
+ <a
211
+ href="/sandbox/register"
212
+ class="inline-block rounded-lg bg-orange-600 px-6 py-3 font-bold text-white transition-colors hover:bg-orange-700"
213
+ >
214
+ Register New Tenant
215
+ </a>
216
+
217
+ <div class="text-center">
218
+ <a
219
+ href="mailto:support@tractstack.com"
220
+ class="text-sm text-orange-600 underline hover:text-orange-800"
221
+ >
222
+ Contact Support
223
+ </a>
224
+ </div>
225
+ </div>
226
+ </div>
227
+ )
228
+ }
229
+ </div>
230
+ </main>
231
+ </Layout>
232
+
233
+ <script>
234
+ // Auto-redirect to dashboard after successful activation with countdown
235
+ const dashboardButton = document.getElementById('dashboard-button');
236
+ if (dashboardButton) {
237
+ let countdown = 5;
238
+
239
+ // Update button text with countdown
240
+ const updateButton = () => {
241
+ dashboardButton.textContent = `Access Your Dashboard (${countdown}s)`;
242
+ countdown--;
243
+
244
+ if (countdown < 0) {
245
+ dashboardButton.click();
246
+ }
247
+ };
248
+
249
+ // Start countdown immediately
250
+ updateButton();
251
+ const interval = setInterval(updateButton, 1000);
252
+
253
+ // Clear interval if user clicks button manually
254
+ dashboardButton.addEventListener('click', () => {
255
+ clearInterval(interval);
256
+ });
257
+ }
258
+ </script>