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,216 @@
1
+ ---
2
+ import { ulid } from 'ulid';
3
+ import Layout from '@/layouts/Layout.astro';
4
+ import Header from '@/components/Header.astro';
5
+ import { getFullContentMap } from '@/stores/analytics';
6
+ import { getBrandConfig } from '@/utils/api/brandConfig';
7
+ import { joinUrlPaths } from '@/utils/helpers';
8
+ import { handleFailedResponse } from '@/utils/backend';
9
+ import { components as codeHookComponents } from '@/custom/CodeHook.astro';
10
+ import StoryKeepHeader from '@/components/edit/Header';
11
+ import StoryKeepToolBar from '@/components/edit/ToolBar';
12
+ import StoryKeepToolMode from '@/components/edit/ToolMode';
13
+ import SettingsPanel from '@/components/edit/SettingsPanel';
14
+ import { Compositor } from '@/components/compositor/Compositor';
15
+ import { requireAdminOrEditor } from '@/utils/auth';
16
+ import { preHealthCheck } from '@/utils/backend';
17
+
18
+ const tenantId =
19
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
20
+
21
+ const healthCheckRedirect = await preHealthCheck(tenantId);
22
+ if (healthCheckRedirect !== undefined) {
23
+ return healthCheckRedirect;
24
+ }
25
+
26
+ const { slug } = Astro.params;
27
+ if (!slug) return Astro.redirect('/404');
28
+
29
+ // Authentication check - redirect to login if not authenticated
30
+ const authCheck = requireAdminOrEditor(Astro);
31
+ if (authCheck) {
32
+ return authCheck;
33
+ }
34
+
35
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
36
+
37
+ const brandConfig = await getBrandConfig(tenantId);
38
+ if (!brandConfig.SITE_INIT) {
39
+ return Astro.redirect('/storykeep');
40
+ }
41
+
42
+ let loadData;
43
+ let storyFragment;
44
+ let title;
45
+ let storyFragmentID;
46
+
47
+ // Handle create mode
48
+ if (slug === 'create') {
49
+ // Create empty storyfragment in memory
50
+ const emptyStoryFragment = {
51
+ id: ulid(),
52
+ nodeType: 'StoryFragment' as const,
53
+ parentId: null,
54
+ title: '',
55
+ slug: '',
56
+ paneIds: [],
57
+ isChanged: false,
58
+ created: new Date(),
59
+ changed: new Date(),
60
+ };
61
+
62
+ loadData = {
63
+ storyfragmentNodes: [emptyStoryFragment],
64
+ };
65
+
66
+ storyFragment = emptyStoryFragment;
67
+ title = 'Create New Page - TractStack Editor';
68
+ storyFragmentID = emptyStoryFragment.id;
69
+ } else {
70
+ // Existing backend fetch logic
71
+ const endpoint = `${goBackend}/api/v1/nodes/storyfragments/slug/${slug}/full-payload`;
72
+
73
+ try {
74
+ const response = await fetch(endpoint, {
75
+ headers: {
76
+ 'X-Tenant-ID': tenantId,
77
+ Cookie: Astro.request.headers.get('cookie') || '',
78
+ },
79
+ });
80
+
81
+ const failedResponse = await handleFailedResponse(
82
+ response,
83
+ goBackend,
84
+ tenantId,
85
+ Astro.url.pathname
86
+ );
87
+ if (failedResponse) {
88
+ return failedResponse;
89
+ }
90
+
91
+ loadData = await response.json();
92
+ } catch (error) {
93
+ console.error('Error fetching storyfragment full payload:', error);
94
+ return Astro.redirect(
95
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
96
+ );
97
+ }
98
+
99
+ // Extract data from the response
100
+ storyFragment = loadData?.storyfragmentNodes.at(0);
101
+ title = storyFragment?.title || `Editor`;
102
+ storyFragmentID = storyFragment?.id;
103
+ }
104
+
105
+ const canonicalURL = slug === brandConfig?.HOME_SLUG ? '/' : `/${slug}`;
106
+ const fullCanonicalURL = brandConfig?.SITE_URL
107
+ ? canonicalURL.startsWith('/')
108
+ ? `${brandConfig.SITE_URL.replace(/\/$/, '')}${canonicalURL}`
109
+ : `${brandConfig.SITE_URL.replace(/\/$/, '')}/${canonicalURL}`
110
+ : canonicalURL;
111
+
112
+ // Extract dates if available
113
+ const pubDatetime = storyFragment?.created
114
+ ? new Date(storyFragment.created)
115
+ : undefined;
116
+ const modDatetime = storyFragment?.changed
117
+ ? new Date(storyFragment.changed)
118
+ : null;
119
+
120
+ // Social image from the story fragment
121
+ const ogImage = storyFragment?.socialImagePath
122
+ ? joinUrlPaths(brandConfig?.SITE_URL || ``, storyFragment.socialImagePath)
123
+ : undefined;
124
+
125
+ const fullContentMap = await getFullContentMap(
126
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default'
127
+ );
128
+ const urlParams: Record<string, string | boolean> = {};
129
+ for (const [key, value] of Astro.url.searchParams) {
130
+ urlParams[key] = value === '' ? true : value;
131
+ }
132
+ ---
133
+
134
+ <Layout
135
+ title={title}
136
+ slug={slug}
137
+ canonicalURL={canonicalURL}
138
+ pubDatetime={pubDatetime}
139
+ modDatetime={modDatetime}
140
+ ogImage={ogImage}
141
+ brandConfig={brandConfig}
142
+ storyfragmentId={storyFragmentID}
143
+ isEditor={true}
144
+ >
145
+ <!-- Standard Header (scrollable) -->
146
+ <Header
147
+ title={title}
148
+ slug={slug}
149
+ brandConfig={brandConfig}
150
+ isContext={false}
151
+ isStoryKeep={true}
152
+ isEditable={false}
153
+ menu={null}
154
+ />
155
+
156
+ <!-- StoryKeep Editor Header (scroll-aware positioning) -->
157
+ <section
158
+ id="storykeepHeader"
159
+ role="banner"
160
+ class="z-101 bg-mywhite left-0 right-0 drop-shadow transition-all duration-200"
161
+ >
162
+ <StoryKeepHeader slug={slug} isContext={false} client:only="react" />
163
+ </section>
164
+
165
+ <div class="flex min-h-screen">
166
+ <!-- Tool Navigation (mobile bottom, desktop side) -->
167
+ <StoryKeepToolMode isContext={false} client:only="react" />
168
+
169
+ <!-- Main Content Area -->
170
+ <main id="mainContent" class="relative flex-1">
171
+ <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
172
+ <div
173
+ class="h-fit min-h-screen"
174
+ style={{
175
+ backgroundImage:
176
+ 'repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(0,0,0,0.05) 10px, rgba(0,0,0,0.05) 20px)',
177
+ }}
178
+ >
179
+ <Compositor
180
+ id={storyFragmentID}
181
+ nodes={loadData}
182
+ config={brandConfig}
183
+ fullContentMap={fullContentMap}
184
+ fullCanonicalURL={fullCanonicalURL}
185
+ urlParams={urlParams}
186
+ availableCodeHooks={Object.keys(codeHookComponents)}
187
+ client:only="react"
188
+ />
189
+ </div>
190
+ </div>
191
+ </main>
192
+ </div>
193
+
194
+ <!-- Floating Controls (Settings Panel & HUD OR ToolBar) -->
195
+ <aside
196
+ id="settingsControls"
197
+ class="z-101 pointer-events-none fixed bottom-24 right-0 flex max-h-screen flex-col items-end gap-2 overflow-y-auto p-4 md:bottom-0"
198
+ >
199
+ <div class="pointer-events-auto">
200
+ <StoryKeepToolBar client:only="react" />
201
+ </div>
202
+ <div class="pointer-events-auto">
203
+ <SettingsPanel
204
+ config={brandConfig}
205
+ availableCodeHooks={['featured-content', 'list-content', 'bunny-video']}
206
+ client:only="react"
207
+ />
208
+ </div>
209
+ </aside>
210
+ </Layout>
211
+
212
+ <script>
213
+ import { setupLayoutObservers, setupLayoutStyles } from '@/utils/layout';
214
+ setupLayoutStyles();
215
+ setupLayoutObservers();
216
+ </script>
@@ -0,0 +1,148 @@
1
+ ---
2
+ import Layout from '@/layouts/Layout.astro';
3
+ import CodeHook from '@/custom/CodeHook.astro';
4
+ import { getBrandConfig } from '@/utils/api/brandConfig';
5
+ import { handleFailedResponse } from '@/utils/backend';
6
+ import { getFullContentMap } from '@/stores/analytics';
7
+ import { getOrSetSessionId } from '@/lib/session';
8
+ import { getStoryData } from '@/lib/storyData';
9
+ import { preHealthCheck } from '@/utils/backend';
10
+
11
+ const tenantId =
12
+ Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
13
+
14
+ const healthCheckRedirect = await preHealthCheck(tenantId);
15
+ if (healthCheckRedirect !== undefined) {
16
+ return healthCheckRedirect;
17
+ }
18
+
19
+ const { slug } = Astro.params || {};
20
+
21
+ if (slug && (slug.startsWith('images/') || slug.startsWith('media/'))) {
22
+ return new Response(null, { status: 404, statusText: 'Not Found' });
23
+ }
24
+
25
+ const lookup = slug || '';
26
+ const sessionId = await getOrSetSessionId(Astro, tenantId);
27
+ const goBackend = import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
28
+
29
+ let storyData;
30
+ try {
31
+ storyData = await getStoryData(Astro, lookup, sessionId, tenantId);
32
+ } catch (error) {
33
+ if (error instanceof Response) {
34
+ return error;
35
+ }
36
+ console.error('Error fetching storyfragment:', error);
37
+ return Astro.redirect(
38
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
39
+ );
40
+ }
41
+
42
+ const storyfragmentId = storyData.id;
43
+ const storyfragmentTitle = storyData.title || 'Untitled Story';
44
+ const paneIds = storyData.paneIds || [];
45
+ const codeHookTargets = storyData.codeHookTargets || {};
46
+
47
+ if (paneIds.length === 0) {
48
+ console.log(`Empty Story Fragment. Redirecting to /storykeep`);
49
+ return Astro.redirect('/storykeep');
50
+ }
51
+
52
+ let fragmentsData: Record<string, string> = {};
53
+ try {
54
+ const batchResponse = await fetch(`${goBackend}/api/v1/fragments/panes`, {
55
+ method: 'POST',
56
+ headers: {
57
+ 'Content-Type': 'application/json',
58
+ 'X-Tenant-ID': tenantId,
59
+ 'X-StoryFragment-ID': storyfragmentId,
60
+ 'X-TractStack-Session-ID': sessionId,
61
+ },
62
+ body: JSON.stringify({ paneIds }),
63
+ });
64
+
65
+ if (batchResponse.ok) {
66
+ const batchData = await batchResponse.json();
67
+ fragmentsData = batchData.fragments || {};
68
+ if (batchData.errors) {
69
+ Object.entries(batchData.errors).forEach(([paneId, error]) => {
70
+ fragmentsData[paneId] =
71
+ `<div class="error">Failed to load pane ${paneId}: ${error}</div>`;
72
+ });
73
+ }
74
+ } else {
75
+ const failedFragmentsResponse = await handleFailedResponse(
76
+ batchResponse,
77
+ goBackend,
78
+ tenantId,
79
+ Astro.url.pathname
80
+ );
81
+ if (failedFragmentsResponse) {
82
+ return failedFragmentsResponse;
83
+ }
84
+ }
85
+ } catch (error) {
86
+ console.error('Error fetching fragments:', error);
87
+ return Astro.redirect(
88
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
89
+ );
90
+ }
91
+
92
+ if (!fragmentsData) {
93
+ return Astro.redirect(
94
+ `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
95
+ );
96
+ }
97
+
98
+ const fullContentMap = await getFullContentMap(tenantId);
99
+ const brandConfig = await getBrandConfig(tenantId);
100
+
101
+ if (!brandConfig.SITE_INIT) {
102
+ return Astro.redirect('/storykeep');
103
+ }
104
+ ---
105
+
106
+ <Layout
107
+ title={storyfragmentTitle}
108
+ slug={lookup || brandConfig.HOME_SLUG}
109
+ menu={storyData.menu || null}
110
+ created={storyData.created}
111
+ isContext={false}
112
+ isStoryKeep={false}
113
+ isEditable={true}
114
+ brandConfig={brandConfig}
115
+ sessionId={sessionId}
116
+ impressions={storyData.impressions || []}
117
+ storyfragmentId={storyfragmentId}
118
+ >
119
+ <main id="main-content" class="min-h-screen w-full">
120
+ <div class="panes-container">
121
+ {
122
+ paneIds.map((paneId: string) => (
123
+ <div
124
+ id={`pane-${paneId}`}
125
+ data-pane-id={paneId}
126
+ class="pane-fragment-container"
127
+ hx-get={`/api/v1/fragments/panes/${paneId}`}
128
+ hx-trigger="refresh"
129
+ hx-swap="innerHTML"
130
+ >
131
+ {codeHookTargets[paneId] ? (
132
+ <div class="overflow-hidden">
133
+ <CodeHook
134
+ target={codeHookTargets[paneId]}
135
+ paneId={paneId}
136
+ fullContentMap={fullContentMap}
137
+ noPaneId={true}
138
+ />
139
+ </div>
140
+ ) : (
141
+ <Fragment set:html={fragmentsData[paneId] || ''} />
142
+ )}
143
+ </div>
144
+ ))
145
+ }
146
+ </div>
147
+ </main>
148
+ </Layout>
@@ -0,0 +1,101 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const GET: APIRoute = async ({ request }) => {
4
+ const goBackend =
5
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+ const tenantId =
7
+ request.headers.get('X-Tenant-ID') ||
8
+ import.meta.env.PUBLIC_TENANTID ||
9
+ 'default';
10
+
11
+ try {
12
+ // Get Authorization header from frontend
13
+ const authHeader = request.headers.get('Authorization');
14
+
15
+ if (!authHeader) {
16
+ return new Response(
17
+ JSON.stringify({
18
+ profile: null,
19
+ }),
20
+ {
21
+ status: 200,
22
+ headers: { 'Content-Type': 'application/json' },
23
+ }
24
+ );
25
+ }
26
+
27
+ // Create abort controller for request timeout
28
+ const controller = new AbortController();
29
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
30
+
31
+ try {
32
+ // Forward request to Go backend
33
+ const response = await fetch(`${goBackend}/api/v1/auth/profile/decode`, {
34
+ method: 'GET',
35
+ headers: {
36
+ Authorization: authHeader,
37
+ 'X-Tenant-ID': tenantId,
38
+ },
39
+ signal: controller.signal,
40
+ });
41
+
42
+ clearTimeout(timeoutId);
43
+
44
+ // Get response from Go backend
45
+ const data = await response.json();
46
+
47
+ // Return Go backend response as-is
48
+ return new Response(JSON.stringify(data), {
49
+ status: response.status,
50
+ headers: {
51
+ 'Content-Type': 'application/json',
52
+ 'Access-Control-Allow-Origin': '*',
53
+ 'Access-Control-Allow-Methods': 'GET, OPTIONS',
54
+ 'Access-Control-Allow-Headers':
55
+ 'Content-Type, Authorization, X-Tenant-ID',
56
+ },
57
+ });
58
+ } catch (fetchError) {
59
+ clearTimeout(timeoutId);
60
+
61
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
62
+ console.error('Profile decode request timeout');
63
+ return new Response(
64
+ JSON.stringify({
65
+ profile: null,
66
+ }),
67
+ {
68
+ status: 408,
69
+ headers: { 'Content-Type': 'application/json' },
70
+ }
71
+ );
72
+ }
73
+ throw fetchError;
74
+ }
75
+ } catch (error) {
76
+ console.error('Profile decode API proxy error:', error);
77
+
78
+ return new Response(
79
+ JSON.stringify({
80
+ profile: null,
81
+ }),
82
+ {
83
+ status: 500,
84
+ headers: { 'Content-Type': 'application/json' },
85
+ }
86
+ );
87
+ }
88
+ };
89
+
90
+ // Handle OPTIONS for CORS preflight
91
+ export const OPTIONS: APIRoute = async () => {
92
+ return new Response(null, {
93
+ status: 200,
94
+ headers: {
95
+ 'Access-Control-Allow-Origin': '*',
96
+ 'Access-Control-Allow-Methods': 'GET, OPTIONS',
97
+ 'Access-Control-Allow-Headers':
98
+ 'Content-Type, Authorization, X-Tenant-ID',
99
+ },
100
+ });
101
+ };
@@ -0,0 +1,122 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const POST: APIRoute = async ({ request }) => {
4
+ try {
5
+ // Parse request body
6
+ const body = await request.json();
7
+ const { password, redirect } = body;
8
+
9
+ if (!password) {
10
+ return new Response(
11
+ JSON.stringify({ success: false, error: 'Password is required' }),
12
+ {
13
+ status: 400,
14
+ headers: { 'Content-Type': 'application/json' },
15
+ }
16
+ );
17
+ }
18
+
19
+ // Get tenant info from environment
20
+ const tenantId =
21
+ request.headers.get('X-Tenant-ID') ||
22
+ import.meta.env.PUBLIC_TENANTID ||
23
+ 'default';
24
+ const backendUrl =
25
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
26
+
27
+ // Prepare request to Go backend
28
+ const backendRequest = {
29
+ password,
30
+ tenantId,
31
+ };
32
+
33
+ // Create abort controller for request timeout
34
+ const controller = new AbortController();
35
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
36
+
37
+ try {
38
+ // Call Go backend login endpoint
39
+ const response = await fetch(`${backendUrl}/api/v1/auth/login`, {
40
+ method: 'POST',
41
+ headers: {
42
+ 'Content-Type': 'application/json',
43
+ 'X-Tenant-ID': tenantId,
44
+ },
45
+ body: JSON.stringify(backendRequest),
46
+ signal: controller.signal,
47
+ });
48
+
49
+ clearTimeout(timeoutId);
50
+
51
+ const result = await response.json();
52
+
53
+ if (response.ok && result.status === 'ok') {
54
+ // Get Set-Cookie header from backend response
55
+ const setCookieHeader = response.headers.get('Set-Cookie');
56
+
57
+ // Build response headers
58
+ const responseHeaders: Record<string, string> = {
59
+ 'Content-Type': 'application/json',
60
+ };
61
+
62
+ if (setCookieHeader) {
63
+ responseHeaders['Set-Cookie'] = setCookieHeader;
64
+ }
65
+
66
+ // Success response
67
+ return new Response(
68
+ JSON.stringify({
69
+ success: true,
70
+ role: result.role || 'authenticated',
71
+ redirect: redirect || '/storykeep',
72
+ }),
73
+ {
74
+ status: 200,
75
+ headers: responseHeaders,
76
+ }
77
+ );
78
+ } else {
79
+ // Login failed
80
+ return new Response(
81
+ JSON.stringify({
82
+ success: false,
83
+ error: result.error || 'Invalid credentials',
84
+ }),
85
+ {
86
+ status: 401,
87
+ headers: { 'Content-Type': 'application/json' },
88
+ }
89
+ );
90
+ }
91
+ } catch (fetchError) {
92
+ clearTimeout(timeoutId);
93
+
94
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
95
+ console.error('Login request timeout');
96
+ return new Response(
97
+ JSON.stringify({
98
+ success: false,
99
+ error: 'Request timeout - please try again',
100
+ }),
101
+ {
102
+ status: 408,
103
+ headers: { 'Content-Type': 'application/json' },
104
+ }
105
+ );
106
+ }
107
+ throw fetchError;
108
+ }
109
+ } catch (error) {
110
+ console.error('Login API error:', error);
111
+ return new Response(
112
+ JSON.stringify({
113
+ success: false,
114
+ error: 'Internal server error',
115
+ }),
116
+ {
117
+ status: 500,
118
+ headers: { 'Content-Type': 'application/json' },
119
+ }
120
+ );
121
+ }
122
+ };
@@ -0,0 +1,37 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const POST: APIRoute = async ({ cookies }) => {
4
+ try {
5
+ // Clear admin and editor auth cookies
6
+ cookies.delete('admin_auth', {
7
+ path: '/',
8
+ });
9
+
10
+ cookies.delete('editor_auth', {
11
+ path: '/',
12
+ });
13
+
14
+ return new Response(
15
+ JSON.stringify({
16
+ success: true,
17
+ message: 'Logged out successfully',
18
+ }),
19
+ {
20
+ status: 200,
21
+ headers: { 'Content-Type': 'application/json' },
22
+ }
23
+ );
24
+ } catch (error) {
25
+ console.error('Logout API error:', error);
26
+ return new Response(
27
+ JSON.stringify({
28
+ success: false,
29
+ error: 'Logout failed',
30
+ }),
31
+ {
32
+ status: 500,
33
+ headers: { 'Content-Type': 'application/json' },
34
+ }
35
+ );
36
+ }
37
+ };
@@ -0,0 +1,76 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const POST: APIRoute = async ({ request }) => {
4
+ const GO_BACKEND =
5
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+
7
+ try {
8
+ // Forward the request to the Go backend
9
+ const body = await request.text();
10
+
11
+ // Create abort controller for request timeout
12
+ const controller = new AbortController();
13
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
14
+
15
+ try {
16
+ const response = await fetch(`${GO_BACKEND}/api/v1/auth/profile`, {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'X-Tenant-ID': import.meta.env.PUBLIC_TENANTID || 'default',
21
+ ...(request.headers.get('Authorization') && {
22
+ Authorization: request.headers.get('Authorization')!,
23
+ }),
24
+ },
25
+ body: body,
26
+ signal: controller.signal,
27
+ });
28
+
29
+ clearTimeout(timeoutId);
30
+
31
+ const data = await response.json();
32
+
33
+ // Return the response with the same status code
34
+ return new Response(JSON.stringify(data), {
35
+ status: response.status,
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ },
39
+ });
40
+ } catch (fetchError) {
41
+ clearTimeout(timeoutId);
42
+
43
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
44
+ console.error('Profile request timeout');
45
+ return new Response(
46
+ JSON.stringify({
47
+ success: false,
48
+ error: 'Request timeout - please try again',
49
+ }),
50
+ {
51
+ status: 408,
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ },
55
+ }
56
+ );
57
+ }
58
+ throw fetchError;
59
+ }
60
+ } catch (error) {
61
+ console.error('Profile API proxy error:', error);
62
+
63
+ return new Response(
64
+ JSON.stringify({
65
+ success: false,
66
+ error: 'Failed to connect to backend service',
67
+ }),
68
+ {
69
+ status: 500,
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ },
73
+ }
74
+ );
75
+ }
76
+ };