我長期以來一直被地下酒吧文化所吸引。我是說,誰不會呢?這不僅僅是關於精釀雞尾酒和陰鬱的燈光,還有其背後的心理學。有些特殊之處在於其排他性——天鵝絨繩子、秘密暗語,以及那種令人興奮的感覺,好像你是精英圈子內的一分子。所以,去年當一位酒吧老闆找我為這種體驗創建數字版本時,我立刻同意了。建設一家數字地下酒吧不只是隨意的線上支付系統或受密碼保護的入口。這是關於創造能與推開昏暗小巷中隱藏門的刺激冒險相媲美的體驗。

以下是我學到的關於創建線上地下酒吧體驗的一切——從輪換秘密代碼的魔力,到設置誘人的 Stripe 訂閱層級,甚至是讓人們想要在門外排隊的申請流程。

Build a Members-Only Speakeasy Website with Stripe & Digital Door Policy

目錄

為什麼地下酒吧模式在線上行得通

排他性不是某種騙局——它根植於我們的心理。稀缺性會增加欲望。自禁酒令時代以來,地下酒吧一直在玩這種心理遊戲。而且,哇,數字說明了一切:從 2023 年到 2025 年,會員制地下酒吧在城市中增長了 25%。為什麼?因為專業人士渴望在普通酒館裡無法獲得的策劃社交體驗。

你不能忽視數字化。到 2025 年,令人驚人的 70% 的新地下酒吧概念已納入數字元素——具有秘密進入代碼的網站、會員應用程式,甚至是 NFT 式的數字鑰匙。真實世界和數字體驗就像舞蹈搭檔,彼此增強對方的步伐。你在 Instagram 上找到他們,碰到一條神秘的鏈接,破解一個謎題來訪問申請頁面,接受審查,在 Stripe 上支付,每週五收到一個輪換的秘密代碼——然後,砰,你通過那扇秘密隱藏的門進去了。

這不只是建設一個網站。這是在創造一種體驗。

真實世界的地下酒吧會員制模式

在建設任何東西之前,我必須看看實際上什麼東西在發揮作用。以下是一些最令人著迷的地下酒吧正在通過他們的會員制所取得的成就:

場所 進入方式 層級和定價 值得注意的福利
Casa De Lobo (Jersey City) 邀請 + OpenTable 預訂 Red Seal(免費,僅限邀請); Green Seal($1,000/年) 10 位客人的優先預訂、18% 合作夥伴折扣、VIP 活動、私人儲物櫃
Red Phone Booth 撥入物理紅色電話亭的秘密代碼 可選的增強會員資格 每夜代碼輪換,增加物理互動層
No Soliciting 由創始成員進行每月申請審查 單層(基於申請) 超級獨家;耐心加倍作為準入條件
Founder's Room (The Paramount) 會員註冊 個人和公司層級 VIP 見面會、私人入口、禮賓服務、飲食優惠
Gainesville Speakeasy 直接購買 $799 啟動 + $299/年續訂 季度活動租賃、$100 飲料點數、編號馬克杯、每次訪問 3 位客人、多地點訪問

有幾件事真的很引人注目。大約 60% 的繁榮地下酒吧要求推薦或申請——他們不會讓任何持有信用卡的人進來。這種社會證明循環——成員帶入新成員——促進了 Casa De Lobo 的 2 倍會員增長,很大程度上由名人和成員推薦推動。

定價的甜蜜點?啟動費用在 $500-$1,000 之間,年度費用 $200-$400。保留率徘徊在 65% 左右,得益於客人免費額度等福利,這也將推薦提高了大約 20%。

Build a Members-Only Speakeasy Website with Stripe & Digital Door Policy - architecture

設計數字門禁政策

這是大多數人搞砸的地方——他們把門禁政策當作基本登錄頁面。初學者的錯誤。你的入口應該感覺像一個有趣的啟示,而不只是另一種形式。

作為隱藏門的著陸頁面

你的公開頁面?保持謹慎。也許是一張照片,也許是一個地址。Red Phone Booth 的網站基本上是雪茄酒廊店面的數字版本。No Soliciting?他們從字面上告訴你要「耐心等待」。

這個前層的設計技巧:

  • 走黑色和大氣風格——黑色、紅色、一點金色。
  • 最少的文本。讓氛圍吸引他們。
  • 沒有刺眼的「註冊」按鈕。這條路應該感覺是偶然的,而不是被強迫的。
  • 隱藏入口:一個看起來不像的可點擊對象、一個序列,或一個在懸停時出現的代碼輸入。

