const express = require('express'); const router = express.Router(); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const { nanoid } = require('nanoid'); const { generateContent } = require('../services/ai-generator'); const { buildSite } = require('../services/site-builder'); const { takeScreenshots } = require('../services/screenshot'); const { assemblePacket } = require('../services/packet-assembler'); // Configure multer for logo uploads const storage = multer.memoryStorage(); const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 }, // 5MB fileFilter: (req, file, cb) => { const allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']; if (allowed.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('Invalid file type. Only images are allowed.')); } } }); // POST /api/generate - Main pipeline router.post('/generate', upload.single('logo'), async (req, res) => { const clientId = nanoid(12); const clientDir = path.join(__dirname, '..', 'data', clientId); try { // Create client directory fs.mkdirSync(path.join(clientDir, 'screenshots'), { recursive: true }); fs.mkdirSync(path.join(clientDir, 'site'), { recursive: true }); // Parse form data const formData = { agencyName: req.body.agencyName, agencyEmail: req.body.agencyEmail, businessName: req.body.businessName, businessAddress: req.body.businessAddress, businessEmail: req.body.businessEmail, businessPhone: req.body.businessPhone, businessDescription: req.body.businessDescription, }; // Save logo if uploaded let logoPath = null; if (req.file) { const ext = path.extname(req.file.originalname) || '.png'; logoPath = path.join(clientDir, `logo${ext}`); fs.writeFileSync(logoPath, req.file.buffer); formData.logoUrl = `/data/${clientId}/logo${ext}`; } // Step 1: Generate AI content console.log(`[${clientId}] Step 1: Generating AI content...`); const aiContent = await generateContent(formData); // Step 2: Build config — generate subdomain from business name const MAIN_DOMAIN = req.app.locals.MAIN_DOMAIN || 'solvedby.us'; const subdomain = formData.businessName .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, '') .substring(0, 40); const siteUrl = `https://${subdomain}.${MAIN_DOMAIN}`; const localSiteUrl = `http://localhost:8899/sites/${clientId}`; const config = { clientId, subdomain, ...formData, ...aiContent, siteUrl, localSiteUrl, generatedAt: new Date().toISOString(), }; // Save config fs.writeFileSync( path.join(clientDir, 'config.json'), JSON.stringify(config, null, 2) ); // Step 3: Build the static site console.log(`[${clientId}] Step 2: Building website...`); await buildSite(config, clientDir); // Step 4: Take screenshots console.log(`[${clientId}] Step 3: Taking screenshots...`); await takeScreenshots(clientId, clientDir); // Step 5: Assemble compliance packet zip console.log(`[${clientId}] Step 4: Assembling compliance packet...`); await assemblePacket(config, clientDir); // Step 6: Register subdomain → clientId mapping const subdomainIndex = req.app.locals.subdomainIndex; const saveSubdomainIndex = req.app.locals.saveSubdomainIndex; subdomainIndex[subdomain] = clientId; saveSubdomainIndex(); console.log(`[${clientId}] Step 5: Registered subdomain ${subdomain}.${MAIN_DOMAIN}`); console.log(`[${clientId}] ✅ Complete! Site live at ${siteUrl}`); res.json({ success: true, clientId, resultsUrl: `/results/${clientId}`, siteUrl, localSiteUrl: `/sites/${clientId}/`, }); } catch (error) { console.error(`[${clientId}] ❌ Error:`, error); res.status(500).json({ success: false, error: error.message || 'Generation failed', }); } }); module.exports = router;