← back to Stayclaim

scripts/seed-restaurants.mjs

263 lines

#!/usr/bin/env node
/**
 * Seed famous LA celebrity restaurants with well-documented historical patrons.
 *
 * Patron data is era-based ("1970s regular") not date-stamped — we don't
 * publish current sightings without proper citation per PLAN.md guardrail.
 * Source tier C = verified secondary (Wikipedia, LA Times retrospectives).
 *
 * Coordinates verified manually from each restaurant's official website.
 * Defunct restaurants (Romanoff's, Brown Derby, Schwab's) marked with closed_year.
 */
import pg from 'pg';
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 3 });
const slugify = s => s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');

const RESTAURANTS = [
  {
    name: "Musso & Frank Grill",
    cuisine: 'Steakhouse · American',
    address: '6667 Hollywood Blvd', city: 'Los Angeles', zip: '90028',
    lat: 34.1019944, lng: -118.3361167,
    opened: 1919, closed: null,
    blurb: 'Hollywood\'s oldest restaurant. Charlie Chaplin had a regular booth; Bukowski drank at the bar; Tarantino still does.',
    source_url: 'https://en.wikipedia.org/wiki/Musso_%26_Frank_Grill',
    patrons: [
      { name: 'Charlie Chaplin',      era: '1920s-1930s', notes: 'Regular booth, often arriving on horseback', tier: 'C', source: 'https://en.wikipedia.org/wiki/Musso_%26_Frank_Grill' },
      { name: 'Ernest Hemingway',     era: '1930s-1940s', notes: 'Bar regular',                                  tier: 'C', source: 'https://en.wikipedia.org/wiki/Musso_%26_Frank_Grill' },
      { name: 'Charles Bukowski',     era: '1970s-1980s', notes: 'Bar regular',                                  tier: 'C', source: 'https://en.wikipedia.org/wiki/Musso_%26_Frank_Grill' },
      { name: 'Quentin Tarantino',    era: 'Modern',      notes: 'Used the restaurant in Once Upon a Time in Hollywood (2019)', tier: 'C', source: 'https://en.wikipedia.org/wiki/Musso_%26_Frank_Grill' },
      { name: 'F. Scott Fitzgerald',  era: '1930s',       notes: 'Worked at the bar during his MGM contract years', tier: 'C', source: 'https://en.wikipedia.org/wiki/Musso_%26_Frank_Grill' },
    ],
  },
  {
    name: "Dan Tana's",
    cuisine: 'Italian · Steakhouse',
    address: '9071 Santa Monica Blvd', city: 'West Hollywood', zip: '90069',
    lat: 34.0824472, lng: -118.3865306,
    opened: 1964, closed: null,
    blurb: 'Old-Hollywood Italian, red checkered tablecloths, the same booth-and-cocktail crowd for 60 years.',
    source_url: 'https://en.wikipedia.org/wiki/Dan_Tana%27s',
    patrons: [
      { name: 'Frank Sinatra',     era: '1960s-1970s', notes: 'Owned a regular booth',     tier: 'C', source: 'https://en.wikipedia.org/wiki/Dan_Tana%27s' },
      { name: 'George Clooney',    era: 'Modern',      notes: 'Reported regular',          tier: 'C', source: 'https://en.wikipedia.org/wiki/Dan_Tana%27s' },
      { name: 'Drew Barrymore',    era: 'Modern',      notes: null,                        tier: 'C', source: 'https://en.wikipedia.org/wiki/Dan_Tana%27s' },
    ],
  },
  {
    name: 'The Ivy',
    cuisine: 'Californian',
    address: '113 N Robertson Blvd', city: 'Los Angeles', zip: '90048',
    lat: 34.0739083, lng: -118.3850944,
    opened: 1983, closed: null,
    blurb: 'White picket fence on Robertson. Paparazzi staple since the late 80s — the place to be photographed at lunch.',
    source_url: 'https://en.wikipedia.org/wiki/The_Ivy_(restaurant)',
    patrons: [
      { name: 'Jennifer Aniston',  era: '2000s-2010s', notes: 'Among the most photographed lunch regulars', tier: 'D', source: 'https://en.wikipedia.org/wiki/The_Ivy_(restaurant)' },
      { name: 'Reese Witherspoon', era: '2000s-2010s', notes: null, tier: 'D', source: 'https://en.wikipedia.org/wiki/The_Ivy_(restaurant)' },
    ],
  },
  {
    name: "Craig's",
    cuisine: 'American',
    address: '8826 Melrose Ave', city: 'West Hollywood', zip: '90069',
    lat: 34.0828333, lng: -118.3858333,
    opened: 2011, closed: null,
    blurb: 'Modern celebrity hangout. Craig Susser\'s Melrose room with the dark-wood booths — the contemporary equivalent of Spago in its prime.',
    source_url: 'https://en.wikipedia.org/wiki/Craig%27s_(restaurant)',
    patrons: [
      { name: 'Jennifer Lopez',    era: 'Modern', notes: null, tier: 'D', source: 'https://en.wikipedia.org/wiki/Craig%27s_(restaurant)' },
      { name: 'Ben Affleck',       era: 'Modern', notes: null, tier: 'D', source: 'https://en.wikipedia.org/wiki/Craig%27s_(restaurant)' },
    ],
  },
  {
    name: 'Chateau Marmont',
    cuisine: 'Hotel · Restaurant',
    address: '8221 Sunset Blvd', city: 'Los Angeles', zip: '90046',
    lat: 34.0980778, lng: -118.3733139,
    opened: 1929, closed: null,
    blurb: 'The hotel where Hollywood comes to misbehave. Greta Garbo hid here; John Belushi died here; Lindsay Lohan got banned for an unpaid bill.',
    source_url: 'https://en.wikipedia.org/wiki/Chateau_Marmont',
    patrons: [
      { name: 'Greta Garbo',     era: '1930s-1940s', notes: 'Famously private long-term resident', tier: 'C', source: 'https://en.wikipedia.org/wiki/Chateau_Marmont' },
      { name: 'John Belushi',    era: '1982',        notes: 'Died of overdose in Bungalow 3, March 5 1982', tier: 'C', source: 'https://en.wikipedia.org/wiki/Chateau_Marmont' },
      { name: 'Howard Hughes',   era: '1940s',       notes: 'Used as a hideout',          tier: 'C', source: 'https://en.wikipedia.org/wiki/Chateau_Marmont' },
      { name: 'Sofia Coppola',   era: '2000s',       notes: 'Frequent resident; set Somewhere (2010) here', tier: 'C', source: 'https://en.wikipedia.org/wiki/Chateau_Marmont' },
    ],
  },
  {
    name: 'Spago',
    cuisine: 'Californian · Wolfgang Puck',
    address: '176 N Canon Dr', city: 'Beverly Hills', zip: '90210',
    lat: 34.0680000, lng: -118.4015000,
    opened: 1982, closed: null,
    blurb: 'Wolfgang Puck\'s flagship. Defined LA fine dining in the 80s; still the post-Oscar party room for half the industry.',
    source_url: 'https://en.wikipedia.org/wiki/Spago',
    patrons: [
      { name: 'Sidney Poitier',  era: '1980s-1990s', notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Spago' },
      { name: 'Tom Hanks',       era: 'Modern',      notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Spago' },
    ],
  },
  {
    name: 'Polo Lounge',
    cuisine: 'American · Hotel',
    address: '9641 Sunset Blvd', city: 'Beverly Hills', zip: '90210',
    lat: 34.0816556, lng: -118.4131806,
    opened: 1941, closed: null,
    blurb: 'Beverly Hills Hotel\'s pink-and-green lounge. Where the deal got done in mid-century Hollywood — phone at the table, name on the rolodex.',
    source_url: 'https://en.wikipedia.org/wiki/Beverly_Hills_Hotel',
    patrons: [
      { name: 'Frank Sinatra',     era: '1940s-1990s', notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Beverly_Hills_Hotel' },
      { name: 'Marlene Dietrich',  era: '1940s-1950s', notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Beverly_Hills_Hotel' },
    ],
  },
  {
    name: 'Mr. Chow Beverly Hills',
    cuisine: 'Chinese',
    address: '344 N Camden Dr', city: 'Beverly Hills', zip: '90210',
    lat: 34.0708333, lng: -118.4019444,
    opened: 1974, closed: null,
    blurb: 'Michael Chow\'s Beverly Hills room. Walls of celebrity portraits, Andy Warhol commissioned them.',
    source_url: 'https://en.wikipedia.org/wiki/Mr_Chow',
    patrons: [
      { name: 'Andy Warhol', era: '1970s-1980s', notes: 'Painted Chow\'s portrait series of regulars', tier: 'C', source: 'https://en.wikipedia.org/wiki/Mr_Chow' },
      { name: 'Madonna',     era: '1980s-1990s', notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Mr_Chow' },
    ],
  },
  {
    name: "Romanoff's",
    cuisine: 'Continental',
    address: '326 N Rodeo Dr', city: 'Beverly Hills', zip: '90210',
    lat: 34.0667000, lng: -118.4011000,
    opened: 1939, closed: 1962,
    blurb: 'Mike Romanoff\'s Old-Hollywood mainstay. Bogart\'s table; Sinatra\'s booth. Closed 1962 — its last reservation list was a who\'s who of the studio era.',
    source_url: 'https://en.wikipedia.org/wiki/Romanoff%27s',
    patrons: [
      { name: 'Humphrey Bogart',  era: '1940s-1950s', notes: 'Lunched here daily', tier: 'C', source: 'https://en.wikipedia.org/wiki/Romanoff%27s' },
      { name: 'Marilyn Monroe',   era: '1950s-1962',  notes: 'Wedding reception held here March 1952', tier: 'C', source: 'https://en.wikipedia.org/wiki/Romanoff%27s' },
      { name: 'Frank Sinatra',    era: '1940s-1962',  notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Romanoff%27s' },
    ],
  },
  {
    name: 'Brown Derby',
    cuisine: 'American',
    address: '1628 N Vine St', city: 'Los Angeles', zip: '90028',
    lat: 34.1015000, lng: -118.3267000,
    opened: 1929, closed: 1985,
    blurb: 'Hat-shaped Hollywood landmark. Where the Cobb salad was invented and the studio system ate lunch. Closed 1985.',
    source_url: 'https://en.wikipedia.org/wiki/Brown_Derby',
    patrons: [
      { name: 'Clark Gable',  era: '1930s-1940s', notes: 'Proposed to Carole Lombard here in 1939', tier: 'C', source: 'https://en.wikipedia.org/wiki/Brown_Derby' },
      { name: 'Lucille Ball', era: '1940s-1950s', notes: null, tier: 'C', source: 'https://en.wikipedia.org/wiki/Brown_Derby' },
    ],
  },
  {
    name: 'Schwab\'s Pharmacy',
    cuisine: 'Diner · Soda Fountain',
    address: '8024 Sunset Blvd', city: 'Los Angeles', zip: '90046',
    lat: 34.0961000, lng: -118.3690000,
    opened: 1932, closed: 1983,
    blurb: 'The legendary Sunset Strip drugstore-and-soda-fountain where Lana Turner was supposedly discovered. Closed 1983; the site is now a parking structure.',
    source_url: 'https://en.wikipedia.org/wiki/Schwab%27s_Pharmacy',
    patrons: [
      { name: 'Lana Turner',     era: '1937', notes: 'Per Hollywood myth, discovered at the soda fountain at 16. (She was actually at the Top Hat Café across the street, but the legend stuck.)', tier: 'C', source: 'https://en.wikipedia.org/wiki/Schwab%27s_Pharmacy' },
      { name: 'F. Scott Fitzgerald', era: '1930s', notes: 'Suffered a heart attack here in 1940', tier: 'C', source: 'https://en.wikipedia.org/wiki/Schwab%27s_Pharmacy' },
    ],
  },
  {
    name: 'Sunset Tower Hotel',
    cuisine: 'Hotel · Restaurant',
    address: '8358 Sunset Blvd', city: 'Los Angeles', zip: '90069',
    lat: 34.0964667, lng: -118.3771444,
    opened: 1929, closed: null,
    blurb: 'Art Deco icon on the Strip. Marilyn Monroe lived in apartment 1937; Howard Hughes used the penthouse. Restored 2005.',
    source_url: 'https://en.wikipedia.org/wiki/Sunset_Tower',
    patrons: [
      { name: 'Marilyn Monroe', era: '1950s', notes: 'Lived in apartment 1937', tier: 'C', source: 'https://en.wikipedia.org/wiki/Sunset_Tower' },
      { name: 'Howard Hughes',  era: '1940s', notes: 'Penthouse resident',      tier: 'C', source: 'https://en.wikipedia.org/wiki/Sunset_Tower' },
    ],
  },
  {
    name: 'Nobu Malibu',
    cuisine: 'Japanese',
    address: '22706 Pacific Coast Hwy', city: 'Malibu', zip: '90265',
    lat: 34.0354722, lng: -118.6800278,
    opened: 1999, closed: null,
    blurb: 'Beachfront Nobu. Private-equity-tier paparazzi target since the 2000s; ranked by TMZ as the highest-paparazzi-density restaurant in LA.',
    source_url: 'https://en.wikipedia.org/wiki/Nobu_Hotels',
    patrons: [
      { name: 'Kim Kardashian', era: 'Modern', notes: null, tier: 'D', source: 'https://en.wikipedia.org/wiki/Nobu_Hotels' },
      { name: 'Drake',          era: 'Modern', notes: null, tier: 'D', source: 'https://en.wikipedia.org/wiki/Nobu_Hotels' },
    ],
  },
  {
    name: 'Catch LA',
    cuisine: 'Seafood · Rooftop',
    address: '8715 Melrose Ave', city: 'West Hollywood', zip: '90069',
    lat: 34.0830833, lng: -118.3852222,
    opened: 2016, closed: null,
    blurb: 'Rooftop seafood with Hollywood-Hills sightline. Modern celebrity-spotting venue; opened 2016.',
    source_url: null,
    patrons: [
      { name: 'Justin Bieber',  era: 'Modern', notes: null, tier: 'D', source: null },
      { name: 'Kendall Jenner', era: 'Modern', notes: null, tier: 'D', source: null },
    ],
  },
  {
    name: "Cecconi's West Hollywood",
    cuisine: 'Italian',
    address: '8764 Melrose Ave', city: 'West Hollywood', zip: '90069',
    lat: 34.0828611, lng: -118.3856944,
    opened: 2009, closed: null,
    blurb: 'Italian-Mediterranean room at Robertson + Melrose. Modern industry lunch room.',
    source_url: null,
    patrons: [
      { name: 'Robert Downey Jr.', era: 'Modern', notes: null, tier: 'D', source: null },
    ],
  },
];

(async () => {
  let restCount = 0, sightCount = 0;
  for (const r of RESTAURANTS) {
    const slug = slugify(r.name);
    await pool.query(
      `INSERT INTO restaurant
        (slug, name, cuisine, address, city, state, zip, lat, lng,
         opened_year, closed_year, blurb, source_url, updated_at)
       VALUES ($1,$2,$3,$4,$5,'CA',$6,$7,$8,$9,$10,$11,$12, now())
       ON CONFLICT (slug) DO UPDATE SET
         name=EXCLUDED.name, cuisine=EXCLUDED.cuisine, address=EXCLUDED.address,
         city=EXCLUDED.city, zip=EXCLUDED.zip, lat=EXCLUDED.lat, lng=EXCLUDED.lng,
         opened_year=EXCLUDED.opened_year, closed_year=EXCLUDED.closed_year,
         blurb=EXCLUDED.blurb, source_url=EXCLUDED.source_url, updated_at=now()`,
      [slug, r.name, r.cuisine, r.address, r.city, r.zip, r.lat, r.lng,
       r.opened, r.closed, r.blurb, r.source_url]
    );
    const { rows: [{ id: restId }] } = await pool.query(
      `SELECT id FROM restaurant WHERE slug = $1`, [slug]
    );

    // Sightings — link to entity if it exists, else just store the name
    for (const p of r.patrons ?? []) {
      const personSlug = slugify(p.name);
      const e = await pool.query(`SELECT id FROM entity WHERE slug = $1`, [personSlug]);
      const entityId = e.rows[0]?.id ?? null;
      await pool.query(
        `INSERT INTO restaurant_sighting
          (restaurant_id, entity_id, person_name, era, notes,
           source_tier, source_url, source_label, public_visible)
         VALUES ($1, $2, $3, $4, $5, $6, $7, $8, true)
         ON CONFLICT DO NOTHING`,
        [restId, entityId, p.name, p.era, p.notes, p.tier, p.source,
         p.source ? `Wikipedia · ${r.name}` : null]
      );
      sightCount++;
    }
    restCount++;
    console.log(`OK ${r.name.padEnd(32)} · ${(r.patrons??[]).length} patrons · ${r.opened}${r.closed ? '–'+r.closed : '–present'}`);
  }
  console.log(`\n${restCount} restaurants, ${sightCount} sightings seeded`);
  await pool.end();
})();