2025-11-13 09:53:08 +05:30
import fs from "fs" ;
import path from "path" ;
import axios from "axios" ;
import { fileURLToPath } from "url" ;
const _ _filename = fileURLToPath ( import . meta . url ) ;
const _ _dirname = path . dirname ( _ _filename ) ;
// For production deployment, always use the production URL
// When running convert-jsx-to-html, always use production URLs for SEO
const mainDirectory = ( import . meta ? . env ? . ENV _MAIN _BASE _URL )
|| process . env . ENV _MAIN _BASE _URL
2025-11-19 17:26:31 +05:30
|| 'https://www.pozo.app' ;
2025-11-13 09:53:08 +05:30
const rawApiUrl = ( import . meta ? . env ? . ENV _API _URL ) || process . env . ENV _API _URL || '' ;
function normalizeApiBase ( url ) {
if ( ! url ) return '' ;
// If full http/https, use as-is
if ( /^https?:\/\//i . test ( url ) ) return url ;
// If protocol-relative (//domain), prefix https:
if ( /^\/\// . test ( url ) ) return ` https: ${ url } ` ;
// Otherwise, assume domain/path and prefix https://
return ` https:// ${ url } ` ;
}
const CommonApiUrl = normalizeApiBase ( rawApiUrl ) . replace ( /\/$/ , '' ) ;
const routes = [
2025-11-19 17:26:31 +05:30
{ path : "index.html" , pageId : 1 , url : ` ${ mainDirectory } / ` } ,
{ path : "signin/index.html" , pageId : 2 , url : ` ${ mainDirectory } /signin ` } ,
{ path : "pricing/index.html" , pageId : 3 , url : ` ${ mainDirectory } /pricing ` } ,
{ path : "contact-us/index.html" , pageId : 4 , url : ` ${ mainDirectory } /contact-us ` } ,
{ path : "blog/index.html" , pageId : 5 , url : ` ${ mainDirectory } /blog ` } ,
{ path : "about-us/index.html" , pageId : 6 , url : ` ${ mainDirectory } /about-us ` } ,
{ path : "privacy-policy/index.html" , pageId : 7 , url : ` ${ mainDirectory } /privacy-policy ` } ,
{ path : "cookie-policy/index.html" , pageId : 8 , url : ` ${ mainDirectory } /cookie-policy ` } ,
{ path : "solutions/index.html" , pageId : 9 , url : ` ${ mainDirectory } /solutions ` } ,
{ path : "case-studies/index.html" , pageId : 10 , url : ` ${ mainDirectory } /case-studies ` } ,
{ path : "live-session/index.html" , pageId : 11 , url : ` ${ mainDirectory } /live-session ` } ,
{ path : "book-demo/index.html" , pageId : 12 , url : ` ${ mainDirectory } /book-demo ` } ,
{ path : "schedule-demo/index.html" , pageId : 13 , url : ` ${ mainDirectory } /schedule-demo ` } ,
{ path : "solutions/retail-billing/index.html" , pageId : 14 , url : ` ${ mainDirectory } /solutions/retail-billing ` } ,
{ path : "solutions/inventory-purchase/index.html" , pageId : 15 , url : ` ${ mainDirectory } /solutions/inventory-purchase ` } ,
{ path : "solutions/weighing-scale-pos/index.html" , pageId : 16 , url : ` ${ mainDirectory } /solutions/weighing-scale-pos ` } ,
{ path : "solutions/multi-store-erp/index.html" , pageId : 17 , url : ` ${ mainDirectory } /solutions/multi-store-erp ` } ,
{ path : "solutions/gst-billing-e-invoice/index.html" , pageId : 18 , url : ` ${ mainDirectory } /solutions/gst-billing-e-invoice ` } ,
{ path : "solutions/offline-billing/index.html" , pageId : 19 , url : ` ${ mainDirectory } /solutions/offline-billing ` } ,
{ path : "solutions/healthcare-management/index.html" , pageId : 20 , url : ` ${ mainDirectory } /solutions/healthcare-management ` } ,
2025-11-13 09:53:08 +05:30
] ;
const fallbackData = {
1 : {
title : "Retail ERP & POS for Indian MSMEs | POZO" ,
description : "Fast billing, smart inventory, GST-ready POS. POZO helps kirana, mini-supermarkets & retail chains speed checkout, connect weighing scales, and manage multi-store ops." ,
image : ` ${ mainDirectory } /og/home.jpg ` ,
} ,
2 : {
2025-11-19 17:26:31 +05:30
title : "Sign In to PozoApp | Retail ERP & POS Login" ,
description : "Access your business dashboard. Sign in to POZO retail ERP & POS system for billing, inventory management, and business analytics." ,
2025-11-13 09:53:08 +05:30
image : ` ${ mainDirectory } /og/Signin-og.jpg ` ,
} ,
3 : {
title : "Pricing - Retail ERP & POS Plans | POZO" ,
description : "Simple plans for MSMEs. Fast billing, inventory, GST e-invoice, weighing-scale integration, WhatsApp e-bills & multi-store controls. Book a demo." ,
image : ` ${ mainDirectory } /og/pricing-og.jpg ` ,
} ,
4 : {
2025-11-19 17:26:31 +05:30
title : "Contact POZO | Retail ERP & POS Support" ,
description : "Get support and sales information for POZO retail ERP & POS solutions. Contact us for billing software, inventory management, and business automation." ,
2025-11-13 09:53:08 +05:30
image : ` ${ mainDirectory } /og/contact-og.jpg ` ,
} ,
5 : {
title : "POZO Blog — Retail ERP, POS & Grocery Billing Guides" ,
description : "Practical guides on POS billing, weighing-scale integration, GST e-invoices, multi-store ERP & inventory control for Indian retailers." ,
image : ` ${ mainDirectory } /og/blog-og.jpg ` ,
} ,
2025-11-19 17:26:31 +05:30
6 : {
title : "About POZO | Retail ERP & POS Solutions for MSMEs" ,
description : "Learn about POZO's mission to digitize Indian retail businesses with affordable ERP & POS solutions, billing software, and inventory management." ,
image : ` ${ mainDirectory } /og/about-og.jpg ` ,
} ,
7 : {
title : "Privacy Policy | POZO Retail ERP & POS" ,
description : "POZO's privacy policy for retail ERP & POS users. Learn how we protect your business data, billing information, and customer details." ,
image : ` ${ mainDirectory } /og/privacy-og.jpg ` ,
} ,
8 : {
title : "Cookie Policy | POZO Retail ERP & POS" ,
description : "POZO's cookie policy explaining how we use cookies to improve your retail ERP & POS experience and website functionality." ,
image : ` ${ mainDirectory } /og/cookie-og.jpg ` ,
} ,
9 : {
title : "Retail Solutions | ERP & POS Software for Every Business" ,
description : "Comprehensive retail solutions: billing software, inventory management, GST compliance, weighing scale integration, and multi-store ERP for Indian businesses." ,
image : ` ${ mainDirectory } /og/solutions-og.jpg ` ,
} ,
10 : {
title : "Case Studies | POZO Retail ERP & POS Success Stories" ,
description : "Real success stories of Indian retailers using POZO ERP & POS. See how businesses improved billing speed, inventory control, and customer satisfaction." ,
image : ` ${ mainDirectory } /og/case-studies-og.jpg ` ,
} ,
11 : {
title : "Live Demo Session | POZO Retail ERP & POS" ,
description : "Join free live demo sessions of POZO retail ERP & POS. See billing, inventory management, GST features, and weighing scale integration in action." ,
image : ` ${ mainDirectory } /og/live-session-og.jpg ` ,
} ,
12 : {
title : "Book Demo | POZO Retail ERP & POS Free Trial" ,
description : "Book a free demo of POZO retail ERP & POS. Experience fast billing, smart inventory, GST compliance, and business automation for your store." ,
image : ` ${ mainDirectory } /og/book-demo-og.jpg ` ,
} ,
13 : {
title : "Schedule Demo | POZO Retail ERP & POS Consultation" ,
description : "Schedule a personalized demo consultation for POZO retail ERP & POS. Get expert guidance on billing, inventory, and business digitization." ,
image : ` ${ mainDirectory } /og/schedule-demo-og.jpg ` ,
} ,
14 : {
title : "Retail Billing Software | Fast POS for Kirana & Supermarkets" ,
description : "Lightning-fast retail billing software with barcode scanning, GST compliance, customer management, and real-time inventory updates for Indian retailers." ,
image : ` ${ mainDirectory } /og/retail-billing-og.jpg ` ,
} ,
15 : {
title : "Inventory & Purchase Management | Smart Stock Control" ,
description : "Advanced inventory management with purchase orders, supplier management, stock alerts, expiry tracking, and automated reordering for retail businesses." ,
image : ` ${ mainDirectory } /og/inventory-purchase-og.jpg ` ,
} ,
16 : {
title : "Weighing Scale POS | Integrated Billing for Grocery Stores" ,
description : "POS system with weighing scale integration for grocery stores, fruit vendors, and bulk retailers. Accurate billing with weight-based pricing." ,
image : ` ${ mainDirectory } /og/weighing-scale-pos-og.jpg ` ,
} ,
17 : {
title : "Multi-Store ERP | Centralized Retail Chain Management" ,
description : "Manage multiple retail locations with centralized inventory, unified reporting, inter-store transfers, and consolidated business analytics." ,
image : ` ${ mainDirectory } /og/multi-store-erp-og.jpg ` ,
} ,
18 : {
title : "GST Billing & E-Invoice | Compliant Retail Software" ,
description : "GST-compliant billing with automatic e-invoice generation, GSTR filing support, tax calculations, and government portal integration." ,
image : ` ${ mainDirectory } /og/gst-billing-og.jpg ` ,
} ,
19 : {
title : "Offline Billing Software | Works Without Internet" ,
description : "Reliable offline billing software that works without internet. Automatic sync when online, ensuring uninterrupted business operations." ,
image : ` ${ mainDirectory } /og/offline-billing-og.jpg ` ,
} ,
20 : {
title : "Healthcare Management System | Medical Store & Clinic ERP" ,
description : "Specialized ERP for medical stores, clinics, and healthcare providers with medicine inventory, prescription management, and patient records." ,
image : ` ${ mainDirectory } /og/healthcare-og.jpg ` ,
} ,
2025-11-13 09:53:08 +05:30
} ;
async function fetchSEO ( pageId ) {
try {
const response = await axios . get (
` ${ CommonApiUrl } /Seo ` ,
{ params : { pageId } }
) ;
if ( response . data ? . statusCode === 1 && response . data ? . data ? . length > 0 ) {
return response . data . data [ 0 ] ;
}
} catch ( error ) {
console . log ( ` Using fallback for PageId ${ pageId } ` ) ;
}
return null ;
}
async function generateSEOFiles ( ) {
for ( const route of routes ) {
const dbData = await fetchSEO ( route . pageId ) ;
const fallback = fallbackData [ route . pageId ] ;
const seoData = {
title : dbData ? . MetaTitle || fallback . title ,
description : dbData ? . MetaDesc || fallback . description ,
image : dbData ? . ImageUrl || fallback . image ,
url : route . url ,
} ;
// Read the prerendered HTML file for this specific route
const filePath = path . join ( _ _dirname , "../dist" , route . path ) ;
let html ;
2025-11-19 17:26:31 +05:30
// ALWAYS use the specific file path, create directory if needed
fs . mkdirSync ( path . dirname ( filePath ) , { recursive : true } ) ;
2025-11-13 09:53:08 +05:30
if ( fs . existsSync ( filePath ) ) {
2025-11-19 17:26:31 +05:30
// If specific file exists, read it
2025-11-13 09:53:08 +05:30
html = fs . readFileSync ( filePath , "utf8" ) ;
2025-11-19 17:26:31 +05:30
console . log ( ` Reading existing: ${ route . path } ` ) ;
2025-11-13 09:53:08 +05:30
} else {
2025-11-19 17:26:31 +05:30
// Copy from base index.html and modify
const baseHtml = fs . readFileSync (
2025-11-13 09:53:08 +05:30
path . join ( _ _dirname , "../dist/index.html" ) ,
"utf8"
) ;
2025-11-19 17:26:31 +05:30
html = baseHtml ;
console . log ( ` Creating new: ${ route . path } from base ` ) ;
2025-11-13 09:53:08 +05:30
}
// Replace SEO tags in the HTML
html = html
2025-11-19 17:26:31 +05:30
// Replace title
. replace ( /<title>[^<]*<\/title>/g , ` <title> ${ seoData . title } </title> ` )
// Replace meta description (handles multiline)
. replace ( /<meta name="description"[\s\S]*?>/g , ` <meta name="description" content=" ${ seoData . description } " /> ` )
// Replace OG tags
. replace ( /<meta property="og:title" content="[^"]*">/g , ` <meta property="og:title" content=" ${ seoData . title } "> ` )
. replace ( /<meta property="og:description"[\s\S]*?>/g , ` <meta property="og:description" content=" ${ seoData . description } " /> ` )
. replace ( /<meta property="og:image" content="[^"]*">/g , ` <meta property="og:image" content=" ${ seoData . image } "> ` )
. replace ( /<meta property="og:url" content="[^"]*">/g , ` <meta property="og:url" content=" ${ seoData . url } "> ` )
// Replace Twitter tags
. replace ( /<meta property="twitter:title" content="[^"]*">/g , ` <meta property="twitter:title" content=" ${ seoData . title } "> ` )
. replace ( /<meta property="twitter:description"[\s\S]*?>/g , ` <meta property="twitter:description" content=" ${ seoData . description } " /> ` )
. replace ( /<meta property="twitter:image" content="[^"]*">/g , ` <meta property="twitter:image" content=" ${ seoData . image } "> ` )
. replace ( /<meta property="twitter:url" content="[^"]*">/g , ` <meta property="twitter:url" content=" ${ seoData . url } "> ` )
// Replace canonical
. replace ( /<link rel="canonical" href="[^"]*">/g , ` <link rel="canonical" href=" ${ seoData . url } "> ` ) ;
2025-11-13 09:53:08 +05:30
// Write the updated HTML back to the file
fs . writeFileSync ( filePath , html ) ;
2025-11-19 17:26:31 +05:30
console . log ( ` ✓ Generated ${ route . path } with unique SEO data ` ) ;
console . log ( ` Title: ${ seoData . title . substring ( 0 , 50 ) } ... ` ) ;
console . log ( ` URL: ${ seoData . url } ` ) ;
console . log ( ` Image: ${ seoData . image } ` ) ;
console . log ( '' ) ;
2025-11-13 09:53:08 +05:30
}
console . log ( "\n✓ All SEO files generated successfully!" ) ;
}
generateSEOFiles ( ) . catch ( console . error ) ;