代碼輸入機制

這是開發者的遊樂場,提供對通過狹縫低聲說出密碼的數字致敬。

// components/DoorEntry.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';

export function DoorEntry() {
  const [code, setCode] = useState('');
  const [error, setError] = useState(false);
  const [shaking, setShaking] = useState(false);
  const router = useRouter();

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    const res = await fetch('/api/verify-code', {
      method: 'POST',
      body: JSON.stringify({ code }),
    });
    
    if (res.ok) {
      // Trigger a "door opening" animation before redirect
      document.body.classList.add('door-reveal');
      setTimeout(() => router.push('/inside'), 1500);
    } else {
      setShaking(true);
      setError(true);
      setTimeout(() => setShaking(false), 500);
    }
  }

  return (
    <form onSubmit={handleSubmit} className={shaking ? 'animate-shake' : ''}>
      <input
        type="text"
        value={code}
        onChange={(e) => setCode(e.target.value.toUpperCase())}
        placeholder="Enter tonight's word"
        className="bg-transparent border-b border-amber-600 text-amber-100
                   text-center text-2xl tracking-widest font-mono
                   focus:outline-none focus:border-amber-400"
        maxLength={12}
        autoComplete="off"
      />
      {error && <p className="text-red-400 text-sm mt-2">Wrong door.</p>}
    </form>
  );
}

想像一下——「Wrong door」比「Invalid code」更俏皮地提示一個誤步。每一個小小的接觸都應該回溯到主題。

構建會員層級

我已經解析了大量競爭對手數據,建議這些層級既融合了易接近性又融合了獨家壯麗:

層級 進入 年度 目標 主要福利
The Knock(僅限邀請) $0 $0 社會證明層 基本訪問、每月 2 個客人免費額度、每週輪換代碼
The Regular $199 啟動 $299/年 核心收入 無限訪問、每月 4 位客人、$50 季度飲料點數、僅限會員活動
The Proprietor $999 啟動 $799/年 高價值 無限客人、私人儲物櫃、禮賓預訂、所有活動優先權、15% 飲食折扣、私人房間訪問
Founding Member $2,500(一次性,限 50 個) 免費終身 啟動資本 + 傳教士 Proprietor 中的一切 + 終身訪問、牆上的名字、每年 2 次創始成員活動

那個免費、僅限邀請的層級至關重要。這是你為推薦引擎播種的方式。付費會員可以邀請有限數量的免費層級人士,在不稀釋品牌的情況下推動漏斗。

Founding Member 層級?絕妙的啟動策略。這是一筆不錯的前期收入(如果你銷售所有 50 個位置,則為 $125k),並培養一支核心樂迷,他們在財務和情感上都已被吸引。

層級的數據庫架構

CREATE TABLE members (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT UNIQUE NOT NULL,
  full_name TEXT NOT NULL,
  tier TEXT NOT NULL CHECK (tier IN ('knock', 'regular', 'proprietor', 'founding')),
  stripe_customer_id TEXT,
  stripe_subscription_id TEXT,
  invited_by UUID REFERENCES members(id),
  guest_passes_remaining INT DEFAULT 2,
  application_status TEXT DEFAULT 'pending' 
    CHECK (application_status IN ('pending', 'approved', 'rejected', 'waitlisted')),
  approved_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  metadata JSONB DEFAULT '{}'
);

CREATE TABLE guest_passes (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  member_id UUID REFERENCES members(id) NOT NULL,
  code TEXT UNIQUE NOT NULL,
  used_at TIMESTAMPTZ,
  guest_name TEXT,
  valid_until TIMESTAMPTZ NOT NULL
);

Supabase 通過其行級安全 (RLS) 政策釘在了上面,這確保成員只能訪問自己的數據、管理員可以監督一切,以及 API 保持安全,所有這些都不需要額外的開發工作。

Stripe 集成以實現循環會員制

Stripe 是這裡的不二選擇。我已經構建了足夠多的訂閱系統來了解陷阱。這是一種從未讓我失望過的方式。

設置產品和價格

首先在 Stripe 的儀表板中設置這些產品:

  • The Regular:$299 年費 + $199 一次性設置費
  • The Proprietor:$799 年費 + $999 一次性設置費
  • Founding Member:單次 $2,500(一次性)

具有混合項目的結帳會話

// app/api/checkout/route.ts
import Stripe from 'stripe';
import { NextRequest, NextResponse } from 'next/server';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

