showcaseDataService.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. import { GreenPage, Block, DesignSettings, MediaSource, AIGCArticle, ThemeName, BackgroundType, FontFamily, ButtonShape, ButtonStyle, SideNavSettings, BannerSettings, HeaderBlock, TextBlock, ImageBlock, VideoBlock, LinkBlock, ProductBlock, NewsBlock, MapBlock, EmailBlock, PhoneBlock, PdfBlock, SocialBlock, NewsItemFromUrl, ChatBlock, EnterpriseInfoBlock, FormBlock, AwardBlock, FooterBlock, BannerType } from '../types';
  2. import { subDays } from 'date-fns';
  3. const themeColors = [
  4. 'from-green-400 to-blue-500',
  5. 'from-purple-500 to-pink-500',
  6. 'from-yellow-400 to-orange-600',
  7. 'from-teal-400 to-cyan-500',
  8. 'from-red-500 to-indigo-600',
  9. 'from-rose-400 to-red-500',
  10. ];
  11. const createInitialAIGCArticles = (): AIGCArticle[] => [
  12. {
  13. id: 'aigc-article-1',
  14. title: 'The Rise of AI in Modern Web Development',
  15. summary: 'An in-depth look at how artificial intelligence is revolutionizing the way we build and interact with websites, from automated testing to intelligent UI generation.',
  16. content: `
  17. <h2>The Dawn of a New Era</h2>
  18. <p>From automated testing to intelligent UI generation, AI is no longer a futuristic concept but a <strong>present-day tool for developers</strong>. The landscape of web development is shifting at an unprecedented pace, with machine learning models now capable of writing code, designing user interfaces, and even deploying applications.</p>
  19. <p>One of the most significant impacts is in the realm of UI/UX design. Tools powered by generative AI can create stunning, user-friendly mockups from simple text prompts. <em>This dramatically accelerates the prototyping phase</em>, allowing teams to iterate on ideas faster than ever before. We're seeing a future where the line between designer and developer blurs, thanks to these intelligent assistants.</p>
  20. <img src="https://picsum.photos/seed/ai-article-1/600/400" alt="AI and code" style="width: 100%; height: auto; border-radius: 8px; margin: 1em 0;" />
  21. <h2>Challenges and Opportunities</h2>
  22. <p>Of course, this revolution doesn't come without its challenges. Questions around code quality, security vulnerabilities in AI-generated scripts, and the ethical implications of job displacement are paramount. However, the opportunities are boundless. Developers can now focus on more complex architectural problems, leaving routine coding tasks to their AI partners. For more information, you can read this <a href="https://example.com" target="_blank" rel="noopener noreferrer">in-depth analysis</a>.</p>
  23. `,
  24. publicationDate: subDays(new Date(), 5).toISOString(),
  25. sourceType: 'generated',
  26. },
  27. {
  28. id: 'aigc-article-2',
  29. title: 'Sustainable Living: 10 Tips for an Eco-Friendly Home',
  30. summary: 'Discover simple yet effective ways to reduce your carbon footprint and create a greener living space, from your kitchen to your garden.',
  31. content: `
  32. <h2>It Starts at Home</h2>
  33. <p>Sustainability is more than just a buzzword; it's a lifestyle that begins right in our own homes. Creating an eco-friendly living space doesn't require a complete overhaul. Simple, consistent changes can lead to a significant positive impact on the environment and even your wallet.</p>
  34. <img src="https://picsum.photos/seed/eco-article-1/600/400" alt="A green home" style="width: 100%; height: auto; border-radius: 8px; margin: 1em 0;" />
  35. <h2>Practical Steps You Can Take Today</h2>
  36. <p>Here are a few tips to get started:</p>
  37. <ol>
  38. <li><strong>Reduce, Reuse, Recycle:</strong> The classic three R's are more important than ever.</li>
  39. <li><strong>Compost Food Scraps:</strong> Reduce landfill waste and create nutrient-rich soil for your garden.</li>
  40. <li><strong>Switch to LED Lighting:</strong> They use significantly less energy and last much longer than traditional bulbs.</li>
  41. <li><em>Fix Leaky Faucets:</em> A small drip can waste gallons of water every day.</li>
  42. </ol>
  43. <p>By adopting these habits, you contribute to a healthier planet for future generations. It's a journey of continuous learning and improvement. Check out <a href="https://example.com/eco" target="_blank" rel="noopener noreferrer">this resource</a> for more ideas.</p>
  44. `,
  45. publicationDate: subDays(new Date(), 12).toISOString(),
  46. sourceType: 'generated',
  47. },
  48. ];
  49. const createInitialVideos = () => {
  50. return [
  51. { id: 'vid1', title: 'Product Demo', thumbnailUrl: "https://picsum.photos/seed/vid1/200/120", videoUrl: 'https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4' },
  52. { id: 'vid2', title: 'Weekly Update', thumbnailUrl: "https://picsum.photos/seed/vid2/200/120", videoUrl: 'https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4' },
  53. ];
  54. };
  55. const merge = <T extends object>(base: T, updates: Partial<T>): T => {
  56. const result = { ...base };
  57. for (const key in updates) {
  58. if (Object.prototype.hasOwnProperty.call(updates, key)) {
  59. const value = updates[key as keyof T];
  60. if (typeof value === 'object' && value !== null && !Array.isArray(value) && base[key as keyof T] && typeof base[key as keyof T] === 'object') {
  61. result[key as keyof T] = merge(base[key as keyof T] as any, value as any);
  62. } else {
  63. result[key as keyof T] = value;
  64. }
  65. }
  66. }
  67. return result;
  68. };
  69. const customizePage = (
  70. basePage: GreenPage,
  71. customizations: {
  72. name: string;
  73. slug: string;
  74. design?: Partial<DesignSettings>;
  75. blocks?: Block[];
  76. }
  77. ): GreenPage => {
  78. const newPage = JSON.parse(JSON.stringify(basePage));
  79. newPage.name = customizations.name;
  80. newPage.slug = customizations.slug;
  81. if (customizations.design) {
  82. // Deep merge design settings
  83. newPage.pageSettings.design = merge(newPage.pageSettings.design, customizations.design);
  84. }
  85. if (customizations.blocks) {
  86. newPage.pageSettings.blocks = customizations.blocks;
  87. }
  88. return newPage;
  89. };
  90. const personalArchetypes = [
  91. {
  92. name: "Alex Doe - Software Developer",
  93. slug: "alex-doe-dev",
  94. design: {
  95. theme: 'dark' as ThemeName,
  96. backgroundType: 'gradient' as BackgroundType,
  97. backgroundValue: 'bg-gradient-to-br from-gray-900 via-blue-900/50 to-gray-900',
  98. fontFamily: 'mono' as FontFamily,
  99. buttonShape: 'square' as ButtonShape,
  100. buttonStyle: 'outline' as ButtonStyle,
  101. avatarSource: { type: 'url', value: 'https://api.dicebear.com/8.x/adventurer-neutral/svg?seed=Alex' } as MediaSource
  102. },
  103. blocks: [
  104. { type: 'chat', layout: 'under_avatar', visible: true, id: 'c1' } as ChatBlock,
  105. { type: 'header', text: 'Alex Doe', visible: true, id: 'h1', titleAlignment: 'center' } as HeaderBlock,
  106. { type: 'text', content: 'Full-Stack Developer | Open-Source Contributor | Tech Enthusiast', visible: true, id: 't1', textAlign: 'center', fontSize: '16px', fontColor: '#d1d5db', isBold: false, isItalic: false } as TextBlock,
  107. { type: 'social', links: [
  108. { id: 's1', platform: 'github', url: 'https://github.com' },
  109. { id: 's2', platform: 'linkedin', url: 'https://linkedin.com' },
  110. { id: 's3', platform: 'twitter', url: 'https://twitter.com' },
  111. ], visible: true, id: 'so1' } as SocialBlock,
  112. { type: 'header', text: 'Projects', visible: true, id: 'h2', titleAlignment: 'left' } as HeaderBlock,
  113. { type: 'link', title: 'Project Titan - AI-Powered Analytics', url: '#', visible: true, id: 'l1' } as LinkBlock,
  114. { type: 'link', title: 'QuantumLeap - A new JS Framework', url: '#', visible: true, id: 'l2' } as LinkBlock,
  115. ]
  116. },
  117. {
  118. name: "Jamie Lee - Photographer",
  119. slug: "jamie-lee-photo",
  120. design: {
  121. theme: 'light' as ThemeName,
  122. backgroundType: 'color' as BackgroundType,
  123. backgroundValue: '#ffffff',
  124. fontFamily: 'serif' as FontFamily,
  125. fontColor: '#111827',
  126. buttonShape: 'pill' as ButtonShape,
  127. buttonStyle: 'filled' as ButtonStyle,
  128. avatarSource: { type: 'url', value: 'https://api.dicebear.com/8.x/adventurer/svg?seed=Jamie' } as MediaSource,
  129. customThemeColors: { background: '#ffffff', text: '#111827', button: '#f3f4f6', buttonText: '#111827' }
  130. },
  131. blocks: [
  132. { type: 'chat', layout: 'under_avatar', visible: true, id: 'c1' } as ChatBlock,
  133. { type: 'header', text: 'Jamie Lee', visible: true, id: 'h1', titleAlignment: 'center' } as HeaderBlock,
  134. { type: 'text', content: 'Capturing moments, telling stories.', visible: true, id: 't1', textAlign: 'center', fontSize: '16px', fontColor: '#4b5563', isBold: false, isItalic: true } as TextBlock,
  135. { type: 'image', layout: 'grid', sources: [
  136. { type: 'url', value: 'https://picsum.photos/seed/jamie1/400/300' },
  137. { type: 'url', value: 'https://picsum.photos/seed/jamie2/400/300' },
  138. { type: 'url', value: 'https://picsum.photos/seed/jamie3/400/300' },
  139. { type: 'url', value: 'https://picsum.photos/seed/jamie4/400/300' },
  140. ], visible: true, id: 'i1' } as ImageBlock,
  141. { type: 'header', text: 'Contact & Bookings', visible: true, id: 'h2', titleAlignment: 'left' } as HeaderBlock,
  142. { type: 'email', label: 'Email for Inquiries', email: '#', visible: true, id: 'e1', displayMode: 'labelOnly' } as EmailBlock,
  143. { type: 'social', links: [{ id: 's1', platform: 'instagram', url: 'https://instagram.com' }], visible: true, id: 'so1' } as SocialBlock,
  144. ]
  145. },
  146. {
  147. name: "Casey Solaris - Musician",
  148. slug: "casey-solaris-music",
  149. design: {
  150. theme: 'synthwave' as ThemeName,
  151. backgroundType: 'image' as BackgroundType,
  152. backgroundValue: 'https://picsum.photos/seed/synth-bg/1200/800',
  153. fontFamily: 'sans' as FontFamily,
  154. buttonShape: 'rounded' as ButtonShape,
  155. buttonStyle: 'outline' as ButtonStyle,
  156. avatarSource: { type: 'url', value: 'https://api.dicebear.com/8.x/lorelei/svg?seed=Casey' } as MediaSource,
  157. },
  158. blocks: [
  159. { type: 'chat', layout: 'under_avatar', visible: true, id: 'c1' } as ChatBlock,
  160. { type: 'header', text: 'CASEY SOLARIS', visible: true, id: 'h1', titleAlignment: 'center' } as HeaderBlock,
  161. { type: 'video', layout: 'single', sources: [{type: 'url', value: 'https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4'}], visible: true, id: 'v1' } as VideoBlock,
  162. { type: 'header', text: 'Stream My Music', visible: true, id: 'h2', titleAlignment: 'left' } as HeaderBlock,
  163. { type: 'link', title: 'Spotify', url: '#', visible: true, id: 'l1' } as LinkBlock,
  164. { type: 'link', title: 'Apple Music', url: '#', visible: true, id: 'l2' } as LinkBlock,
  165. { type: 'link', title: 'Bandcamp', url: '#', visible: true, id: 'l3' } as LinkBlock,
  166. ]
  167. },
  168. ];
  169. const enterpriseArchetypes = [
  170. {
  171. name: "Innovatech AI",
  172. slug: "innovatech-ai",
  173. design: {
  174. theme: 'dark' as ThemeName,
  175. fontFamily: 'sans' as FontFamily,
  176. fontColor: '#e5e7eb',
  177. backgroundType: 'gradient' as BackgroundType,
  178. backgroundValue: 'bg-gradient-to-br from-gray-900 to-slate-800',
  179. bannerSettings: {
  180. type: 'image' as BannerType,
  181. // FIX: Added missing 'value' property to conform to the BannerSettings type.
  182. value: '',
  183. imageSource: { type: 'url', value: 'https://picsum.photos/seed/innovatech-banner/1200/400' } as MediaSource,
  184. height: 400,
  185. width: 'full'
  186. },
  187. sideNavSettings: {
  188. backgroundColor: 'transparent',
  189. textColor: '#9ca3af',
  190. activeLinkColor: '#10b981',
  191. hoverBackgroundColor: '#374151',
  192. hoverTextColor: '#ffffff',
  193. // FIX: Added missing 'fontFamily' and 'fontSize' properties to conform to the SideNavSettings type.
  194. fontFamily: 'sans',
  195. fontSize: '14px',
  196. }
  197. },
  198. blocks: [
  199. { id: 'chat-enterprise-1', type: 'chat', layout: 'widget', visible: true } as ChatBlock,
  200. { id: 'ent-h1', type: 'header', text: 'About Innovatech', visible: true, titleAlignment: 'left' } as HeaderBlock,
  201. { id: 'ent-t1', type: 'text', content: "Innovatech AI is a leading provider of cutting-edge artificial intelligence solutions. Our mission is to empower businesses with transformative technologies that drive growth, efficiency, and innovation. We specialize in machine learning, natural language processing, and computer vision to solve complex challenges across various industries.", visible: true, textAlign: 'left', fontSize: '16px', fontColor: '#d1d5db', isBold: false, isItalic: false } as TextBlock,
  202. { id: 'ent-h2', type: 'header', text: 'Our Solutions', visible: true, titleAlignment: 'left' } as HeaderBlock,
  203. { id: 'ent-i1', type: 'image', layout: 'grid', sources: [{ type: 'url', value: 'https://picsum.photos/seed/solution1/400/300' }, { type: 'url', value: 'https://picsum.photos/seed/solution2/400/300' }], visible: true } as ImageBlock,
  204. { id: 'ent-h3', type: 'header', text: 'Company Information', visible: true, titleAlignment: 'left' } as HeaderBlock,
  205. { id: 'ent-info1', type: 'enterprise_info', alignment: 'left', items: [
  206. { id: 'ei-1', icon: 'building', label: 'Legal Name', value: 'Innovatech AI Solutions, Inc.' },
  207. { id: 'ei-2', icon: 'calendar', label: 'Founded', value: '2021' },
  208. { id: 'ei-3', icon: 'location', label: 'Headquarters', value: 'San Francisco, CA' },
  209. ], visible: true } as EnterpriseInfoBlock,
  210. { id: 'ent-h4', type: 'header', text: 'Contact Us', visible: true, titleAlignment: 'left' } as HeaderBlock,
  211. { id: 'ent-form1', type: 'form', title: 'Get in Touch', description: 'Fill out the form below and our team will get back to you shortly.', submitButtonText: 'Submit Request', fields: [
  212. { id: 'name', label: 'Full Name', enabled: true, required: true },
  213. { id: 'email', label: 'Work Email', enabled: true, required: true },
  214. { id: 'company', label: 'Company', enabled: true, required: true },
  215. { id: 'phone', label: 'Phone', enabled: true, required: false },
  216. ], purposeOptions: [{id: 'po1', label: 'Sales Inquiry'}, {id: 'po2', label: 'Partnership'}], visible: true } as FormBlock,
  217. { id: 'footer-ent-1', type: 'footer', layout: 'standard', copyrightText: '© 2024 Innovatech AI Solutions, Inc. All Rights Reserved.', legalText: 'Filing No. 123-456-789', navLinks: [{id:'fn1', title: 'Home', url:'#'}, {id:'fn2', title:'Solutions', url:'#'}], otherLinks: [{id:'fo1', title:'Privacy Policy', url:'#'}], statement: '', visible: true } as FooterBlock,
  218. ]
  219. },
  220. {
  221. name: "Sterling & Partners Law",
  222. slug: "sterling-partners-law",
  223. design: {
  224. theme: 'light' as ThemeName,
  225. fontFamily: 'serif' as FontFamily,
  226. fontColor: '#1f2937',
  227. backgroundType: 'color' as BackgroundType,
  228. backgroundValue: '#f9fafb',
  229. bannerSettings: {
  230. type: 'gradient' as BannerType,
  231. value: 'bg-gradient-to-r from-gray-700 via-gray-900 to-black',
  232. // FIX: Added missing 'imageSource' property to conform to the BannerSettings type.
  233. imageSource: { type: 'url', value: 'https://picsum.photos/seed/law-firm-banner/1200/250' } as MediaSource,
  234. height: 250,
  235. width: 'full'
  236. },
  237. sideNavSettings: {
  238. backgroundColor: 'transparent',
  239. textColor: '#4b5563',
  240. activeLinkColor: '#ca8a04', // a gold color
  241. hoverBackgroundColor: '#f3f4f6',
  242. hoverTextColor: '#111827',
  243. navFloatStyle: 'top',
  244. // FIX: Added missing 'fontFamily' and 'fontSize' properties to conform to the SideNavSettings type.
  245. fontFamily: 'serif',
  246. fontSize: '14px',
  247. }
  248. },
  249. blocks: [
  250. { id: 'chat-law-1', type: 'chat', layout: 'widget', visible: true } as ChatBlock,
  251. { id: 'law-h1', type: 'header', text: 'About Our Firm', visible: true, titleAlignment: 'left' } as HeaderBlock,
  252. { id: 'law-t1', type: 'text', content: "Sterling & Partners is a premier law firm dedicated to providing exceptional legal services. With decades of combined experience, our attorneys are committed to achieving the best possible outcomes for our clients through rigorous advocacy and strategic counsel.", visible: true, textAlign: 'left', fontSize: '16px', fontColor: '#374151', isBold: false, isItalic: false } as TextBlock,
  253. { id: 'law-h2', type: 'header', text: 'Practice Areas', visible: true, titleAlignment: 'left' } as HeaderBlock,
  254. { id: 'law-l1', type: 'link', title: 'Corporate Law', url: '#', visible: true } as LinkBlock,
  255. { id: 'law-l2', type: 'link', title: 'Intellectual Property', url: '#', visible: true } as LinkBlock,
  256. { id: 'law-l3', type: 'link', title: 'Litigation & Arbitration', url: '#', visible: true } as LinkBlock,
  257. { id: 'law-h3', type: 'header', text: 'Accolades', visible: true, titleAlignment: 'left' } as HeaderBlock,
  258. { id: 'law-award1', type: 'award', layout: 'single', items: [
  259. {id: 'aw1', title: 'Law Firm of the Year', subtitle: 'National Law Review', year: '2023', imageSource: {type: 'url', value: 'https://picsum.photos/seed/law-award1/100'}},
  260. {id: 'aw2', title: 'Top Corporate Counsel', subtitle: 'Attorneys Weekly', year: '2022', imageSource: {type: 'url', value: 'https://picsum.photos/seed/law-award2/100'}}
  261. ], visible: true} as AwardBlock,
  262. { id: 'law-h4', type: 'header', text: 'Our Location', visible: true, titleAlignment: 'left' } as HeaderBlock,
  263. { id: 'law-map1', type: 'map', address: '1 Wall Street, New York, NY', visible: true, displayStyle: 'interactiveMap' } as MapBlock,
  264. { id: 'footer-law-1', type: 'footer', layout: 'centered', copyrightText: '© 2024 Sterling & Partners LLP. Attorney Advertising.', navLinks: [{id:'fn1', title: 'Home', url:'#'}, {id:'fn2', title:'Contact', url:'#'}], otherLinks: [{id:'fo1', title:'Disclaimer', url:'#'}], statement: 'Prior results do not guarantee a similar outcome.', visible: true } as FooterBlock,
  265. ]
  266. }
  267. ];
  268. const basePage: GreenPage = {
  269. id: 'base_page',
  270. name: 'Base Page',
  271. slug: 'base-page',
  272. themeColor: 'from-gray-500 to-gray-700',
  273. pageSettings: {
  274. blocks: [],
  275. design: {
  276. theme: 'dark' as ThemeName,
  277. customThemeColors: { background: '#111827', text: '#FFFFFF', button: '#374151', buttonText: '#FFFFFF' },
  278. buttonStyle: 'filled' as ButtonStyle,
  279. buttonShape: 'rounded' as ButtonShape,
  280. fontFamily: 'sans' as FontFamily,
  281. fontColor: '#FFFFFF',
  282. fontSize: 'text-base',
  283. backgroundType: 'gradient' as BackgroundType,
  284. backgroundValue: 'bg-gradient-to-br from-gray-800 to-gray-900',
  285. avatarSource: { type: 'url', value: 'https://api.dicebear.com/8.x/adventurer/svg?seed=Base' },
  286. bannerSettings: {
  287. type: 'image' as BannerType,
  288. value: '',
  289. imageSource: { type: 'url', value: "https://picsum.photos/seed/default-banner/1200/300" } as MediaSource,
  290. height: 300,
  291. width: 'contained' as 'contained',
  292. },
  293. sideNavSettings: {
  294. backgroundColor: 'transparent',
  295. textColor: '#d1d5db',
  296. activeLinkColor: '#10b981',
  297. hoverBackgroundColor: '#374151',
  298. hoverTextColor: '#ffffff',
  299. fontFamily: 'sans' as FontFamily,
  300. fontSize: '14px',
  301. navFloatStyle: 'normal' as 'normal',
  302. navBackgroundStyle: 'compact' as 'compact',
  303. },
  304. chatWidgetSettings: {
  305. iconColor: '#10b981', headerBackgroundColor: '#10b981', headerTextColor: '#FFFFFF',
  306. panelBackgroundColor: '#1f2937', userMessageBackgroundColor: '#3b82f6',
  307. userMessageTextColor: '#FFFFFF', aiMessageBackgroundColor: '#374151', aiMessageTextColor: '#FFFFFF',
  308. },
  309. },
  310. },
  311. aiAssistantSettings: {
  312. persona: 'You are a helpful assistant.',
  313. voiceId: 'vo1',
  314. language: 'English',
  315. conversationStyle: 'professional',
  316. knowledgeBaseFiles: [],
  317. knowledgeBaseUrls: [],
  318. forbiddenUserKeywords: [],
  319. forbiddenAIKeywords: [],
  320. },
  321. analyticsData: {
  322. conversations: [],
  323. formSubmissions: [],
  324. },
  325. aigcSettings: {
  326. videos: createInitialVideos(),
  327. articles: createInitialAIGCArticles(),
  328. schedule: [],
  329. }
  330. };
  331. export const generatePersonalShowcases = (): GreenPage[] => {
  332. // FIX: Completed the .map() function by returning the result of customizePage.
  333. return personalArchetypes.map((archetype, index) => {
  334. const page = customizePage(basePage, {
  335. name: archetype.name,
  336. slug: archetype.slug,
  337. design: archetype.design,
  338. blocks: archetype.blocks,
  339. });
  340. page.id = `showcase-personal-${index}`;
  341. // FIX: Simplified theme color selection to prevent type errors.
  342. page.themeColor = themeColors[index % themeColors.length];
  343. return page;
  344. });
  345. };
  346. // FIX: Added the missing generateEnterpriseShowcases function to create and export enterprise-themed showcase pages.
  347. export const generateEnterpriseShowcases = (): GreenPage[] => {
  348. return enterpriseArchetypes.map((archetype, index) => {
  349. const page = customizePage(basePage, {
  350. name: archetype.name,
  351. slug: archetype.slug,
  352. design: archetype.design,
  353. blocks: archetype.blocks,
  354. });
  355. page.id = `showcase-enterprise-${index}`;
  356. page.themeColor = themeColors[index % themeColors.length];
  357. return page;
  358. });
  359. };