← back to Nodailyworries

server.js

42 lines

// No Daily Worries — insurance guide site. Static content + a lead-capture
// endpoint. Zero-config: serves public/, appends leads to data/leads.jsonl.
const express = require('express');
const fs = require('node:fs');
const path = require('node:path');

const app = express();
const PORT = process.env.PORT || 9931;
const PUB = path.join(__dirname, 'public');
const LEADS = path.join(__dirname, 'data', 'leads.jsonl');

app.use(express.json({ limit: '16kb' }));

// ads.txt served explicitly (authorizes the AdSense account for this domain)
app.get('/ads.txt', (_req, res) => {
  res.type('text/plain').send('google.com, pub-5278231299883833, DIRECT, f08c47fec0942fa0\n');
});

app.get('/healthz', (_req, res) => res.json({ ok: true, site: 'nodailyworries' }));

// lead capture — minimal validation, append-only JSONL
app.post('/api/lead', (req, res) => {
  const { email = '', line = '', zip = '' } = req.body || {};
  if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) return res.status(400).json({ ok: false, error: 'invalid email' });
  const row = {
    ts: new Date().toISOString(),
    email: String(email).slice(0, 200),
    line: String(line).slice(0, 60),
    zip: String(zip).replace(/[^0-9]/g, '').slice(0, 5),
    ip: (req.headers['x-forwarded-for'] || req.socket.remoteAddress || '').toString().split(',')[0].trim(),
  };
  try {
    fs.mkdirSync(path.dirname(LEADS), { recursive: true });
    fs.appendFileSync(LEADS, JSON.stringify(row) + '\n');
  } catch (e) { return res.status(500).json({ ok: false }); }
  res.json({ ok: true });
});

app.use(express.static(PUB, { extensions: ['html'] }));

app.listen(PORT, () => console.log(`nodailyworries on :${PORT}`));