const TIER_CONFIG = {
  regular: {
    lineItems: [
      { price: 'price_regular_initiation', quantity: 1 }, // one-time
      { price: 'price_regular_annual', quantity: 1 },      // recurring
    ],
    mode: 'subscription' as const,
  },
  proprietor: {
    lineItems: [
      { price: 'price_proprietor_initiation', quantity: 1 },
      { price: 'price_proprietor_annual', quantity: 1 },
    ],
    mode: 'subscription' as const,
  },
  founding: {
    lineItems: [
      { price: 'price_founding_lifetime', quantity: 1 },
    ],
    mode: 'payment' as const,
  },
};

export async function POST(req: NextRequest) {
  const { tier, memberId } = await req.json();
  const config = TIER_CONFIG[tier as keyof typeof TIER_CONFIG];
  
  if (!config) {
    return NextResponse.json({ error: 'Invalid tier' }, { status: 400 });
  }

  const session = await stripe.checkout.sessions.create({
    mode: config.mode,
    payment_method_types: ['card'],
    line_items: config.lineItems,
    success_url: `${process.env.NEXT_PUBLIC_URL}/welcome?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.NEXT_PUBLIC_URL}/membership`,
    metadata: { memberId, tier },
    // Include a manual age check since bars typically mean...well, age restrictions
    custom_fields: [
      {
        key: 'dob',
        label: { type: 'custom', custom: 'Date of Birth (must be 21+)' },
        type: 'text',
      },
    ],
  });

  return NextResponse.json({ url: session.url });
}

用於層級激活的 Webhook 處理器

大多數指南放棄的地方:處理的不僅僅是成功交易——想想失敗的續訂、取消、訂閱調整。

// app/api/webhooks/stripe/route.ts
import { headers } from 'next/headers';
import Stripe from 'stripe';
import { createClient } from '@supabase/supabase-js';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
);

export async function POST(req: Request) {
  const body = await req.text();
  const headersList = await headers();
  const sig = headersList.get('stripe-signature')!;

  const event = stripe.webhooks.constructEvent(
    body,
    sig,
    process.env.STRIPE_WEBHOOK_SECRET!
  );

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session;
      const { memberId, tier } = session.metadata!;
      
      await supabase.from('members').update({
        tier,
        stripe_customer_id: session.customer as string,
        stripe_subscription_id: session.subscription as string,
        application_status: 'approved',
        approved_at: new Date().toISOString(),
      }).eq('id', memberId);
      
      // Time for that welcome email with the inaugural secret code
      await fetch(process.env.RESEND_WEBHOOK_URL!, {
        method: 'POST',
        body: JSON.stringify({ memberId, tier, event: 'welcome' }),
      });
      break;
    }
    
    case 'invoice.payment_failed': {
      const invoice = event.data.object as Stripe.Invoice;
      // Use Stripe's Smart Retries to handle beginning dunning and, if necessary, timely downgrading to 'knock' tier
      break;
    }
    
    case 'customer.subscription.deleted': {
      const sub = event.data.object as Stripe.Subscription;
      await supabase.from('members').update({
        tier: 'knock',
        stripe_subscription_id: null,
      }).eq('stripe_subscription_id', sub.id);
      break;
    }
  }

  return new Response('OK', { status: 200 });
}

記住這些費用:Stripe 每筆交易收取約 2.9% + $0.30。在 $299 年度會員上?那大約是 $9。在創始成員的 $2,500 上?你要交給他們大約 $73。不是致命傷,但好計入。

構建技術棧

根據我們的 Next.js 開發項目的經驗,以下是我推薦的工具集:

層級 工具 為什麼
框架 Next.js 15(App Router) 最佳的無伺服器元件混合,具有路由靈活性和出色的開發者體驗
數據庫 Supabase(Postgres + Auth + RLS) 內置認證、實時訂閱、這東西還有行級安全!
支付 Stripe 計費 + 結帳 訂閱的行業巨頭,客户入口輕而易舉
電子郵件 Resend 自動化秘密代碼、歡迎漏斗、續訂通知無故障
CMS(適用於活動/內容) Sanity 或 Payload CMS 事件和菜單管理,無需程式碼
託管 Vercel 邊界函數、API 路由、動態代碼輪換、實時更新——還能更簡單嗎?
排程 Cal.com 或自訂 私人預訂、RSVP、輕鬆排程選項

對於優先考慮內容的酒吧,如事件列表或不斷變化的菜單,無頭 CMS 確保非開發人員可以順暢地更新內容。如果出色的性能和 SEO 比儀表板式體驗更重要,也許考慮 Astro 用於面向公眾的內容,同時為安全的會員門戶保留 Next.js。

