← back to Small Business Builder

src/lib/interview-questions.js

202 lines

// Interview question bank for shop owner profiles.
//
// Goals (in priority order):
//   1. Capture the owner's voice — the thing Booksy/Yelp can never replicate.
//   2. Name nearby businesses (restaurants, coffee, bars) — long-tail local SEO.
//      "best coffee near Fellow Barber" / "where to eat after a haircut in Silver Lake"
//   3. Surface neighborhood-specific knowledge — turns each profile into a mini
//      neighborhood guide, which is exactly what visitors are actually searching for.
//   4. Be FUN. Owners hate filling out forms. These should feel like a magazine
//      profile interview, not a customer-onboarding wizard.
//
// Sections group questions visually on both the admin form and the public profile.
//
// Each question:
//   - id          — stable key, used in the JSONB blob (don't rename casually)
//   - section     — 'story' | 'craft' | 'neighborhood' | 'fun'
//   - q           — the prompt the owner sees
//   - placeholder — short example to unblock writer's block
//   - seo_intent  — one-line note on which search query this question is fishing for
//                   (we don't show this to the owner; it's a comment for us)
//   - max_chars   — soft limit; the form lets them go over but warns

export const QUESTIONS = [
  // ----- THE STORY -------------------------------------------------------
  {
    id: 'origin_story',
    section: 'story',
    q: "What's the story? How did this place come to be?",
    placeholder: "We took over this space in 2014 after the original owner retired. The chairs are still original from 1962…",
    seo_intent: "captures historical/legacy queries; '[shop] history', 'oldest barber [neighborhood]'",
    max_chars: 600,
  },
  {
    id: 'who_walks_in',
    section: 'story',
    q: "Who's the person who walks in here? Describe your regulars.",
    placeholder: "A lot of post-production sound editors from the studios up the street, some Eastsider creatives, and the occasional kid getting his first real haircut…",
    seo_intent: "demographic match-making; people self-identify against the description",
    max_chars: 400,
  },
  {
    id: 'one_thing_known_for',
    section: 'story',
    q: "What's the one thing — service, cut, treatment — you're known for?",
    placeholder: "The hot-towel straight razor shave. We're one of three shops in LA still using a real strop…",
    seo_intent: "service-specific search; '[service] in [neighborhood]'",
    max_chars: 300,
  },

  // ----- THE CRAFT -------------------------------------------------------
  {
    id: 'philosophy',
    section: 'craft',
    q: "Your philosophy in one sentence — what do you stand for?",
    placeholder: "Old-school respect, modern technique, and we'll never rush you out the door.",
    seo_intent: "brand voice signal — used for opening editorial blockquote",
    max_chars: 180,
  },
  {
    id: 'mistake_clients_make',
    section: 'craft',
    q: "What's the most common thing people get wrong when they walk in?",
    placeholder: "They show me a photo of a 25-year-old with totally different hair texture. I'd rather know YOUR hair than copy someone else's…",
    seo_intent: "expertise-positioning; reads like an advice column, surfaces in 'how to ask for a haircut' searches",
    max_chars: 400,
  },
  {
    id: 'what_takes_pride',
    section: 'craft',
    q: "What's a small detail you take pride in that most clients never notice?",
    placeholder: "I sterilize the comb between every client. Most shops just use a Barbicide jar for show…",
    seo_intent: "trust signal; 'clean barber [neighborhood]', hygiene-aware searches",
    max_chars: 300,
  },

  // ----- THE NEIGHBORHOOD ------------------------------------------------
  // These are the SEO workhorses. Owners naming actual local businesses by
  // name lights up local-graph queries we'd never rank for organically.
  {
    id: 'fav_restaurant',
    section: 'neighborhood',
    q: "Favorite restaurant within walking distance — where do you actually eat?",
    placeholder: "Night + Market Song on Sunset. The pad see ew is dangerous. Tell Justin we sent you.",
    seo_intent: "WORKHORSE — 'restaurants near [shop]', '[restaurant] [neighborhood]' both reverse-link here",
    max_chars: 280,
  },
  {
    id: 'best_coffee',
    section: 'neighborhood',
    q: "Best coffee in the neighborhood? Be honest, not diplomatic.",
    placeholder: "Maru in Silver Lake. The hojicha latte is unreal. Don't tell them I sent you, they're already too busy.",
    seo_intent: "WORKHORSE — 'best coffee [neighborhood]' is one of the highest-volume local searches",
    max_chars: 280,
  },
  {
    id: 'after_the_chair',
    section: 'neighborhood',
    q: "Someone just got off your chair, has 30 minutes to kill — where do they go?",
    placeholder: "Walk down to Sunset Junction, grab a drink at Bar Stella, sit outside and watch the neighborhood pass. Or hit Skylight Books across the street.",
    seo_intent: "high-intent capture — 'things to do near [shop]', the literal moment the user is reading our page",
    max_chars: 400,
  },
  {
    id: 'date_night',
    section: 'neighborhood',
    q: "Where do you take a date in this neighborhood?",
    placeholder: "Dinner at Botanica, drinks at the bar at Speranza after. Both BYO-good-conversation.",
    seo_intent: "'[neighborhood] date night', 'romantic restaurants [neighborhood]' — high-conversion local searches",
    max_chars: 280,
  },
  {
    id: 'happy_hour',
    section: 'neighborhood',
    q: "Best happy hour walking distance from the shop?",
    placeholder: "Bar Henry, 4-7pm. $8 martinis, $1 oysters Tuesdays. They know me.",
    seo_intent: "happy-hour searches are insanely high-volume in LA",
    max_chars: 280,
  },
  {
    id: 'hidden_gem',
    section: 'neighborhood',
    q: "What's a hidden gem in the neighborhood — a place tourists don't know about?",
    placeholder: "The little Cuban window at Mama's Hot Tamales on Tuesday afternoons. No sign. Cash only. You'll figure it out.",
    seo_intent: "'hidden gems [neighborhood]' — listicle-bait, picks up linkbacks",
    max_chars: 320,
  },
  {
    id: 'piece_of_history',
    section: 'neighborhood',
    q: "Tell me a piece of [neighborhood] history nobody else knows.",
    placeholder: "This whole block used to be a streetcar yard. The terrazzo floors in our shop are from a dance hall that was here in 1948.",
    seo_intent: "'[neighborhood] history' — magnet for local-history-curious traffic; great for inbound links",
    max_chars: 500,
  },

  // ----- FOR FUN ---------------------------------------------------------
  {
    id: 'overrated_underrated',
    section: 'fun',
    q: "What's overrated in this neighborhood? What's underrated?",
    placeholder: "Overrated: brunch lines on Sunday. Underrated: the empanadas at the gas station on Glendale.",
    seo_intent: "voicey content; surfaces as quote in editorial roundups",
    max_chars: 320,
  },
  {
    id: 'soundtrack',
    section: 'fun',
    q: "What's playing in the shop right now?",
    placeholder: "Today: D'Angelo, Voodoo. Always: anything but the radio.",
    seo_intent: "vibe signal; humanizes the profile",
    max_chars: 200,
  },
  {
    id: 'best_thing_heard',
    section: 'fun',
    q: "Best thing a client ever said to you in this chair?",
    placeholder: "An older guy tipped me 50 bucks and said 'this haircut got me my divorce settlement.' Made my year.",
    seo_intent: "social-share-bait; this is the quote that ends up screenshotted on Instagram",
    max_chars: 400,
  },
  {
    id: 'if_not_this',
    section: 'fun',
    q: "If you weren't doing this, what would you be doing?",
    placeholder: "Probably running a record store, badly.",
    seo_intent: "human-interest tail; closes the profile warmly",
    max_chars: 200,
  },
];

