From 5764e9f244ea952ea6b9642f3ef23148466bee72 Mon Sep 17 00:00:00 2001 From: Mao Nakamoto <41178744+maonakamoto@users.noreply.github.com> Date: Fri, 28 Aug 2026 10:38:09 +0200 Subject: [PATCH] fix(bots): repair 20 dead nav links, restore Imhotep's lost content The config-driven refactor (4600019e) deleted ~16,000 lines of bot page content but left data/bots.ts still advertising it. Every bot's nav kept linking to sections that no longer existed: swiss-german-teacher communication, culture, waitlist research-assistant scraping, drafts, questions, discovery, integration, roadmap medical-expert harm-reduction artistic-advisor styles, techniques, get-started product-manager workflow, showcase, examples, integration, testimonials, pricing, get-started legal-expert get-started Twenty menu items that scrolled nowhere, on the live site, for seven months. Nothing failed because nothing compared data/bots.ts to bot-pages.ts. Now they do: tests/__tests__/lib/bot-nav-integrity.test.ts asserts every nav item targets a section the page actually renders, and that ids are unique. Mutation-verified -- repoint one item at a missing section and it fails and names it. legal-expert's 'Get Started' was repointed to the cta section it clearly meant. The rest are removed, because the sections they named are gone. Content restored for medical-expert, recovered from the deleted components and ported as config (no new components needed): medbox MedBox home health lab -- the 6 sensors health-topics the 6 topics Imhotep covers regimens Basic / Advanced, and how they compare to Blueprint Its page goes from 7 sections to 10, and from 3,833 to 5,380 rendered characters. The nav gains MedBox and Topics in place of the dead link. NOT restored: the harm-reduction section, a substance comparison table covering heroin, methamphetamine, MDMA, LSD and psilocybin. On a site offering AI health guidance that is a product and possibly a regulatory decision, not a cleanup one. It stays in git at 4600019e^ pending a call: git show 4600019e^:app/bots/medical-expert/components/features/HarmReductionSection.tsx The other four bots still need their content ported; this is the pattern. verify: format, lint, typecheck, 253 tests, build -- all green. Verified visually against a local production build. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01HVwg8DKHQktxJuHeLM3xpG --- data/bots.ts | 24 +--- lib/config/bot-pages.ts | 113 ++++++++++++++++++ tests/__tests__/lib/bot-nav-integrity.test.ts | 43 +++++++ 3 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 tests/__tests__/lib/bot-nav-integrity.test.ts 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)]); + }, + ); +});