import fs from 'node:fs/promises'; import path from 'node:path'; import { blogPostData, locationData, serviceData } from '../src/data/seoData'; type RouteMeta = { route: string; title: string; description: string; canonicalUrl: string; keywords?: string[]; schema?: Record; }; const DIST_DIR = path.resolve(process.cwd(), 'dist'); const BASE_URL = 'https://bayareait.services'; const DEFAULT_OG_IMAGE = `${BASE_URL}/logo.svg`; const staticRoutes: RouteMeta[] = [ { route: '/', title: 'IT Service & IT Support for Businesses in Corpus Christi, TX', description: 'Reliable IT support and IT services for businesses in Corpus Christi, TX. Fast response, outsourced IT support and help desk solutions.', canonicalUrl: `${BASE_URL}/`, keywords: ['IT Service', 'IT Support', 'Corpus Christi', 'IT Help Desk'], schema: { '@context': 'https://schema.org', '@type': 'ITService', name: 'Bay Area IT', url: BASE_URL, telephone: '+1-361-765-8400', areaServed: ['Corpus Christi', 'Portland', 'Rockport', 'Aransas Pass', 'Kingsville'], }, }, { route: '/about', title: 'About Bay Area IT | Local IT Support in Corpus Christi', description: 'Learn about Bay Area IT, a local IT partner serving Corpus Christi and the Coastal Bend with practical support, reliable service, and over 25 years of experience.', canonicalUrl: `${BASE_URL}/about`, schema: { '@context': 'https://schema.org', '@type': 'Organization', name: 'Bay Area IT', url: BASE_URL, }, }, { route: '/services', title: 'IT Services | Bay Area IT Support, Email, Networking and Web', description: 'Explore Bay Area IT services for Corpus Christi businesses, including help desk support, business email, networking, hardware, web design, and day-to-day IT support.', canonicalUrl: `${BASE_URL}/services`, }, { route: '/blog', title: 'Blog | Bay Area IT Insights for Corpus Christi Businesses', description: 'Read practical IT guidance for Corpus Christi and Coastal Bend businesses, from managed IT support and costs to business email and local service coverage.', canonicalUrl: `${BASE_URL}/blog`, }, { route: '/contact', title: 'Contact Bay Area IT | Free IT Assessment in Corpus Christi', description: 'Talk to Bay Area IT about managed IT support, help desk coverage, business email, networking, and technology support across Corpus Christi and the Coastal Bend.', canonicalUrl: `${BASE_URL}/contact`, }, { route: '/locations', title: 'IT Support Service Areas - Corpus Christi & Coastal Bend, TX', description: 'Bay Area IT provides IT support and IT services throughout the Coastal Bend. View all cities we serve in the Corpus Christi area.', canonicalUrl: `${BASE_URL}/locations`, }, { route: '/privacy-policy', title: 'Privacy Policy | Bay Area IT', description: 'Read how Bay Area IT collects, uses, and protects information submitted through this website.', canonicalUrl: `${BASE_URL}/privacy-policy`, }, { route: '/terms-of-service', title: 'Terms of Service | Bay Area IT', description: 'Review the Bay Area IT terms covering use of this website and our IT support services.', canonicalUrl: `${BASE_URL}/terms-of-service`, }, ]; const dynamicRoutes: RouteMeta[] = [ ...locationData.map((item) => ({ route: `/${item.slug}`, title: item.title, description: item.description, canonicalUrl: `${BASE_URL}/${item.slug}`, keywords: item.keywords, schema: { '@context': 'https://schema.org', '@type': 'LocalBusiness', name: 'Bay Area IT', url: `${BASE_URL}/${item.slug}`, areaServed: item.city, }, })), ...serviceData.map((item) => ({ route: `/${item.slug}`, title: item.title, description: item.description, canonicalUrl: `${BASE_URL}/${item.slug}`, keywords: item.keywords, schema: { '@context': 'https://schema.org', '@type': 'Service', name: item.h1, provider: { '@type': 'Organization', name: 'Bay Area IT', }, url: `${BASE_URL}/${item.slug}`, }, })), ...blogPostData .filter((item) => !item.redirect) .map((item) => ({ route: `/${item.slug}`, title: item.title, description: item.description, canonicalUrl: `${BASE_URL}/${item.slug}`, keywords: item.keywords, schema: { '@context': 'https://schema.org', '@type': 'BlogPosting', headline: item.h1, description: item.description, url: `${BASE_URL}/${item.slug}`, publisher: { '@type': 'Organization', name: 'Bay Area IT', }, }, })), ]; function escapeHtml(value: string) { return value .replace(/&/g, '&') .replace(/"/g, '"') .replace(//g, '>'); } function buildHead(meta: RouteMeta) { const keywords = meta.keywords?.length ? `\n ` : ''; const schema = meta.schema ? `\n ` : ''; return ` ${escapeHtml(meta.title)} ${keywords} ${schema}`; } function injectHead(template: string, meta: RouteMeta) { const withoutTitle = template.replace(/[\s\S]*?<\/title>/i, ''); return withoutTitle.replace('</head>', `${buildHead(meta)}\n </head>`); } async function writeRouteHtml(template: string, meta: RouteMeta) { const html = injectHead(template, meta); const cleanRoute = meta.route === '/' ? '' : meta.route.replace(/^\/+/, ''); const filePath = meta.route === '/' ? path.join(DIST_DIR, 'index.html') : path.join(DIST_DIR, cleanRoute, 'index.html'); await fs.mkdir(path.dirname(filePath), { recursive: true }); await fs.writeFile(filePath, html, 'utf8'); } async function main() { const templatePath = path.join(DIST_DIR, 'index.html'); const template = await fs.readFile(templatePath, 'utf8'); const allRoutes = [...staticRoutes, ...dynamicRoutes]; await Promise.all(allRoutes.map((meta) => writeRouteHtml(template, meta))); console.log(`Prerendered ${allRoutes.length} route HTML files.`); } main().catch((error) => { console.error('Failed to prerender route HTML files.'); console.error(error); process.exit(1); });