// Section metadata for layout.
export const SECTIONS = {
  story:        { label: 'The Story',        order: 1 },
  craft:        { label: 'The Craft',        order: 2 },
  neighborhood: { label: 'The Neighborhood', order: 3 },
  fun:          { label: 'For Fun',          order: 4 },
};

// Group questions by section for rendering.
export function questionsBySection() {
  const out = {};
  for (const q of QUESTIONS) {
    (out[q.section] = out[q.section] || []).push(q);
  }
  // Return in section order
  return Object.entries(SECTIONS)
    .sort((a, b) => a[1].order - b[1].order)
    .map(([key, meta]) => ({ key, ...meta, questions: out[key] || [] }));
}

// Apply per-shop substitutions to every string field on a question
// (e.g., "[neighborhood]" → "Silver Lake"). Substituting across the whole
// object — not just `q` and `placeholder` — keeps fields like `seo_intent`
// from silently leaking literal "[neighborhood]" tokens if surfaced later.
export function localizeQuestion(q, business) {
  const hood = business?.neighborhood || 'the neighborhood';
  const sub = (s) => (typeof s === 'string' ? s.replace(/\[neighborhood\]/g, hood) : s);
  const out = { ...q };
  for (const k of Object.keys(out)) out[k] = sub(out[k]);
  return out;
}