// Stack Router - Handles company and technology specific stack pages class StackRouter { constructor() { this.routes = new Map(); this.currentRoute = null; this.init(); } init() { // Listen for hash changes and initial load window.addEventListener('hashchange', () => this.handleRouteChange()); window.addEventListener('load', () => this.handleRouteChange()); // Check for path-based routes on load this.handleRouteChange(); } // Get company info from data loader getCompanyInfo(slug) { return window.dataLoader.getCompanyInfo(slug); } // Get technology info from data loader getTechnologyInfo(slug) { return window.dataLoader.getTechnologyInfo(slug); } // Handle route changes handleRouteChange() { const path = window.location.pathname; const hash = window.location.hash; // Check for company routes (/company/epic-games) const companyMatch = path.match(/\/company\/([^\/]+)/); if (companyMatch) { this.loadCompanyStack(companyMatch[1]); return; } // Check for technology routes (/technology/unity) const technologyMatch = path.match(/\/technology\/([^\/]+)/); if (technologyMatch) { this.loadTechnologyStack(technologyMatch[1]); return; } // Check for hash-based routes for development if (hash.startsWith('#/company/')) { const company = hash.replace('#/company/', ''); this.loadCompanyStack(company); return; } if (hash.startsWith('#/technology/')) { const technology = hash.replace('#/technology/', ''); this.loadTechnologyStack(technology); return; } if (hash === '#/companies') { this.loadAllCompaniesPage(); return; } // Return to main page this.loadMainPage(); } // Load company-specific stack page async loadCompanyStack(companySlug) { const companyInfo = this.getCompanyInfo(companySlug); if (!companyInfo) { console.error('Company not found:', companySlug); return; } this.currentRoute = { type: 'company', slug: companySlug, info: companyInfo }; // Wait for data to be loaded if (!window.dataLoader.componentsData) { await window.dataLoader.loadAllComponents(); } // Get company stack components const stackComponents = window.dataLoader.getCompanyStack(companySlug); // Update page content this.renderStackPage(companyInfo, stackComponents, 'company'); // Update page title and meta document.title = `${companyInfo.name} Stack - Claude Code Templates`; this.updateMetaTags(companyInfo, 'company'); } // Load technology-specific stack page async loadTechnologyStack(techSlug) { const techInfo = this.getTechnologyInfo(techSlug); if (!techInfo) { console.error('Technology not found:', techSlug); return; } this.currentRoute = { type: 'technology', slug: techSlug, info: techInfo }; // Wait for data to be loaded if (!window.dataLoader.componentsData) { await window.dataLoader.loadAllComponents(); } // Get technology stack components const stackComponents = window.dataLoader.getTechnologyStack(techSlug); // Update page content this.renderStackPage(techInfo, stackComponents, 'technology'); // Update page title and meta document.title = `${techInfo.name} Stack - Claude Code Templates`; this.updateMetaTags(techInfo, 'technology'); } // Render stack page content renderStackPage(stackInfo, components, type) { const main = document.querySelector('main.terminal'); if (!main) return; // Hide original content const originalSections = main.querySelectorAll('section:not(.stack-page)'); originalSections.forEach(section => section.style.display = 'none'); // Remove existing stack page if any const existingStackPage = main.querySelector('.stack-page'); if (existingStackPage) { existingStackPage.remove(); } // Create stack page const stackPageHTML = this.generateStackPageHTML(stackInfo, components, type); main.insertAdjacentHTML('afterbegin', stackPageHTML); // Initialize cart functionality for the new page if (window.initializeCartForStackPage) { window.initializeCartForStackPage(); } // Update header to show back button this.updateHeaderForStack(stackInfo); } // Generate stack page HTML generateStackPageHTML(stackInfo, components, type) { const totalComponents = Object.values(components).reduce((sum, arr) => sum + arr.length, 0); return `

${stackInfo.name} Development Stack

${stackInfo.description}

${totalComponents} Components
${components.agents.length} Agents
${components.commands.length} Commands
${components.mcps.length} MCPs
${stackInfo.website ? `Visit ${stackInfo.name} →` : ''}
${this.generateStackComponentsHTML(components)}

🚀 Install Complete ${stackInfo.name} Stack

