astro-tractstack 2.0.0-rc.9 → 2.0.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 (142) hide show
  1. package/LICENSE +8 -97
  2. package/README.md +7 -5
  3. package/bin/create-tractstack.js +31 -8
  4. package/dist/index.js +106 -29
  5. package/package.json +10 -5
  6. package/templates/css/frontend.css +1 -1
  7. package/templates/custom/minimal/CodeHook.astro +13 -12
  8. package/templates/custom/minimal/CustomRoutes.astro +25 -31
  9. package/templates/custom/with-examples/CodeHook.astro +22 -11
  10. package/templates/custom/with-examples/CustomRoutes.astro +4 -8
  11. package/templates/custom/with-examples/ProductCard.astro +29 -0
  12. package/templates/custom/with-examples/ProductCardWrapper.astro +43 -0
  13. package/templates/custom/with-examples/ProductGrid.astro +64 -0
  14. package/templates/custom/with-examples/pages/Collections.astro +58 -98
  15. package/templates/gitignore +42 -0
  16. package/templates/prettierignore +5 -0
  17. package/templates/prettierrc +19 -0
  18. package/templates/src/client/app.js +127 -0
  19. package/templates/src/client/htmx.min.js +3519 -0
  20. package/templates/src/client/view.js +429 -0
  21. package/templates/src/components/Footer.astro +4 -9
  22. package/templates/src/components/Header.astro +67 -60
  23. package/templates/src/components/Menu.tsx +188 -52
  24. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +2 -2
  25. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +9 -13
  26. package/templates/src/components/codehooks/EpinetTableView.tsx +11 -7
  27. package/templates/src/components/codehooks/EpinetWrapper.tsx +1 -0
  28. package/templates/src/components/codehooks/FeaturedArticle.astro +105 -0
  29. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +318 -0
  30. package/templates/src/components/codehooks/ListContent.astro +32 -162
  31. package/templates/src/components/codehooks/ListContentSetup.tsx +43 -138
  32. package/templates/src/components/codehooks/ProductCardSetup.tsx +152 -0
  33. package/templates/src/components/codehooks/ProductGridSetup.tsx +274 -0
  34. package/templates/src/components/codehooks/SearchWidget.tsx +453 -0
  35. package/templates/src/components/compositor/Node.tsx +3 -6
  36. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +21 -11
  37. package/templates/src/components/compositor/elements/BunnyVideo.tsx +21 -20
  38. package/templates/src/components/compositor/nodes/Pane.tsx +51 -21
  39. package/templates/src/components/compositor/nodes/RenderChildren.tsx +6 -1
  40. package/templates/src/components/compositor/nodes/Widget.tsx +16 -2
  41. package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +155 -0
  42. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +20 -1
  43. package/templates/src/components/edit/Header.tsx +10 -4
  44. package/templates/src/components/edit/PanelSwitch.tsx +11 -7
  45. package/templates/src/components/edit/SettingsPanel.tsx +29 -18
  46. package/templates/src/components/edit/ToolBar.tsx +1 -28
  47. package/templates/src/components/edit/ToolMode.tsx +45 -32
  48. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +12 -2
  49. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +8 -2
  50. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +1 -1
  51. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +17 -27
  52. package/templates/src/components/edit/pane/PageGenSelector.tsx +16 -16
  53. package/templates/src/components/edit/pane/PageGenSpecial.tsx +26 -49
  54. package/templates/src/components/edit/pane/PageGen_preview.tsx +17 -2
  55. package/templates/src/components/edit/pane/PanePanel_path.tsx +2 -4
  56. package/templates/src/components/edit/pane/PanePanel_title.tsx +243 -76
  57. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +17 -19
  58. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +48 -37
  59. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +60 -55
  60. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +56 -50
  61. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +54 -47
  62. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +54 -44
  63. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +113 -138
  64. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +54 -40
  65. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +3 -3
  66. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +56 -49
  67. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +14 -5
  68. package/templates/src/components/edit/state/SaveModal.tsx +316 -169
  69. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +1 -1
  70. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +56 -55
  71. package/templates/src/components/edit/widgets/BunnyWidget.tsx +538 -59
  72. package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +656 -0
  73. package/templates/src/components/edit/widgets/ToggleWidget.tsx +9 -16
  74. package/templates/src/components/fields/ArtpackImage.tsx +4 -1
  75. package/templates/src/components/fields/BackgroundImage.tsx +1 -1
  76. package/templates/src/components/fields/BackgroundImageWrapper.tsx +127 -35
  77. package/templates/src/components/fields/ColorPickerCombo.tsx +66 -62
  78. package/templates/src/components/fields/ImageUpload.tsx +1 -1
  79. package/templates/src/components/fields/ViewportComboBox.tsx +59 -42
  80. package/templates/src/components/form/ActionBuilderBeliefSelector.tsx +117 -0
  81. package/templates/src/components/form/ActionBuilderField.tsx +306 -87
  82. package/templates/src/components/search/SearchModal.tsx +420 -0
  83. package/templates/src/components/search/SearchResults.tsx +367 -0
  84. package/templates/src/components/search/SearchWrapper.tsx +46 -0
  85. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -1
  86. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +34 -8
  87. package/templates/src/components/storykeep/Dashboard_Branding.tsx +1 -1
  88. package/templates/src/components/storykeep/Dashboard_Content.tsx +6 -0
  89. package/templates/src/components/storykeep/StoryKeepBackdrop.astro +87 -0
  90. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +38 -34
  91. package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +1 -1
  92. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +56 -8
  93. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +18 -3
  94. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +5 -8
  95. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +274 -228
  96. package/templates/src/components/storykeep/widgets/Wizard.tsx +14 -7
  97. package/templates/src/components/widgets/ImpressionWrapper.tsx +0 -1
  98. package/templates/src/constants/shapes.ts +9 -0
  99. package/templates/src/constants.ts +2121 -16
  100. package/templates/src/hooks/useSearch.ts +228 -0
  101. package/templates/src/layouts/Layout.astro +213 -104
  102. package/templates/src/lib/storyData.ts +4 -1
  103. package/templates/src/pages/[...slug]/edit.astro +14 -14
  104. package/templates/src/pages/[...slug].astro +82 -21
  105. package/templates/src/pages/api/orphan-analysis.ts +0 -1
  106. package/templates/src/pages/api/tailwind.ts +23 -21
  107. package/templates/src/pages/context/[...contextSlug]/edit.astro +14 -14
  108. package/templates/src/pages/context/[...contextSlug].astro +7 -2
  109. package/templates/src/pages/storykeep/advanced.astro +5 -4
  110. package/templates/src/pages/storykeep/branding.astro +5 -4
  111. package/templates/src/pages/storykeep/content.astro +5 -4
  112. package/templates/src/pages/storykeep/init.astro +40 -1
  113. package/templates/src/pages/storykeep/login.astro +1 -1
  114. package/templates/src/pages/storykeep.astro +5 -4
  115. package/templates/src/stores/nodes.ts +59 -88
  116. package/templates/src/stores/orphanAnalysis.ts +19 -21
  117. package/templates/src/stores/storykeep.ts +7 -0
  118. package/templates/src/types/compositorTypes.ts +6 -0
  119. package/templates/src/types/tractstack.ts +17 -0
  120. package/templates/src/utils/actions/lispLexer.ts +2 -2
  121. package/templates/src/utils/actions/preParse_Action.ts +3 -0
  122. package/templates/src/utils/api/beliefHelpers.ts +12 -36
  123. package/templates/src/utils/api/menuHelpers.ts +2 -2
  124. package/templates/src/utils/api.ts +26 -0
  125. package/templates/src/utils/compositor/TemplateNodes.ts +7 -0
  126. package/templates/src/utils/compositor/allowInsert.ts +5 -3
  127. package/templates/src/utils/compositor/nodesHelper.ts +4 -0
  128. package/templates/src/utils/compositor/processMarkdown.ts +16 -2
  129. package/templates/src/utils/compositor/reduceNodesClassNames.ts +4 -0
  130. package/templates/src/utils/compositor/templateMarkdownStyles.ts +13 -13
  131. package/templates/src/utils/compositor/typeGuards.ts +1 -0
  132. package/templates/src/utils/customHelpers.ts +38 -0
  133. package/templates/src/utils/helpers.ts +2 -2
  134. package/templates/src/utils/layout.ts +65 -144
  135. package/utils/inject-files.ts +95 -18
  136. package/templates/src/client/analytics-events.js +0 -207
  137. package/templates/src/client/belief-events.js +0 -191
  138. package/templates/src/client/sse.js +0 -613
  139. package/templates/src/components/codehooks/FeaturedContent.astro +0 -273
  140. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +0 -738
  141. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +0 -128
  142. package/templates/src/components/edit/pane/PanePanel_slug.tsx +0 -219
