import express from 'express'; import path from 'path'; import { fileURLToPath } from 'url'; import seoMiddleware from './seo-middleware.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const PORT = process.env.PORT || 3000; // Configure MIME types for JSX files app.use((req, res, next) => { if (req.path.endsWith('.jsx')) { res.setHeader('Content-Type', 'application/javascript'); } next(); }); // Serve static assets FIRST (CSS, JS, images, fonts) - these MUST work // CRITICAL: These must be BEFORE SEO middleware to prevent JS/CSS from being intercepted // Block /src files in production - they should never be requested // If requested, return 404 immediately to prevent SEO middleware from intercepting app.use('/src', (req, res) => { res.status(404).setHeader('Content-Type', 'text/plain').send('Source files not available in production'); }); // Serve /assets (built files) - BOTH /assets and /home/assets app.use('/assets', express.static(path.join(__dirname, '../dist/assets'))); app.use('/home/assets', express.static(path.join(__dirname, '../dist/assets'))); // Serve /og images - BOTH /og and /home/og app.use('/og', express.static(path.join(__dirname, '../dist/og'))); app.use('/home/og', express.static(path.join(__dirname, '../dist/og'))); // Serve favicon and other root files for /home/ paths app.use('/home/PozoAppFavicon.png', express.static(path.join(__dirname, '../dist/PozoAppFavicon.png'))); app.use('/home/fav.ico', express.static(path.join(__dirname, '../dist/fav.ico'))); app.use('/home/manifest.json', express.static(path.join(__dirname, '../dist/manifest.json'))); // Serve all other static files from dist (but NOT index.html) app.use(express.static(path.join(__dirname, '../dist'), { index: false, // Don't serve index.html automatically setHeaders: (res, filePath) => { // Set correct MIME types if (filePath.endsWith('.css')) { res.setHeader('Content-Type', 'text/css'); } else if (filePath.endsWith('.js')) { res.setHeader('Content-Type', 'application/javascript'); } else if (filePath.endsWith('.html')) { res.status(404).end(); return; } } })); // CRITICAL: Explicit handler for /src/ requests - prevent them from reaching SEO middleware // If static middleware didn't serve it, return 404 instead of falling through app.use('/src', (req, res, next) => { // If we reach here, the static middleware didn't find the file // Return 404 instead of letting it fall through to SEO middleware res.status(404).setHeader('Content-Type', 'text/plain').send('File not found'); }); // 301 Redirects Middleware - SAFE ADDITION (no removal) // Handles duplicate URLs, trailing slashes, and old URL redirects app.use((req, res, next) => { const url = req.url; const host = req.headers.host || ''; // Force HTTPS redirect (if not already HTTPS) if (req.protocol !== 'https' && process.env.NODE_ENV === 'production') { return res.redirect(301, `https://${host}${url}`); } // Remove trailing slash (except for root and directories) if (url.length > 1 && url.endsWith('/') && !url.includes('.')) { return res.redirect(301, url.slice(0, -1)); } // Normalize /home/* to /* (if needed after migration) // Commented out for now - uncomment when ready to remove /home prefix // if (url.startsWith('/home/') && url !== '/home/') { // return res.redirect(301, url.replace('/home', '')); // } // Old URL redirects (add more as needed) const redirectMap = { '/pricing-pozoapp': '/pricing', '/home/pricing-pozoapp': '/pricing', '/home/pricing-pozoapp/': '/pricing', }; if (redirectMap[url]) { return res.redirect(301, redirectMap[url]); } next(); }); // CRITICAL: Apply SEO middleware AFTER static files and redirects // This ensures HTML requests go through SEO middleware // But static assets are served first app.use(seoMiddleware); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); console.log('Dynamic SEO enabled!'); }); export default app;