Get all ${totalComponents} components with a single command:

$ ${this.generateStackInstallCommand(components)}
`; } // Generate components sections HTML generateStackComponentsHTML(components) { let html = ''; const sections = [ { type: 'agents', title: 'AI Agents', icon: '🤖', description: 'Specialized AI assistants for your workflow' }, { type: 'commands', title: 'Commands', icon: '⚡', description: 'Ready-to-use automation commands' }, { type: 'mcps', title: 'MCPs', icon: '🔌', description: 'Model Context Protocol integrations' } ]; sections.forEach(section => { const items = components[section.type] || []; if (items.length > 0) { html += `

${section.icon} ${section.title}

${section.description}

${items.length} ${items.length === 1 ? section.type.slice(0, -1) : section.type}
${items.map(component => this.generateComponentCardHTML(component)).join('')}
`; } }); return html; } // Generate component card HTML generateComponentCardHTML(component) { const { tags, companies, technologies } = window.dataLoader.getComponentMetadata(component.name); return `

${component.name}

${this.extractDescription(component.content)}
${tags.length > 0 || technologies.length > 0 ? `
${[...tags.slice(0, 3), ...technologies.slice(0, 2)].map(tag => `${tag}` ).join('')}
` : ''}
`; } // Extract description from component content extractDescription(content) { const descMatch = content.match(/description:\s*(.+?)(?:\n|$)/); if (descMatch) { return descMatch[1].replace(/^['"]|['"]$/g, '').substring(0, 150) + '...'; } return 'No description available'; } // Generate install command for entire stack generateStackInstallCommand(components) { const allComponents = [...components.agents, ...components.commands, ...components.mcps]; const componentArgs = allComponents.map(c => `--${c.type} ${c.name}`).join(' '); return `npx claude-code-templates@latest ${componentArgs}`; } // Update header for stack page updateHeaderForStack(stackInfo) { const header = document.querySelector('.header'); if (!header) return; // Add back button let backButton = header.querySelector('.back-button'); if (!backButton) { backButton = document.createElement('button'); backButton.className = 'back-button'; backButton.innerHTML = ` Back to Main `; backButton.onclick = () => this.goBack(); const headerContent = header.querySelector('.header-content'); if (headerContent) { headerContent.insertBefore(backButton, headerContent.firstChild); } } } // Update meta tags for SEO updateMetaTags(stackInfo, type) { // Update Open Graph tags const ogTitle = document.querySelector('meta[property="og:title"]'); const ogDescription = document.querySelector('meta[property="og:description"]'); if (ogTitle) { ogTitle.content = `${stackInfo.name} Development Stack - Claude Code Templates`; } if (ogDescription) { ogDescription.content = stackInfo.description; } // Update Twitter tags const twitterTitle = document.querySelector('meta[name="twitter:title"]'); const twitterDescription = document.querySelector('meta[name="twitter:description"]'); if (twitterTitle) { twitterTitle.content = `${stackInfo.name} Development Stack - Claude Code Templates`; } if (twitterDescription) { twitterDescription.content = stackInfo.description; } } // Navigate back to main page goBack() { // Remove stack page const stackPage = document.querySelector('.stack-page'); if (stackPage) { stackPage.remove(); } // Show original content const main = document.querySelector('main.terminal'); if (main) { const originalSections = main.querySelectorAll('section:not(.stack-page)'); originalSections.forEach(section => section.style.display = ''); } // Remove back button const backButton = document.querySelector('.back-button'); if (backButton) { backButton.remove(); } // Reset route this.currentRoute = null; window.history.pushState({}, '', window.location.pathname); // Reset page title and meta document.title = 'Claude Code Templates'; this.resetMetaTags(); } // Load main page (reset everything) loadMainPage() { if (this.currentRoute) { this.goBack(); } } // Reset meta tags to original values resetMetaTags() { const ogTitle = document.querySelector('meta[property="og:title"]'); const ogDescription = document.querySelector('meta[property="og:description"]'); if (ogTitle) { ogTitle.content = 'Claude Code Templates - Ready-to-use configurations'; } if (ogDescription) { ogDescription.content = 'Browse and install Claude Code configuration templates for different languages and frameworks. Includes 100+ agents, 159+ commands, 23+ MCPs, and 14+ templates.'; } } // Load all companies page async loadAllCompaniesPage() { this.currentRoute = { type: 'companies', slug: 'all' }; // Wait for data to be loaded if (!window.dataLoader.componentsData) { await window.dataLoader.loadAllComponents(); } // Update page content this.renderAllCompaniesPage(); // Update page title and meta document.title = 'All Development Stacks - Claude Code Templates'; this.updateMetaTagsForAllCompanies(); } // Render all companies page renderAllCompaniesPage() { const main = document.querySelector('main.terminal'); if (!main) return; // Hide original content const originalSections = main.querySelectorAll('section:not(.stack-page)'); originalSections.forEach(section => section.style.display = 'none'); // Remove existing stack page if any const existingStackPage = main.querySelector('.stack-page'); if (existingStackPage) { existingStackPage.remove(); } // Get all companies from metadata const allCompanies = window.dataLoader.metadataData?.companies || {}; // Create all companies page const allCompaniesHTML = this.generateAllCompaniesPageHTML(allCompanies); main.insertAdjacentHTML('afterbegin', allCompaniesHTML); // Update header to show back button this.updateHeaderForStack({ name: 'All Development Stacks' }); } // Generate all companies page HTML generateAllCompaniesPageHTML(companies) { const companiesArray = Object.entries(companies); // Group companies by category const categories = { 'AI & Machine Learning': ['openai', 'anthropic'], 'Payments & E-commerce': ['stripe', 'shopify', 'shopify'], 'CRM & Business': ['salesforce', 'hubspot', 'airtable', 'linear'], 'Communication': ['twilio', 'slack', 'discord', 'sendgrid'], 'Cloud & Infrastructure': ['aws', 'vercel', 'netlify', 'cloudflare', 'firebase', 'supabase'], 'Databases': ['mongodb', 'planetscale'], 'Development Tools': ['github', 'figma', 'adobe', 'atlassian', 'notion'], 'Entertainment & Media': ['spotify', 'youtube', 'twitter'], 'Game Development': ['unity-technologies', 'epic-games'], 'Marketing': ['mailchimp', 'hubspot'] }; let categorizedHTML = ''; let uncategorizedCompanies = [...companiesArray]; // Generate categorized sections Object.entries(categories).forEach(([categoryName, companyIds]) => { const categoryCompanies = companyIds .map(id => companiesArray.find(([key]) => key === id)) .filter(Boolean); if (categoryCompanies.length > 0) { categorizedHTML += `

