← back to Wallpaperdistributors

_legacy-directory/server.js

143 lines

const express = require('express');
const path = require('path');
const fs = require('fs');
const helmet = require('helmet');
const compression = require('compression');
const morgan = require('morgan');

const app = express();
const PORT = process.env.PORT || 9932;
const GA_ID = process.env.GA_ID || 'G-NBZ5WTBW8F';

const distributors = JSON.parse(
  fs.readFileSync(path.join(__dirname, 'data', 'distributors.json'), 'utf8')
);

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

app.use(helmet({
  contentSecurityPolicy: false,
  crossOriginEmbedderPolicy: false,
}));
app.use(compression());
app.use(morgan('tiny'));

app.use((req, res, next) => {
  res.set('Cache-Control', 'no-store, must-revalidate');
  next();
});

// Never serve editor/snapshot artifacts from the static root.
app.use((req, res, next) => {
  if (/\.(bak|orig|pre-[^/]*|[^/]*~)$|\.bak\.|\.pre-/i.test(req.path)) {
    return res.status(404).render('404', { site: SITE });
  }
  next();
});

app.use(express.static(path.join(__dirname, 'public'), { maxAge: '1h' }));

const allRegions = Array.from(new Set(distributors.flatMap(d => d.regions))).sort();
const allSegments = Array.from(new Set(distributors.flatMap(d => d.segments))).sort();
const allLines = Array.from(new Set(distributors.flatMap(d => d.lines_carried))).sort();

const SITE = {
  domain: 'wallpaperdistributors.com',
  name: 'Wallpaper Distributors',
  tagline: 'B2B wallcovering distributors, mapped to the lines they carry',
  description: 'Trade index of B2B wallcovering distributors across the U.S. and Canada — searchable by vendor line, region, and project segment. Find which distributor stocks Schumacher, Thibaut, Phillip Jeffries, Cole & Son, Maya Romanoff, Wolf-Gordon, Kravet, and other lines for residential, hospitality, healthcare, multifamily, and commercial projects.',
  email: 'info@wallpaperdistributors.com',
  phone: '888-373-4564',
  address: 'Designer Wallcoverings, 15442 Ventura Bl #102, Sherman Oaks CA 91403',
  ga_id: GA_ID,
};

function sortDistributors(list, sort) {
  const copy = list.slice();
  switch (sort) {
    case 'company':
      return copy.sort((a, b) => a.company.localeCompare(b.company));
    case 'city':
      return copy.sort((a, b) => a.city.localeCompare(b.city));
    case 'lines':
      return copy.sort((a, b) => b.lines_carried.length - a.lines_carried.length);
    case 'years':
      return copy.sort((a, b) => a.founded - b.founded);
    case 'newest':
    default:
      return copy.sort((a, b) => b.id - a.id);
  }
}

app.get('/', (req, res) => {
  const { q, region, segment, line, trade, sort } = req.query;
  let filtered = distributors.slice();

  if (q) {
    const needle = String(q).toLowerCase();
    filtered = filtered.filter(d =>
      d.company.toLowerCase().includes(needle) ||
      d.city.toLowerCase().includes(needle) ||
      d.lines_carried.some(l => l.toLowerCase().includes(needle)) ||
      d.segments.some(s => s.toLowerCase().includes(needle)) ||
      (d.notes || '').toLowerCase().includes(needle)
    );
  }
  if (region) filtered = filtered.filter(d => d.regions.includes(String(region)));
  if (segment) filtered = filtered.filter(d => d.segments.includes(String(segment)));
  if (line) filtered = filtered.filter(d => d.lines_carried.includes(String(line)));
  if (trade === '1') filtered = filtered.filter(d => d.trade_only);

  filtered = sortDistributors(filtered, sort);

  res.render('index', {
    site: SITE,
    distributors: filtered,
    total: distributors.length,
    matched: filtered.length,
    filters: {
      q: q || '',
      region: region || '',
      segment: segment || '',
      line: line || '',
      trade: trade || '',
      sort: sort || 'newest',
    },
    facets: { regions: allRegions, segments: allSegments, lines: allLines },
  });
});

app.get('/distributor/:id', (req, res) => {
  const id = Number(req.params.id);
  const distributor = distributors.find(d => d.id === id);
  if (!distributor) return res.status(404).render('404', { site: SITE });
  const related = distributors
    .filter(d => d.id !== distributor.id && d.lines_carried.some(l => distributor.lines_carried.includes(l)))
    .slice(0, 4);
  res.render('distributor', { site: SITE, distributor, related });
});

app.get('/line/:line', (req, res) => {
  const line = req.params.line;
  const carriers = distributors.filter(d => d.lines_carried.includes(line));
  if (!carriers.length) return res.status(404).render('404', { site: SITE });
  res.render('line', { site: SITE, line, carriers });
});

app.get('/about', (req, res) => {
  res.render('about', { site: SITE });
});

app.get('/healthz', (req, res) =>
  res.json({ ok: true, port: PORT, distributors: distributors.length })
);

app.use((req, res) => res.status(404).render('404', { site: SITE }));

app.listen(PORT, () => {
  console.log(
    `wallpaperdistributors listening on :${PORT} (${distributors.length} distributors loaded, GA ${GA_ID})`
  );
});