← 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;
}