${categoryName}

${categoryCompanies.map(([key, company]) => { // Remove from uncategorized list uncategorizedCompanies = uncategorizedCompanies.filter(([k]) => k !== key); return this.generateCompanyCardHTML(key, company); }).join('')}
`; } }); // Add uncategorized companies if any if (uncategorizedCompanies.length > 0) { categorizedHTML += `

Other Platforms

${uncategorizedCompanies.map(([key, company]) => this.generateCompanyCardHTML(key, company) ).join('')}
`; } return `

All Development Stacks

Complete list of companies and platforms with development APIs, SDKs, and integration opportunities

${companiesArray.length} Companies
${Object.keys(categories).length} Categories
${categorizedHTML}
`; } // Generate individual company card for all companies page generateCompanyCardHTML(companyKey, company) { return `

${company.name}

${company.description}

`; } // Update meta tags for all companies page updateMetaTagsForAllCompanies() { const ogTitle = document.querySelector('meta[property="og:title"]'); const ogDescription = document.querySelector('meta[property="og:description"]'); if (ogTitle) { ogTitle.content = 'All Development Stacks - Claude Code Templates'; } if (ogDescription) { ogDescription.content = 'Browse all available development stacks for major companies and platforms. Find agents, commands, and MCPs for APIs like OpenAI, Stripe, Shopify, AWS, and more.'; } } // Navigate programmatically navigateTo(path) { window.history.pushState({}, '', path); this.handleRouteChange(); } } // Initialize router when DOM is loaded document.addEventListener('DOMContentLoaded', () => { window.stackRouter = new StackRouter(); }); // Make it available globally window.StackRouter = StackRouter;