秘密代碼系統

這是事情變得有趣的地方:設置一個作業來輪換秘密代碼並將其發送給成員。

// app/api/cron/rotate-code/route.ts
import { createClient } from '@supabase/supabase-js';
import { Resend } from 'resend';

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
);
const resend = new Resend(process.env.RESEND_API_KEY!);

// Secret-hued words fitting the speakeasy culture
const WORDS = [
  'PROHIBITION', 'BATHTUB', 'BOOTLEG', 'MOONSHINE', 'GIGGLEWATER',
  'SPEAKEASY', 'HOOCH', 'BLINDPIG', 'ROTGUT', 'FIREWATER',
  'COFFIN_VARNISH', 'JAZZJUICE', 'NEEDLEBEER', 'PANTHER_SWEAT',
];

export async function GET(req: Request) {
  // Authentication is crucial for our cron secret checks
  const authHeader = req.headers.get('authorization');
  if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response('Unauthorized', { status: 401 });
  }

  const todaysCode = WORDS[Math.floor(Math.random() * WORDS.length)] 
    + '-' + Math.floor(Math.random() * 99).toString().padStart(2, '0');

  // Log the current code
  await supabase.from('active_codes').upsert({
    id: 'current',
    code: todaysCode,
    valid_from: new Date().toISOString(),
    valid_until: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
  });

  // Fetch all approved members
  const { data: members } = await supabase
    .from('members')
    .select('email, full_name')
    .eq('application_status', 'approved');

  // Fire off batch emails using Resend API
  if (members?.length) {
    await resend.batch.send(
      members.map((m) => ({
        from: 'The Door <door@yourspeakeasy.com>',
        to: m.email,
        subject: 'Tonight\'s Word',
        html: `<p style="font-family: monospace; font-size: 24px; 
                text-align: center; color: #d4a574;">${todaysCode}</p>`,
      }))
    );
  }

  return new Response(`Code rotated: ${todaysCode}`, { status: 200 });
}

將其計劃為 Vercel Cron Job 在每天下午 4 點運行(晚間的完美時機):

// vercel.json
{
  "crons": [{
    "path": "/api/cron/rotate-code",
    "schedule": "0 16 * * *"
  }]
}

會員儀表板和獨家功能

既然他們已經進去,你必須在他們的儀表板上提供持續的價值。以下是你想要展示的內容:

  • 今晚的代碼:前置中心,帶有簡單的複製以與批准的客人分享
  • 客人免費額度生成器:成員為每個客人邀請旋轉單次使用的二維碼
  • 活動日曆:RSVP 控制人們秘密地(或不那麼秘密地)等待的東西
  • 飲料點數狀態:想要實時更新?方便!
  • 升級選項:誘惑他們使用他們尚未擁有的層級亮點
  • 預訂功能:預訂私人房間等優先空間
  • 獨家網絡:這個選擇加入的目錄對於那些專業人士聯繫的場所可能是巨大的

Stripe 的客户入口負責細節上的更改和付款,讓你少操心一件事。

申請和審核流程

這是你銷售它不僅僅是一家酒吧的地方。借鑑 No Soliciting 和 Casa De Lobo 的智慧:

  1. 發現:我們的希望者發現隱藏的申請按鈕(通過推薦、彩蛋或停留在某個時髦地點的二維碼)
  2. 申請提交:以下是他們分享的內容——關於自己的基本信息、可選(高度加權)推薦代碼和一小篇短文。
  3. 等待:一個神奇的月度審查流程。延遲是有意的。自動回覆設置期望:「申請每月 1 日進行審查。」
  4. 管理員的回合:通過 Retool 或簡單的管理面板,決策者可以批准、拒絕或列出潛在成員。
  5. 慶祝時間!:以 Stripe 結帳鏈接開始,然後浪費歡迎音符和那誘人的第一個代碼。

延遲批准實際上提高了感知價值。No Soliciting 的「耐心等待」規則?這是天才之舉。

定價策略和收入基準

讓我們將一些現實的數字投入其中:

指標 保守 激進
創始成員(一次性) 30 × $2,500 = $75,000 50 × $2,500 = $125,000
Proprietor 層級(第 1 年) 25 × ($999 + $799) = $44,950 50 × $1,798 = $89,900
Regular 層級(第 1 年) 100 × ($199 + $299) = $49,800 200 × $498 = $99,600
Knock(免費)層級 200 × $0 = $0(但推動推薦) 400 × $0 = $0
第 1 年總計 $169,750 $314,500
第 2 年循環(65% 保留) ~$73,000 ~$146,000

