diff --git a/data/bots.ts b/data/bots.ts index f21179d3..54ad42ae 100644 --- a/data/bots.ts +++ b/data/bots.ts @@ -52,9 +52,6 @@ const bots: Bot[] = [ menuItems: [ { id: 'demo', label: 'Demo', icon: 'πŸ’¬', section: 'demo' }, { id: 'features', label: 'Features', icon: '✨', section: 'features' }, - { id: 'communication', label: 'Communication', icon: 'βœ‰οΈ', section: 'communication' }, - { id: 'culture', label: 'Culture', icon: 'πŸ”οΈ', section: 'culture' }, - { id: 'waitlist', label: 'Join Waitlist', icon: 'πŸ“', section: 'waitlist' }, ], }, display: { @@ -97,12 +94,6 @@ const bots: Bot[] = [ menuItems: [ { id: 'demo', label: 'Demo', icon: 'πŸ’»', section: 'demo' }, { id: 'features', label: 'Features', icon: '✨', section: 'features' }, - { id: 'scraping', label: 'Web Scraping', icon: '🌐', section: 'scraping' }, - { id: 'drafts', label: 'Drafts', icon: 'πŸ“', section: 'drafts' }, - { id: 'questions', label: 'Daily Questions', icon: '❓', section: 'questions' }, - { id: 'discovery', label: 'Discovery', icon: 'πŸ’‘', section: 'discovery' }, - { id: 'integration', label: 'Integration', icon: 'πŸ”—', section: 'integration' }, - { id: 'roadmap', label: 'Roadmap', icon: 'πŸ—ΊοΈ', section: 'roadmap' }, ], }, display: { @@ -143,7 +134,8 @@ const bots: Bot[] = [ { id: 'demo', label: 'Demo', icon: 'πŸ’»', section: 'demo' }, { id: 'features', label: 'Features', icon: '✨', section: 'features' }, { id: 'professionals', label: 'For Professionals', icon: 'πŸ‘¨β€βš•οΈ', section: 'professionals' }, - { id: 'harm-reduction', label: 'Harm Reduction', icon: 'πŸ›‘οΈ', section: 'harm-reduction' }, + { id: 'medbox', label: 'MedBox', icon: 'πŸ”¬', section: 'medbox' }, + { id: 'health-topics', label: 'Topics', icon: '🩺', section: 'health-topics' }, { id: 'vision', label: 'Vision', icon: 'πŸš€', section: 'vision' }, ], }, @@ -186,7 +178,7 @@ const bots: Bot[] = [ { id: 'testimonials', label: 'Testimonials', icon: 'πŸ’¬', section: 'testimonials' }, { id: 'vision', label: 'Vision', icon: 'πŸš€', section: 'vision' }, { id: 'technology', label: 'Technology', icon: 'βš™οΈ', section: 'technology' }, - { id: 'get-started', label: 'Join Waitlist', icon: '✨', section: 'get-started' }, + { id: 'get-started', label: 'Join Waitlist', icon: '✨', section: 'cta' }, ], }, display: { @@ -226,9 +218,6 @@ const bots: Bot[] = [ menuItems: [ { id: 'demo', label: 'Demo', icon: 'πŸ–ΌοΈ', section: 'demo' }, { id: 'features', label: 'Features', icon: '✨', section: 'features' }, - { id: 'styles', label: 'Styles', icon: '🎭', section: 'styles' }, - { id: 'techniques', label: 'Techniques', icon: 'πŸ–ŒοΈ', section: 'techniques' }, - { id: 'get-started', label: 'Get Started', icon: 'πŸš€', section: 'get-started' }, ], }, display: { @@ -269,13 +258,6 @@ const bots: Bot[] = [ menuItems: [ { id: 'demo', label: 'Demo', icon: 'πŸ’»', section: 'demo' }, { id: 'features', label: 'Features', icon: '✨', section: 'features' }, - { id: 'workflow', label: 'Workflow', icon: 'πŸ”„', section: 'workflow' }, - { id: 'showcase', label: 'Showcase', icon: '🎯', section: 'showcase' }, - { id: 'examples', label: 'Examples', icon: 'πŸ“‹', section: 'examples' }, - { id: 'integration', label: 'Integration', icon: 'πŸ”—', section: 'integration' }, - { id: 'testimonials', label: 'Testimonials', icon: 'πŸ’¬', section: 'testimonials' }, - { id: 'pricing', label: 'Pricing', icon: 'πŸ’°', section: 'pricing' }, - { id: 'get-started', label: 'Get Started', icon: 'πŸš€', section: 'get-started' }, ], }, display: { diff --git a/lib/config/bot-pages.ts b/lib/config/bot-pages.ts index 0d777c3f..a09d1615 100644 --- a/lib/config/bot-pages.ts +++ b/lib/config/bot-pages.ts @@ -699,6 +699,119 @@ export const botPageConfigs: Record = { ], } as BenefitsContent, }, + { + id: 'medbox', + type: 'features', + content: { + badge: 'Home Health Lab', + title: 'MedBox: Your Home Health Laboratory', + subtitle: + 'Clinical-grade diagnostics at home. MedBox automates health monitoring and puts the power of a medical lab at your fingertips.', + columns: 3, + features: [ + { + icon: '\u{1F4C8}', + title: 'Continuous Glucose Monitor', + description: 'Real-time blood glucose tracking without finger pricks.', + }, + { + icon: '\u2764\uFE0F', + title: '12-Lead ECG Monitor', + description: 'Clinical-grade heart monitoring and arrhythmia detection.', + }, + { + icon: '\u{1F9EA}', + title: 'Blood Chemistry Analyzer', + description: 'Complete blood count, lipid panels, and metabolic testing.', + }, + { + icon: '\u{1FA78}', + title: 'Blood Pressure System', + description: 'Continuous monitoring with physician-grade accuracy.', + }, + { + icon: '\u{1F634}', + title: 'Sleep & Recovery Monitor', + description: 'Tracks deep sleep, REM, HRV, and respiratory patterns.', + }, + { + icon: '\u2696\uFE0F', + title: 'Body Composition Scanner', + description: 'Measures muscle mass, visceral fat, and bone density.', + }, + ], + } as FeaturesContent, + }, + { + id: 'health-topics', + type: 'features', + content: { + badge: 'What You Can Ask', + title: 'Health Topics Imhotep Covers', + subtitle: + 'Common areas people bring to Imhotep, from daily habits to chronic conditions.', + columns: 3, + features: [ + { + icon: '\u2764\uFE0F', + title: 'Heart Health', + description: 'Blood pressure, cholesterol, and cardiovascular risk.', + }, + { + icon: '\u{1F9E0}', + title: 'Mental Wellness', + description: 'Stress, mood, and evidence-based coping strategies.', + }, + { + icon: '\u{1F957}', + title: 'Nutrition', + description: 'Diet patterns, macronutrients, and supplementation.', + }, + { + icon: '\u{1F3C3}', + title: 'Exercise', + description: 'Training load, recovery, and building a sustainable routine.', + }, + { + icon: '\u{1F634}', + title: 'Sleep', + description: 'Sleep quality, circadian rhythm, and insomnia.', + }, + { + icon: '\u{1F4CA}', + title: 'Diabetes', + description: 'Glucose management, monitoring, and long-term risk.', + }, + ], + } as FeaturesContent, + }, + { + id: 'regimens', + type: 'how-it-works', + content: { + title: 'Personalized Health Regimens', + steps: [ + { + icon: '\u{1F4CB}', + title: 'Imhotep Basic', + description: + 'Low cost, about 30 minutes a day, low complexity β€” and still fully customised to you.', + }, + { + icon: '\u{1F4C8}', + title: 'Imhotep Advanced', + description: + 'Medium cost, one to two hours a day, for people who want to go deeper without a full protocol.', + }, + { + icon: '\u2696\uFE0F', + title: 'Compared to Blueprint', + description: + 'High cost, three or more hours a day, high complexity, and limited customisation.', + }, + ], + } as HowItWorksContent, + }, { id: 'vision', type: 'vision', diff --git a/tests/__tests__/lib/bot-nav-integrity.test.ts b/tests/__tests__/lib/bot-nav-integrity.test.ts new file mode 100644 index 00000000..136463a1 --- /dev/null +++ b/tests/__tests__/lib/bot-nav-integrity.test.ts @@ -0,0 +1,43 @@ +/** + * Guard: a bot's nav may only link to sections that exist on its page. + * + * The config-driven refactor (4600019e) deleted ~16,000 lines of bot page + * content but left data/bots.ts still advertising it. The result was 19 menu + * items across five bots that scrolled nowhere -- "Web Scraping", "Daily + * Questions", "Harm Reduction", "Pricing" -- each one a link to a section that + * had been removed. Nothing failed, because nothing compared the two files. + * + * This is that comparison. + */ +import bots, { type Bot } from '@/data/bots'; +import { getBotPageConfig } from '@/lib/config/bot-pages'; + +describe('bot nav integrity', () => { + const withPages: Bot[] = bots.filter((b) => getBotPageConfig(b.slug)); + + it('every bot with a page config is covered', () => { + expect(withPages.length).toBeGreaterThan(0); + }); + + it.each(withPages.map((b) => [b.slug, b] as const))( + '%s: every nav item targets a real section', + (slug, bot) => { + const config = getBotPageConfig(slug); + const sectionIds = new Set(config!.sections.map((s) => s.id)); + + const dangling = (bot.nav?.menuItems ?? []) + .filter((item) => item.section !== undefined && !sectionIds.has(item.section)) + .map((item) => `${item.label} -> #${item.section}`); + + expect(dangling).toEqual([]); + }, + ); + + it.each(withPages.map((b) => [b.slug, b] as const))( + '%s: nav item ids are unique', + (_slug, bot) => { + const ids = (bot.nav?.menuItems ?? []).map((i) => i.id); + expect(ids).toEqual([...new Set(ids)]); + }, + ); +});