UNPKG

vibe-seo

Version:

AI-friendly SEO generator for modern web frameworks

369 lines (311 loc) 11.2 kB
const fs = require('fs-extra'); const path = require('path'); const yaml = require('js-yaml'); /** * Load and parse YAML configuration file */ async function loadConfig(configPath) { try { const configContent = await fs.readFile(configPath, 'utf8'); const config = yaml.load(configContent); // Validate required fields validateConfig(config); // Set defaults config.framework = config.framework || 'static'; config.outputDir = config.outputDir || './seo/output'; config.publicDir = config.publicDir || './public'; return config; } catch (error) { throw new Error(`Failed to load config: ${error.message}`); } } /** * Load config and auto-detect framework if needed */ async function loadConfigWithFrameworkDetection(configPath, projectDir) { try { const config = await loadConfig(configPath); // If framework is static, try to auto-detect the actual framework if (config.framework === 'static') { const { detectFramework } = require('./utils'); const detectedFramework = await detectFramework(projectDir); if (detectedFramework !== 'static') { console.log(`🔄 Auto-detected framework: ${detectedFramework} (was set to 'static')`); config.framework = detectedFramework; // Update the config file with the correct framework const yaml = require('js-yaml'); const updatedConfig = yaml.dump(config, { indent: 2 }); await fs.writeFile(configPath, updatedConfig); console.log(`✅ Updated config file with correct framework: ${detectedFramework}`); } } return config; } catch (error) { throw new Error(`Failed to load config: ${error.message}`); } } /** * Create default configuration for a framework */ async function createConfig(framework, outputDir) { const configDir = path.join(outputDir, 'config'); await fs.ensureDir(configDir); const configPath = path.join(configDir, 'seo.config.yaml'); // Get the YAML string with comments directly const yamlContent = getDefaultConfig(framework); await fs.writeFile(configPath, yamlContent); return configPath; } /** * Validate configuration object */ function validateConfig(config) { const required = ['site', 'bots']; for (const field of required) { if (!config[field]) { throw new Error(`Missing required config field: ${field}`); } } if (!config.site.url) { throw new Error('Missing required field: site.url'); } if (!config.site.name) { throw new Error('Missing required field: site.name'); } } /** * Get default configuration for a framework */ function getDefaultConfig(framework) { // Create a comprehensive YAML configuration with detailed comments const yamlConfig = `# ============================================================================= # VIBE-SEO CONFIGURATION FILE # ============================================================================= # This file configures SEO settings for your website. # Edit the values below to match your site's information. # ============================================================================= # Framework Detection (auto-detected, but you can override) # Options: nextjs, nextjs-app, nextjs-pages, react, vue, angular, static framework: ${framework} # ============================================================================= # SITE INFORMATION # ============================================================================= # Basic information about your website site: # Your site's base URL (required) # This is used for generating absolute URLs in sitemaps and meta tags url: "https://yoursite.com" # Your site's name (required) # Used in page titles, meta tags, and robots.txt name: "Your Site Name" # Default meta description for your site # Used as fallback when page-specific descriptions aren't available description: "Your compelling site description that explains what your site is about" # Path to your site's logo # Used for Open Graph images and structured data logo: "/assets/logo.png" # Primary language code (ISO 639-1) # Used for hreflang tags and language detection language: "en" # Locale for Open Graph and social media # Format: language_COUNTRY (e.g., en_US, es_ES) locale: "en_US" # Default author name # Used in meta tags and structured data author: "Your Name" # Path to your favicon # Used in meta tags and browser tabs favicon: "/favicon.ico" # ============================================================================= # MULTILINGUAL CONFIGURATION # ============================================================================= # Configure multiple languages for international SEO languages: # Default language code default: "en" # Supported languages # Add more languages to enable hreflang tags supported: # English (default) - code: "en" locale: "en_US" name: "English" url: "https://yoursite.com" # Example: Add Spanish language # - code: "es" # locale: "es_ES" # name: "Español" # url: "https://yoursite.com/es" # Example: Add German language # - code: "de" # locale: "de_DE" # name: "Deutsch" # url: "https://yoursite.de" # ============================================================================= # BOT CONFIGURATION # ============================================================================= # Control which search engines and AI crawlers can access your site bots: # Allowed crawlers (search engines and AI bots) # These bots will be allowed to crawl your site allow: # Traditional search engines - "Googlebot" # Google Search - "Bingbot" # Microsoft Bing - "DuckDuckBot" # DuckDuckGo # AI-powered search and chat bots - "GPTBot" # OpenAI ChatGPT - "PerplexityBot" # Perplexity AI - "ClaudeBot" # Anthropic Claude - "Meta-ExternalAgent" # Meta AI - "Applebot" # Apple Intelligence - "YouBot" # You.com # Blocked crawlers (optional) # Add bots here to prevent them from crawling your site disallow: [] # Crawl delay in seconds # How long bots should wait between requests crawlDelay: 1 # ============================================================================= # SEO TEMPLATES # ============================================================================= # Templates for generating meta tags and titles seo: # Page title template # Variables: {title}, {siteName}, {pageName} titleTemplate: "{title} | {siteName}" # Meta description template # Variables: {description}, {siteDescription} descriptionTemplate: "{description}" # Open Graph image template # Variables: {siteUrl}, {slug}, {pageName} imageTemplate: "{siteUrl}/og-images/{slug}.png" # Twitter card type # Options: summary, summary_large_image, app, player twitterCard: "summary_large_image" # Default Open Graph type # Options: website, article, book, profile, etc. ogType: "website" # Default keywords for meta tags # Comma-separated list of relevant keywords defaultKeywords: "keyword1, keyword2, keyword3" # ============================================================================= # SITEMAP CONFIGURATION # ============================================================================= # Settings for XML sitemap generation sitemap: # Default change frequency for pages # Options: always, hourly, daily, weekly, monthly, yearly, never changefreq: "weekly" # Default priority for pages (0.0 to 1.0) # Higher values indicate more important pages priority: 0.8 # Paths to exclude from sitemap # Use wildcards (*) to exclude entire directories excludePaths: - "/admin/*" # Admin pages - "/api/*" # API endpoints - "/_next/*" # Next.js internal files - "/private/*" # Private pages - "/temp/*" # Temporary files - "/draft/*" # Draft content # ============================================================================= # SEARCH ENGINE VERIFICATION # ============================================================================= # Verification tokens for search engine webmaster tools # Get these from your search engine webmaster console verification: # Google Search Console verification token # Found in Google Search Console > Settings > Ownership google: "" # Bing Webmaster Tools verification token # Found in Bing Webmaster Tools > Settings bing: "" # Yandex Webmaster verification token # Found in Yandex Webmaster Tools yandex: "" # Pinterest verification token # Found in Pinterest Business > Settings pinterest: "" # ============================================================================= # FRAMEWORK-SPECIFIC PATHS # ============================================================================= # Directory paths for your specific framework # These are auto-detected but can be customized paths: # Source directory (where your components/pages are) srcDir: "./src" # Public directory (static assets) publicDir: "./public" # Build output directory buildDir: "./dist" # Where to output SEO files outputDir: "./public" # ============================================================================= # TROUBLESHOOTING # ============================================================================= # If you encounter Vite plugin errors like "Cannot find module '@vitejs/plugin-react-swc'": # # 1. The vibe-seo plugin is self-contained and doesn't require additional dependencies # 2. Make sure vite-seo-plugin.js exists in your project root # 3. Check that your Vite version is 4.0 or higher # 4. If issues persist, you can manually add the plugin to your vite.config.ts: # # import seoPlugin from './vite-seo-plugin.js'; # # export default defineConfig({ # plugins: [seoPlugin()] # }); # # For more help, visit: https://github.com/onecf/vibe-seo/issues `; return yamlConfig; } /** * Get framework-specific path configurations */ function getFrameworkPaths(framework) { const nextjsPaths = { pagesDir: './pages', appDir: './app', publicDir: './public', outputDir: './public' }; const frameworks = { nextjs: nextjsPaths, 'nextjs-pages': nextjsPaths, 'nextjs-app': nextjsPaths, react: { srcDir: './src', publicDir: './public', buildDir: './dist', // Vite uses 'dist' by default outputDir: './public' }, vue: { srcDir: './src', publicDir: './public', distDir: './dist', outputDir: './public' }, angular: { srcDir: './src', distDir: './dist', assetsDir: './src/assets', outputDir: './src' }, static: { srcDir: './src', publicDir: './public', outputDir: './public' } }; return frameworks[framework] || frameworks.static; } module.exports = { loadConfig, loadConfigWithFrameworkDetection, createConfig, validateConfig, getDefaultConfig, getFrameworkPaths };