Stripe 費用大約會佔 3-4%。基礎設施成本(Vercel 託管、Supabase、Resend)每月可能花費 $100-$200。考慮到這些數字會員制,利潤邊際看起來金色。

對於 2026 預測,動態定價正在獲得牽引力——根據需求調整啟動費用,大幅增加收入潛力。怎麼樣一些 AI 集成審核工具?預測趨勢顯示他們將增長約 35%。

部署和上線路線圖

計劃在大約一個月內上線 MVP?以下是一個簡單的時間表:

第 1 週:設置舞台。在 Figma 中設計著陸、申請和儀表板。啟動你的 Next.js 和 Supabase 設置,以及 Stripe 產品。釘住那個外觀——美學在這裡有很大關係。

第 2 週:至關重要的基礎工作。整合 NextAuth.js 或 Clerk 進行身份認證、構建 Stripe 流程、修復 webhook,以及設置你的管理員批准界面。

第 3 週:投入你的熱情。開發代碼輪換、門動畫、會員儀表板、客人免費額度系統和通過 Resend 的電子郵件模板。

第 4 週:密封一切。測試整個流程(你想要從申請到進入都順利航行)並使用 Vercel 部署。通過測試版邀請讓一組 10-20 個測試人員來對一切進行壓力測試。

需要一個合作夥伴來建造這樣的東西?聯繫我們。這正是我們的強項,具有透明定價,你將在開始前了解成本和範圍。

常見問題

建設會員專用地下酒吧網站需要花多少錢? 一個 Next.js 和 Supabase 的自訂交易加上 Stripe?想想 $15,000-$40,000,取決於深度。一個更精簡的 Webflow + Memberstack + Stripe 解決方案可能運行 $5,000-$10,000。持續的基礎設施通常保持在每月 $200 以下。記住:便宜的外觀會破壞目的——設計是你的皇后牌。

你可以為此使用 Squarespace 或 Wix 嗎? 是的,但你很快會遇到限制。他們根本無法處理輪換代碼或細微的層級模型。將多個外部工具拼在一起變得昂貴且複雜。對於基礎邀請網站是完美的,但自訂是我們完整地下酒吧故事的關鍵。

處理酒吧會員的年齡驗證? 查看 Stripe Identity 進行身份檢查。為了減少摩擦,在結帳時納入生日字段,進行伺服器檢查。如果某些成員需要上傳身份證?不要跳過那些當地酒精法律——每個地點都有其怪癖細節。

分發秘密代碼的最佳方法? 電子郵件是基本頻道——使用 Resend 或 SendGrid。通過 Twilio 發送代碼片段以增加交付風味。考慮通過 PWA 的推送通知以獲得更多參與度。使用 Telegram 或 Signal 等加密聊天增加秘密觸感。頻繁的代碼輪換?這完全是為了保持動態。

防止成員公開分享秘密代碼? 雖然不可能完全停止,但讓這種努力變得毫無意義。將代碼驗證與活動會話綁定。追蹤代碼進入、提醒懷疑。每個成員的唯一代碼減少洩漏,創建可追蹤的線索。

需要申請或允許開放註冊? 優先應用的方法重新定義了價值並提高了保留率(每年 65% 相比 40% 其他)。甜蜜點?打開一個免費層級加推薦;保留層級需要推薦和申請。

Stripe 的哪些功能是必不可少的? 強制性:Stripe Checkout 進行支付、Billing 進行循環、Webhook 進行數據庫同步、Customer Portal 進行自助服務。在更高端:Stripe Identity 進行身份檢查、Stripe Tax 進行銷售稅計算。單獨 Stripe 的智能重試就可以自動挽救約 10% 的拖欠訂閱。

你可以集成預訂系統嗎? 是的!嵌入現有服務(如 Resy)、使用 Cal.com 作為平衡方法,或工程深入的 Supabase 預訂系統——授予完全靈活性。基於層級的策略茁壯成長——讓更高層級的人更早搶佔預訂。

物理地下酒吧如何將網站與真實門集成? 二維碼驗證名列前茅。成員在門口分享他們的儀表板二維碼,通過工作人員平板電腦驗證。NFC 會員卡(每張 $3-5)是另一條路線。Red Phone Booth 的物理撥號創意仍然是卓越的標準——取得代碼,在電話亭上物理執行它。