@@ -168,16 +168,10 @@ for (const [key, value] of Astro.url.searchParams) {
168
168
  <StoryKeepToolMode isContext={false} client:only="react" />
169
169
 
170
170
  <!-- Main Content Area -->
171
- <main
172
- id="mainContent"
173
- class="relative flex-1"
174
- style={{
175
- paddingBottom: 'var(--bottom-right-controls-bottom-offset, 16px)',
176
- }}
177
- >
171
+ <main id="mainContent" class="relative flex-1 overflow-x-auto">
178
172
  <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
179
173
  <div
180
- class="h-fit min-h-screen"
174
+ class="h-fit min-h-screen pb-96"
181
175
  style={{
182
176
  backgroundImage:
183
177
  'repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(0,0,0,0.05) 10px, rgba(0,0,0,0.05) 20px)',
@@ -201,15 +195,22 @@ for (const [key, value] of Astro.url.searchParams) {
201
195
  <!-- Floating Controls (Settings Panel & HUD OR ToolBar) -->
202
196
  <aside
203
197
  id="settingsControls"
204
- 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
+ class="z-101 pointer-events-none fixed bottom-16 right-2 flex flex-col items-end gap-2 md:bottom-2"
205
199
  >
206
- <div class="pointer-events-auto">
200
+ <div class="pointer-events-none flex-grow"></div>
201
+
202
+ {/* Toolbar's wrapper: Does not grow or shrink */}
203
+ <div class="pointer-events-auto flex-shrink-0">
207
204
  <StoryKeepToolBar client:only="react" />
208
205
  </div>
209
- <div class="pointer-events-auto">
206
+
207
+ {
208
+ /* Settings Panel's wrapper: Grows, shrinks, and will be positioned by our script */
209
+ }
210
+ <div class="pointer-events-auto max-h-full">
210
211
  <SettingsPanel
211
212
  config={brandConfig}
212
- availableCodeHooks={['featured-content', 'list-content', 'bunny-video']}
213
+ availableCodeHooks={Object.keys(codeHookComponents)}
213
214
  client:only="react"
214
215
  />
215
216
  </div>
@@ -217,7 +218,6 @@ for (const [key, value] of Astro.url.searchParams) {
217
218
  </Layout>
218
219
 
219
220
  <script>
220
- import { setupLayoutObservers, setupLayoutStyles } from '@/utils/layout';
221
- setupLayoutStyles();
221
+ import { setupLayoutObservers } from '@/utils/layout';
222
222
  setupLayoutObservers();
223
223
  </script>
@@ -30,7 +30,9 @@ let storyData;
30
30
  try {
31
31
  storyData = await getStoryData(Astro, lookup, sessionId, tenantId);
32
32
  } catch (error) {
33
- if (error instanceof Response) {
33
+ if (error instanceof Response && error.status === 404) {
34
+ return Astro.redirect('/404');
35
+ } else if (error instanceof Response) {
34
36
  return error;
35
37
  }
36
38
  console.error('Error fetching storyfragment:', error);
@@ -43,6 +45,7 @@ const storyfragmentId = storyData.id;
43
45
  const storyfragmentTitle = storyData.title || 'Untitled Story';
44
46
  const paneIds = storyData.paneIds || [];
45
47
  const codeHookTargets = storyData.codeHookTargets || {};
48
+ const resourcesPayload = storyData.resourcesPayload || {};
46
49
 
47
50
  if (paneIds.length === 0) {
48
51
  console.log(`Empty Story Fragment. Redirecting to /storykeep`);
@@ -101,11 +104,22 @@ const brandConfig = await getBrandConfig(tenantId);
101
104
  if (!brandConfig.SITE_INIT) {
102
105
  return Astro.redirect('/storykeep');
103
106
  }
107
+
108
+ const ogImage =
109
+ typeof storyData.socialImagePath === `string`
110
+ ? storyData.socialImagePath
111
+ : undefined;
112
+ const paneSlugLookup: Record<string, string> = {};
113
+ paneIds.forEach((paneId: string) => {
114
+ const paneData = fullContentMap.find((item) => item.id === paneId);
115
+ paneSlugLookup[paneId] = paneData?.slug || paneId;
116
+ });
104
117
  ---
105
118
 
106
119
  <Layout
107
120
  title={storyfragmentTitle}
108
121
  slug={lookup || brandConfig.HOME_SLUG}
122
+ ogImage={ogImage}
109
123
  menu={storyData.menu || null}
110
124
  created={storyData.created}
111
125
  isContext={false}
@@ -120,26 +134,73 @@ if (!brandConfig.SITE_INIT) {
120
134
  <div class="panes-container">
121
135
  {
122
136
  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
- )}
137
+ <div id={paneSlugLookup[paneId]}>
138
+ <div
139
+ id={`pane-${paneId}`}
140
+ data-pane-id={paneId}
141
+ class="pane-fragment-container"
142
+ style={
143
+ !codeHookTargets[paneId]
144
+ ? undefined
145
+ : !storyData.codeHookVisibility?.[paneId]
146
+ ? 'display:none;'
147
+ : 'display:block;'
148
+ }
149
+ hx-get={`/api/v1/fragments/panes/${paneId}`}
150
+ hx-trigger="refresh"
151
+ hx-swap="innerHTML scroll:none"
152
+ >
153
+ {codeHookTargets[paneId] ? (
154
+ <div class="relative overflow-hidden">
155
+ <CodeHook
156
+ target={codeHookTargets[paneId]}
157
+ options={(() => {
158
+ const optionsStr =
159
+ codeHookTargets[paneId + '-' + codeHookTargets[paneId]];
160
+ return optionsStr
161
+ ? { params: { options: optionsStr } }
162
+ : undefined;
163
+ })()}
164
+ fullContentMap={fullContentMap}
165
+ resourcesPayload={resourcesPayload}
166
+ />
167
+ <div id={`pane-${paneId}-unset`}>
168
+ {Array.isArray(storyData.codeHookVisibility?.[paneId]) && (
169
+ <button
170
+ type="button"
171
+ class="text-mydarkgrey absolute right-2 top-2 z-10 rounded-full bg-white p-1.5 hover:bg-black hover:text-white"
172
+ title="Go Back"
173
+ hx-post="/api/v1/state"
174
+ hx-trigger="click"
175
+ hx-swap="none"
176
+ hx-vals={JSON.stringify({
177
+ unsetBeliefIds:
178
+ storyData.codeHookVisibility[paneId].join(','),
179
+ paneId: paneId,
180
+ })}
181
+ hx-preserve="true"
182
+ >
183
+ <svg
184
+ class="h-6 w-6"
185
+ fill="none"
186
+ viewBox="0 0 24 24"
187
+ stroke-width="1.5"
188
+ stroke="currentColor"
189
+ >
190
+ <path
191
+ stroke-linecap="round"
192
+ stroke-linejoin="round"
193
+ d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3"
194
+ />
195
+ </svg>
196
+ </button>
197
+ )}
198
+ </div>
199
+ </div>
200
+ ) : (
201
+ <Fragment set:html={fragmentsData[paneId] || ''} />
202
+ )}
203
+ </div>
143
204
  </div>
144
205
  ))
145
206
  }
@@ -69,7 +69,6 @@ export const GET: APIRoute = async ({ request }) => {
69
69
  status: 200,
70
70
  headers: {
71
71
  'Content-Type': 'application/json',
72
- 'Cache-Control': 'public, max-age=300', // Cache for 5 minutes
73
72
  },
74
73
  });
75
74
  } catch (fetchError) {
@@ -11,24 +11,6 @@ export const POST: APIRoute = async ({ request }) => {
11
11
  request.headers.get('X-Tenant-ID') ||
12
12
  import.meta.env.PUBLIC_TENANTID ||
13
13
  'default';
14
- const isMultiTenant =
15
- import.meta.env.PUBLIC_ENABLE_MULTI_TENANT === 'true' &&
16
- tenantId !== 'default';
17
-
18
- if (isMultiTenant) {
19
- return new Response('CSS generation disabled in multi-tenant mode', {
20
- status: 403,
21
- });
22
- }
23
-
24
- // Read tailwind config from project root
25
- const configPath = path.join(process.cwd(), 'tailwind.config.cjs');
26
- const configContent = await fs.readFile(configPath, 'utf-8');
27
- const tailwindConfig = new Function(
28
- 'module',
29
- 'exports',
30
- configContent + '; return module.exports;'
31
- )({ exports: {} }, {});
32
14
 
33
15
  const goBackend =
34
16
  import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
@@ -63,9 +45,29 @@ export const POST: APIRoute = async ({ request }) => {
63
45
  ...new Set([...(cleanClasses || []), ...(dirtyClasses || [])]),
64
46
  ];
65
47
 
66
- // Generate CSS using JIT
67
- const tailwindCss = createTailwindcss({ tailwindConfig });
68
- const htmlContent = [`<span class="${allClasses.join(' ')}"></span>`];
48
+ // Read base tailwind config from project root
49
+ const configPath = path.join(process.cwd(), 'tailwind.config.cjs');
50
+ const configContent = await fs.readFile(configPath, 'utf-8');
51
+ const baseTailwindConfig = new Function(
52
+ 'module',
53
+ 'exports',
54
+ configContent + '; return module.exports;'
55
+ )({ exports: {} }, {});
56
+
57
+ // Create config with safelist
58
+ const tailwindConfigWithSafelist = {
59
+ ...baseTailwindConfig,
60
+ safelist: allClasses,
61
+ };
62
+
63
+ // Generate CSS using JIT with safelist
64
+ const tailwindCss = createTailwindcss({
65
+ tailwindConfig: tailwindConfigWithSafelist,
66
+ });
67
+
68
+ // Use simple HTML content since safelist should handle class generation
69
+ const htmlContent = ['<div>Using the safelist</div>'];
70
+
69
71
  const generatedCss = await tailwindCss.generateStylesFromContent(
70
72
  `@tailwind base; @tailwind utilities;`,
71
73
  htmlContent
@@ -159,16 +159,10 @@ for (const [key, value] of Astro.url.searchParams) {
159
159
  <StoryKeepToolMode isContext={true} client:only="react" />
160
160
 
161
161
  <!-- Main Content Area -->
162
- <main
163
- id="mainContent"
164
- class="relative flex-1"
165
- style={{
166
- paddingBottom: 'var(--bottom-right-controls-bottom-offset, 16px)',
167
- }}
168
- >
162
+ <main id="mainContent" class="relative flex-1 overflow-x-auto">
169
163
  <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
170
164
  <div
171
- class="h-fit min-h-screen"
165
+ class="h-fit min-h-screen pb-96"
172
166
  style={{
173
167
  backgroundImage:
174
168
  'repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(0,0,0,0.05) 10px, rgba(0,0,0,0.05) 20px)',
@@ -192,15 +186,22 @@ for (const [key, value] of Astro.url.searchParams) {
192
186
  <!-- Floating Controls (Settings Panel & HUD OR ToolBar) -->
193
187
  <aside
194
188
  id="settingsControls"
195
- class="z-101 pointer-events-none fixed bottom-24 right-0 flex max-h-screen flex-col items-end gap-2 overflow-y-auto p-4 md:bottom-0"
189
+ class="z-101 pointer-events-none fixed bottom-16 right-2 flex flex-col items-end gap-2 md:bottom-2"
196
190
  >
197
- <div class="pointer-events-auto">
191
+ <div class="pointer-events-none flex-grow"></div>
192
+
193
+ {/* Toolbar's wrapper: Does not grow or shrink */}
194
+ <div class="pointer-events-auto flex-shrink-0">
198
195
  <StoryKeepToolBar client:only="react" />
199
196
  </div>
200
- <div class="pointer-events-auto">
197
+
198
+ {
199
+ /* Settings Panel's wrapper: Grows, shrinks, and will be positioned by our script */
200
+ }
201
+ <div class="pointer-events-auto max-h-full">
201
202
  <SettingsPanel
202
203
  config={brandConfig}
203
- availableCodeHooks={['featured-content', 'list-content', 'bunny-video']}
204
+ availableCodeHooks={Object.keys(codeHookComponents)}
204
205
  client:only="react"
205
206
  />
206
207
  </div>
@@ -208,7 +209,6 @@ for (const [key, value] of Astro.url.searchParams) {
208
209
  </Layout>
209
210
 
210
211
  <script>
211
- import { setupLayoutObservers, setupLayoutStyles } from '@/utils/layout';
212
- setupLayoutStyles();
212
+ import { setupLayoutObservers } from '@/utils/layout';
213
213
  setupLayoutObservers();
214
214
  </script>
@@ -59,6 +59,7 @@ try {
59
59
  const paneId = contextPaneData.id;
60
60
  const paneTitle = contextPaneData.title || 'Context';
61
61
  const codeHookTarget = contextPaneData.codeHookTarget || null;
62
+ const resourcesPayload = storyData.resourcesPayload || {};
62
63
 
63
64
  // Get rendered fragment for the context pane
64
65
  let fragmentData = '';
@@ -119,11 +120,15 @@ if (!brandConfig.SITE_INIT) {
119
120
  class="context-pane-container"
120
121
  hx-get={`/api/v1/fragments/panes/${paneId}`}
121
122
  hx-trigger="refresh"
122
- hx-swap="innerHTML"
123
+ hx-swap="innerHTML scroll:none"
123
124
  >
124
125
  {
125
126
  codeHookTarget ? (
126
- <CodeHook target={codeHookTarget} fullContentMap={fullContentMap} />
127
+ <CodeHook
128
+ target={codeHookTarget}
129
+ resourcesPayload={resourcesPayload}
130
+ fullContentMap={fullContentMap}
131
+ />
127
132
  ) : (
128
133
  <Fragment set:html={fragmentData} />
129
134
  )
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import Layout from '@/layouts/Layout.astro';
3
+ import StoryKeepBackdrop from '@/components/storykeep/StoryKeepBackdrop.astro';
3
4
  import StoryKeepDashboard from '@/components/storykeep/Dashboard';
4
5
  import StoryKeepDashboard_Advanced from '@/components/storykeep/Dashboard_Advanced';
5
6
  import { requireAdminOrEditor, isAuthenticated, isAdmin } from '@/utils/auth';
@@ -40,11 +41,10 @@ if (initializing) {
40
41
  const title = 'Advanced | StoryKeep';
41
42
 
42
43
  let fullContentMap;
43
- let homeSlug = 'hello';
44
+ const homeSlug = brandConfig.HOME_SLUG || 'hello';
44
45
 
45
46
  try {
46
47
  fullContentMap = await getFullContentMap(tenantId);
47
- homeSlug = fullContentMap.find((item) => item.isHome)?.slug || 'hello';
48
48
  } catch (error) {
49
49
  return Astro.redirect(
50
50
  `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
@@ -53,8 +53,9 @@ try {
53
53
  ---
54
54
 
55
55
  <Layout title={title} slug="storykeep" isStoryKeep={true}>
56
- <main id="main-content" class="min-h-screen w-full">
57
- <div class="p-8">
56
+ <main id="main-content" class="relative min-h-screen w-full">
57
+ <StoryKeepBackdrop brandConfig={brandConfig} />
58
+ <div class="max-w-5xl p-3.5 md:p-8">
58
59
  <StoryKeepDashboard
59
60
  client:only="react"
60
61
  fullContentMap={fullContentMap}
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import Layout from '@/layouts/Layout.astro';
3
+ import StoryKeepBackdrop from '@/components/storykeep/StoryKeepBackdrop.astro';
3
4
  import BrandingPageWrapper from '@/components/storykeep/state/BrandingWrapper';
4
5
  import { requireAdminOrEditor, isAuthenticated, isAdmin } from '@/utils/auth';
5
6
  import { getFullContentMap } from '@/stores/analytics';
@@ -29,11 +30,10 @@ const initializing = !brandConfig.SITE_INIT;
29
30
  const title = 'Branding | StoryKeep';
30
31
 
31
32
  let fullContentMap;
32
- let homeSlug = 'hello';
33
+ const homeSlug = brandConfig.HOME_SLUG || 'hello';
33
34
 
34
35
  try {
35
36
  fullContentMap = await getFullContentMap(tenantId);
36
- homeSlug = fullContentMap.find((item) => item.isHome)?.slug || 'hello';
37
37
  } catch (error) {
38
38
  return Astro.redirect(
39
39
  `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
@@ -42,8 +42,9 @@ try {
42
42
  ---
43
43
 
44
44
  <Layout title={title} slug="storykeep" isStoryKeep={true}>
45
- <main id="main-content" class="min-h-screen w-full">
46
- <div class="p-8">
45
+ <main id="main-content" class="relative min-h-screen w-full">
46
+ <StoryKeepBackdrop brandConfig={brandConfig} />
47
+ <div class="max-w-5xl p-3.5 md:p-8">
47
48
  <BrandingPageWrapper
48
49
  client:only="react"
49
50
  fullContentMap={fullContentMap}
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import Layout from '@/layouts/Layout.astro';
3
+ import StoryKeepBackdrop from '@/components/storykeep/StoryKeepBackdrop.astro';
3
4
  import StoryKeepDashboard from '@/components/storykeep/Dashboard';
4
5
  import StoryKeepDashboard_Content from '@/components/storykeep/Dashboard_Content';
5
6
  import { requireAdminOrEditor, isAuthenticated, isAdmin } from '@/utils/auth';
@@ -36,11 +37,10 @@ const title = 'Content | StoryKeep';
36
37
  const createMenu = Astro.url.searchParams.has('create-menu');
37
38
 
38
39
  let fullContentMap;
39
- let homeSlug = 'hello';
40
+ const homeSlug = brandConfig.HOME_SLUG || 'hello';
40
41
 
41
42
  try {
42
43
  fullContentMap = await getFullContentMap(tenantId);
43
- homeSlug = fullContentMap.find((item) => item.isHome)?.slug || 'hello';
44
44
  } catch (error) {
45
45
  return Astro.redirect(
46
46
  `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
@@ -49,8 +49,9 @@ try {
49
49
  ---
50
50
 
51
51
  <Layout title={title} slug="storykeep" isStoryKeep={true}>
52
- <main id="main-content" class="min-h-screen w-full">
53
- <div class="p-8">
52
+ <main id="main-content" class="relative min-h-screen w-full">
53
+ <StoryKeepBackdrop brandConfig={brandConfig} />
54
+ <div class="max-w-5xl p-3.5 md:p-8">
54
55
  <StoryKeepDashboard
55
56
  client:only="react"
56
57
  fullContentMap={fullContentMap}
@@ -31,6 +31,45 @@ const mainStylesUrl = isDev
31
31
  <link rel="stylesheet" href={mainStylesUrl} />
32
32
  </head>
33
33
  <body class="h-full">
34
- <RegistrationForm client:load isInitMode={true} />
34
+ <div class="max-w-5xl p-3.5 md:p-8">
35
+ <RegistrationForm client:load isInitMode={true} />
36
+ </div>
37
+
38
+ <script>
39
+ // Ensure clean slate for fresh installation
40
+ (function initCleanSlate() {
41
+ try {
42
+ // Clear admin/editor auth cookies
43
+ document.cookie =
44
+ 'admin_auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
45
+ document.cookie =
46
+ 'editor_auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
47
+
48
+ // Clear all TractStack localStorage items
49
+ const tractStackKeys = [];
50
+ for (let i = 0; i < localStorage.length; i++) {
51
+ const key = localStorage.key(i);
52
+ if (key && key.startsWith('tractstack_')) {
53
+ tractStackKeys.push(key);
54
+ }
55
+ }
56
+ tractStackKeys.forEach((key) => localStorage.removeItem(key));
57
+
58
+ // Clear session-related items
59
+ localStorage.removeItem('tractstack_session_id');
60
+ localStorage.removeItem('tractstack_fingerprint');
61
+ localStorage.removeItem('tractstack_visit');
62
+ localStorage.removeItem('tractstack_entered_tracked');
63
+
64
+ // Clear session cookie
65
+ document.cookie =
66
+ 'tractstack_session_id=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
67
+
68
+ console.log('TractStack: Clean slate initialization complete');
69
+ } catch (error) {
70
+ console.warn('TractStack: Error during clean slate init:', error);
71
+ }
72
+ })();
73
+ </script>
35
74
  </body>
36
75
  </html>
@@ -75,7 +75,7 @@ const mainStylesUrl = isDev
75
75
  </h2>
76
76
  </div>
77
77
 
78
- <div class="mx-auto">
78
+ <div class="mx-auto max-w-sm">
79
79
  <div class="rounded-lg bg-white px-6 py-12 shadow-inner">
80
80
  <!-- Error message -->
81
81
  <div
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import Layout from '@/layouts/Layout.astro';
3
+ import StoryKeepBackdrop from '@/components/storykeep/StoryKeepBackdrop.astro';
3
4
  import StoryKeepDashboard from '@/components/storykeep/Dashboard';
4
5
  import StoryKeepDashboard_Analytics from '@/components/storykeep/Dashboard_Analytics';
5
6
  import { requireAdminOrEditor, isAuthenticated, isAdmin } from '@/utils/auth';
@@ -35,14 +36,13 @@ if (initializing) {
35
36
 
36
37
  const title = 'Analytics | StoryKeep';
37
38
 
39
+ const homeSlug = brandConfig.HOME_SLUG || 'hello';
38
40
  let fullContentMap;
39
- let homeSlug = 'hello';
40
41
 
41
42
  try {
42
43
  fullContentMap = await getFullContentMap(
43
44
  Astro.locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default'
44
45
  );
45
- homeSlug = fullContentMap.find((item) => item.isHome)?.slug || 'hello';
46
46
  } catch (error) {
47
47
  return Astro.redirect(
48
48
  `/maint?from=${encodeURIComponent(Astro.url.pathname)}`
@@ -51,8 +51,9 @@ try {
51
51
  ---
52
52
 
53
53
  <Layout title={title} isStoryKeep={true} slug="storykeep">
54
- <main id="main-content" class="min-h-screen w-full">
55
- <div class="p-3.5 md:p-8">
54
+ <main id="main-content" class="relative min-h-screen w-full">
55
+ <StoryKeepBackdrop brandConfig={brandConfig} />
56
+ <div class="max-w-5xl p-3.5 md:p-8">
56
57
  <StoryKeepDashboard
57
58
  client:only="react"
58
59
  fullContentMap={fullContentMap}