36 KiB
Project Felt — Phase 3 Product Specification
Complete Venue Platform
Version: 0.1 Draft Date: 2026-02-28 Depends on: Phase 1 (Tournaments) + Phase 2 (Cash Games)
Table of Contents
- Overview
- Dealer Management
- Player Loyalty System
- Private Venues & Memberships
- Venue Analytics & Reporting
- Public Venue Presence
- Data Architecture
- API Design
- Roadmap
1. Overview
What Phase 3 Adds
Phase 1 manages tournaments. Phase 2 manages cash games. Phase 3 manages everything else — the people, the relationships, and the business intelligence that turn a poker room into a venue that players return to.
Phase 3 has four pillars:
- Dealer Management — Scheduling, skills, shifts, rotation
- Player Loyalty — Points, tiers, rewards, promotions
- Private Venues & Memberships — Access control, member management, invitations
- Analytics & Public Presence — Business intelligence, venue profiles, event publishing
Design Principles
- Everything connects. Dealer scheduling integrates with tournament and cash table assignments. Loyalty points accrue from tournaments AND cash games. Analytics aggregate across all operations.
- Progressive adoption. Venues can enable Phase 3 features individually. A small bar might only want dealer scheduling. A large room wants everything. No feature forces adoption of another.
- Player-visible value. Players should see the value of Phase 3 — loyalty rewards, membership benefits, career stats. This drives word-of-mouth to other venues.
- Operator simplicity. Every Phase 3 feature must be simpler to use than the spreadsheet/whiteboard it replaces. If it's not, we've failed.
2. Dealer Management
2.1 Dealer Profiles
Each dealer is a user in the system (they may also be a player — dual roles supported). Their profile contains:
Identity: Name, contact info, photo, employee ID (venue-assigned)
Skill Tags:
| Category | Tags (examples) |
|---|---|
| Game variants | Hold'em, Omaha, PLO Hi-Lo, Stud, Razz, Draw, Short Deck, Mixed |
| Betting structures | No-Limit, Pot-Limit, Fixed-Limit |
| Format specialization | Cash games, Tournaments, Both |
| Experience level | Trainee, Standard, Experienced, Senior |
| Special skills | High-stakes tables, Final table dealing, Celebrity/VIP events |
| Languages | Danish, English, German, etc. |
Skills are tagged by the venue manager. A dealer can request skill additions (e.g., after training on a new game), subject to manager approval.
Availability Windows: Dealers set weekly recurring availability (e.g., "Available Mon-Fri 4PM-12AM, Sat 12PM-12AM, not available Sunday"). They can override specific dates (e.g., "Unavailable Dec 24-26"). The scheduling system respects these.
2.2 Schedule Management
Shift Templates: Venues define recurring shift templates:
Morning: 10:00 — 18:00
Afternoon: 14:00 — 22:00
Evening: 18:00 — 02:00
Tournament: Based on tournament schedule (variable)
Split: 10:00 — 14:00, 18:00 — 22:00
Templates are building blocks. The actual schedule is assembled from templates assigned to specific dealers on specific dates.
Schedule Builder (Operator UI):
Week view with dealers on the Y-axis and days on the X-axis. Drag-and-drop shift assignment. Color-coded by shift type. Conflict detection (double-booking, availability violations, skill mismatch) shown in real-time.
┌──────────────────────────────────────────────────────────────┐
│ DEALER SCHEDULE — Week of Mar 2 │
│ │
│ Mon Tue Wed Thu Fri Sat Sun │
│ Anna K. [Eve] [Eve] [---] [Eve] [Eve] [Aft] [---] │
│ Mike S. [Mor] [Mor] [Mor] [Mor] [Mor] [---] [---] │
│ Chris L. [Aft] [---] [Aft] [Aft] [Eve] [Eve] [Aft] │
│ Sarah D. [---] [Aft] [Eve] [---] [Aft] [Eve] [Eve] │
│ Tom H. [Mor] [Mor] [Mor] [Mor] [---] [Mor] [---] │
│ │
│ ⚠ Warning: Friday Evening needs 3 dealers, only 2 assigned │
│ ⚠ Warning: Chris L. exceeds 40h this week │
└──────────────────────────────────────────────────────────────┘
Scheduling constraints (auto-enforced):
- Maximum hours per week (configurable, default 40)
- Minimum rest between shifts (configurable, default 10 hours)
- Availability windows respected
- Skill requirements per table/game met
- Minimum staffing levels per shift (configurable)
2.3 Shift Trading
Dealers can trade shifts with each other — the system facilitates this while enforcing skill requirements.
Trading flow:
- Dealer A posts a shift for trade ("Friday Evening available")
- System shows the post to all dealers who: (a) are available that day, (b) have the required skills, (c) wouldn't exceed hour limits
- Dealer B offers to take it
- If manager approval is required (venue-configurable): manager approves/rejects
- If no approval required: trade is instant
- Both dealers notified. Schedule updated. Audit log recorded.
Drop without trade: A dealer can drop a shift (with enough notice, venue-configurable). The system posts it as an open shift. If unclaimed by a threshold time, the manager is notified.
2.4 Dealer Assignment to Tables
Phase 3 connects dealer scheduling to Phase 1 (tournaments) and Phase 2 (cash games):
Cash game dealer assignment:
- Operator assigns a dealer to a cash table from the on-shift dealer pool
- System shows only dealers who: (a) are on shift, (b) have the matching game skill
- Dealer rotation timer (configurable: push every 30/45/60 minutes)
- When the rotation timer hits, system suggests the next dealer and shows who's available
Tournament dealer assignment:
- Tournament tables can have assigned dealers
- Multi-table tournaments: dealers rotate across tables per the rotation schedule
- Final table: system can flag dealers with "final table" skill for assignment
2.5 Dealer Mobile Experience
Dealers access their schedule and shift management via the same mobile PWA (role-based views):
- My Schedule: See upcoming shifts, with venue details and game/table assignments
- Trade Board: See available shifts for trade. Offer to take shifts. Post own shifts.
- Clock In/Out: Tap to start/end shift. Automatic time tracking.
- Notifications: Shift reminders, trade offers, schedule changes, rotation alerts
- Hours Summary: Current week hours, pay period total, overtime status
2.6 Work Hours & Reporting
Automatic tracking: Clock-in/clock-out via mobile or Leaf UI. Break tracking (configurable: paid/unpaid breaks, minimum break duration compliance).
Reports (for venue manager):
- Hours per dealer per period (week, month, pay period)
- Overtime alerts
- No-show / late arrival log
- Shift trade history
- Skill utilization (which game skills are most in-demand)
Export: CSV for payroll integration. Standard format compatible with common payroll systems.
3. Player Loyalty System
3.1 Points Engine
Points are the currency of loyalty. Venues configure how players earn them.
Point accrual rules (all configurable):
| Activity | Default Points | Example |
|---|---|---|
| Tournament entry | 1 point per €1 buy-in | €50 tournament = 50 points |
| Tournament finish (top 10%) | Bonus 50 points | ITM finish = bonus |
| Cash game play | 1 point per hour | 4-hour session = 4 points |
| Cash game buy-in | 0.5 points per €1 | €200 buy-in = 100 points |
| League participation | 10 points per event | Season regular = loyalty bonus |
| Referral | 25 points per new player | Bring a friend |
| Special events | Custom | Venue-defined promotions |
Multipliers (stackable):
- Time-based: "2x points on Tuesday nights" (drive traffic on slow nights)
- Game-based: "1.5x points on PLO tables" (incentivize new games)
- Tier-based: "Gold members earn 1.5x base points"
- Event-based: "3x points during anniversary week"
Point expiry: Configurable. Options: never expire, expire after X months of inactivity, expire after calendar year. Venues choose.
3.2 Tier System
Players progress through tiers based on point accumulation:
| Tier | Threshold (example) | Benefits (example) |
|---|---|---|
| Bronze | 0 points | Base point earning, basic profile |
| Silver | 500 points/quarter | 1.25x point multiplier, priority waitlist |
| Gold | 2,000 points/quarter | 1.5x multiplier, free tournament entry/month, comp credits |
| Platinum | 5,000 points/quarter | 2x multiplier, VIP event access, dedicated floor contact |
Tier configuration:
- Tier names, thresholds, and benefits are fully customizable per venue
- Evaluation period: monthly, quarterly, or annual
- Tier maintenance: "maintain or drop" vs. "earn once, keep forever" (venue choice)
- Grace period: configurable period before tier demotion (e.g., 1 month grace after missing threshold)
3.3 Rewards Catalog
Venues define what players can spend points on:
| Category | Examples |
|---|---|
| Tournament entries | Free buy-in to weekly tournament (500 points) |
| Food & beverage | €10 bar credit (200 points), free coffee (50 points) |
| Merchandise | Venue t-shirt (1,000 points), branded card protector (300 points) |
| Seat upgrades | Priority seat selection in next tournament (100 points) |
| Cash game | Free hour of rake-free play (800 points) |
| Events | VIP event invitation (2,000 points) |
| Custom | Whatever the venue wants to offer |
Redemption flow:
- Player views rewards on mobile → selects reward → confirms
- System deducts points, generates reward voucher with unique code
- Player shows voucher to staff (or staff scans QR code)
- Staff marks voucher as redeemed in the system
- All tracked for analytics (which rewards are popular, cost per redemption)
3.4 Automated Promotions
Venues can create promotions that trigger automatically:
Promotion types:
- Time-based: "Double points every Wednesday 2-6PM"
- Birthday: "100 bonus points on your birthday month"
- Win-back: "Been away 30+ days? Come back and earn 3x points this visit"
- Achievement: "Play your 100th tournament? 500 bonus points"
- Seasonal: "Holiday tournament series — 2x points on all December events"
- Referral: "Refer a friend who plays 3 events — both get 200 bonus points"
Promotions are created in the operator UI with start/end dates, targeting rules, and automatic application. No manual tracking.
3.5 Cross-Venue Loyalty (Multi-Venue Operators)
For operators running multiple venues:
- Player loyalty tier is shared across all venues
- Points earned at any venue count toward tier status
- Rewards can be redeemed at any venue (or restricted to earning venue — operator choice)
- Leaderboards can span all venues or be venue-specific
- Corporate-level promotions push to all venues
3.6 Display & Mobile Integration
Player mobile view:
┌─────────────────────────────┐
│ MY LOYALTY │
│ │
│ ★ GOLD MEMBER │
│ 2,450 / 5,000 to Platinum │
│ ████████░░░░ 49% │
│ │
│ Available Points: 1,200 │
│ Lifetime Points: 8,750 │
│ │
│ [View Rewards] [History] │
│ │
│ Active Promotions: │
│ 🔥 2x points tonight! │
│ 🎂 Birthday month bonus │
└─────────────────────────────┘
Display node views:
- Loyalty leaderboard (top earners this month/quarter)
- Current promotions ("2x Points Tonight!")
- Tier benefits overview
- All auto-cycle in signage playlists
4. Private Venues & Memberships
4.1 Venue Privacy Modes
| Mode | Visibility | Registration |
|---|---|---|
| Public | Anyone sees schedule, events, games | Open — anyone can join |
| Semi-Private | Schedule visible, limited detail | Requires application + approval |
| Private | Invisible to non-members | Invite-only |
Privacy mode affects:
- Public venue page visibility
- Whether the venue appears in search/discovery
- Whether events are listed publicly
- Whether non-members can join waitlists or register for tournaments
4.2 Membership Management
Membership tiers (venue-defined):
| Tier | Example | Access |
|---|---|---|
| Standard | €20/month | Tournament access, cash game access |
| Premium | €50/month | + Priority waitlist, league eligibility |
| VIP | €100/month | + High-stakes games, private events, guest passes |
| Founding | By invitation | Full access, lifetime rate, governance input |
Member lifecycle:
- Application: Player applies via venue page or invitation link
- Approval: Venue operator reviews application. Auto-approve rules (e.g., referred by existing member) available.
- Payment: Monthly/annual fee (tracked in Felt — payment processing via Stripe or venue's own system)
- Active membership: Access granted per tier
- Renewal: Auto-reminder before expiry. Grace period configurable.
- Suspension/Cancellation: Operator can suspend or cancel. Player can self-cancel with configurable notice period.
Invite system:
- Members generate invite links (limited per member per month — configurable)
- Invited players get a pre-approved application
- Referral credit for the inviting member (loyalty points or other reward)
- Guest passes: temporary access for specific events (configurable per tier — e.g., VIP members get 2 guest passes per month)
4.3 Member Communications
In-app messaging:
- Venue → all members (announcements)
- Venue → tier-specific (e.g., VIP event invitations)
- Venue → individual member (private message)
- Delivered via mobile PWA notification + optional email/SMS
Automated communications:
- Welcome message on membership approval
- Renewal reminders (7 days, 1 day before expiry)
- Event announcements (new tournaments, special events)
- Membership tier changes (upgrade/downgrade notifications)
- Win-back messages for lapsed members
4.4 Member Directory (Optional)
Venues can enable a member directory (privacy settings per member):
- Members can see who else is a member (first name + last initial)
- Opt-in: members choose what to share (photo, game preferences, bio)
- Useful for building community in private clubs
- Disabled by default — venue must explicitly enable
5. Venue Analytics & Reporting
5.1 Revenue Dashboard
Real-time revenue tracking:
- Tournament revenue: entry fees collected, house take
- Cash game revenue: rake collected per table, per game type
- Membership revenue: fees collected
- Combined: total revenue by day/week/month/year
Visualizations:
- Revenue trend line (last 30/90/365 days)
- Revenue by source (pie: tournaments vs. cash vs. memberships)
- Revenue by game type (which games make the most money?)
- Revenue by day of week (which nights are strongest?)
- Revenue by time of day (when are the peak revenue hours?)
5.2 Player Analytics
Player engagement metrics:
- Active players (played in last 7/30/90 days)
- New player acquisition rate
- Player retention rate (% returning within 30 days)
- Player lifetime value (total revenue attributed per player)
- Visit frequency distribution
Player segmentation:
- By game preference (tournament vs. cash vs. both)
- By stakes level
- By loyalty tier
- By visit frequency (regular, occasional, lapsed)
- By value (high-value, medium, low)
All player analytics are aggregated — individual player data is not exposed to other players.
5.3 Operational Analytics
Table utilization:
- Seats occupied vs. available over time (heatmap by hour of day / day of week)
- Average table utilization rate
- Table open/close patterns
Tournament analytics:
- Fill rates (registered vs. capacity)
- Average entries per tournament
- Most popular tournament formats
- Late registration patterns
- Prize pool trends
Waitlist analytics:
- Average wait time by game/stakes
- Waitlist conversion rate (joined → seated)
- Waitlist abandonment rate
- Peak demand times
Dealer analytics:
- Hours worked per dealer
- Shift coverage rates
- Trade frequency
- Rotation compliance
5.4 Multi-Venue Benchmarking
For operators with multiple venues:
- Side-by-side venue comparison (revenue, utilization, player engagement)
- Identify best practices from top-performing venues
- Flag underperforming venues with specific metrics
- Cross-venue player flow (which players play at multiple venues?)
5.5 Export & Integration
- CSV export: All reports exportable for Excel/accounting
- PDF reports: Formatted reports for stakeholders
- API access: All analytics available via REST API for custom integrations
- Scheduled reports: Auto-generate and email weekly/monthly reports to venue owner
6. Public Venue Presence
6.1 Venue Profile Page
Each venue gets a public page at venue-name.felt.io (or custom domain):
- Venue name, logo, photos, description
- Location with map
- Hours of operation
- Current games running (live, for public venues)
- Upcoming events and tournaments
- Game offerings (types and stakes)
- Contact information
SEO-optimized for "poker near [city]" searches.
6.2 Event Publishing
Automated schedule publishing:
- Weekly tournament schedule auto-published to venue page
- Upcoming special events with registration
- League schedules and current standings
External publishing (API integrations):
- Poker Atlas format export (automatic submission)
- Hendon Mob format export (tournament results)
- Social media API integration (auto-post new events to venue's Facebook/Instagram)
- iCal feed for players to subscribe to venue schedule
6.3 Online Registration
Players can register for upcoming tournaments from the venue page:
- View tournament details (format, buy-in, blind structure, starting stack)
- Register (with or without pre-payment — venue configurable)
- See current registrant count and capacity
- Cancel registration (within venue's cancellation policy)
- Automatic reminders before the event
7. Data Architecture
New Tables (extends Phase 1 + 2 schema)
-- =====================
-- DEALER MANAGEMENT
-- =====================
CREATE TABLE dealers (
id TEXT PRIMARY KEY,
player_id TEXT REFERENCES players(id), -- Dealer may also be a player
name TEXT NOT NULL,
email TEXT,
phone TEXT,
photo_url TEXT,
employee_id TEXT,
status TEXT NOT NULL DEFAULT 'active', -- active, inactive, terminated
hire_date DATE,
notes TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE dealer_skills (
id TEXT PRIMARY KEY,
dealer_id TEXT NOT NULL REFERENCES dealers(id),
skill_type TEXT NOT NULL, -- game_variant, betting, format, experience, special, language
skill_value TEXT NOT NULL, -- "holdem", "no_limit", "tournament", "senior", "high_stakes", "danish"
verified BOOLEAN NOT NULL DEFAULT false,
verified_by TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE shift_templates (
id TEXT PRIMARY KEY,
name TEXT NOT NULL, -- "Evening"
start_time TIME NOT NULL, -- "18:00"
end_time TIME NOT NULL, -- "02:00"
break_minutes INTEGER DEFAULT 0,
color TEXT, -- Hex color for schedule UI
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE dealer_schedules (
id TEXT PRIMARY KEY,
dealer_id TEXT NOT NULL REFERENCES dealers(id),
date DATE NOT NULL,
template_id TEXT REFERENCES shift_templates(id),
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
status TEXT NOT NULL DEFAULT 'scheduled', -- scheduled, confirmed, in_progress, completed, no_show, traded
actual_start DATETIME,
actual_end DATETIME,
notes TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(dealer_id, date, template_id)
);
CREATE TABLE dealer_availability (
id TEXT PRIMARY KEY,
dealer_id TEXT NOT NULL REFERENCES dealers(id),
day_of_week INTEGER, -- 0=Mon, 6=Sun (NULL for specific date override)
specific_date DATE, -- For one-off availability changes
available_from TIME, -- NULL = not available
available_to TIME,
is_available BOOLEAN NOT NULL DEFAULT true,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE shift_trades (
id TEXT PRIMARY KEY,
schedule_id TEXT NOT NULL REFERENCES dealer_schedules(id),
offering_dealer TEXT NOT NULL REFERENCES dealers(id),
taking_dealer TEXT REFERENCES dealers(id), -- NULL = open for offers
status TEXT NOT NULL DEFAULT 'posted', -- posted, offered, approved, completed, cancelled
requires_approval BOOLEAN NOT NULL DEFAULT false,
approved_by TEXT,
approved_at DATETIME,
notes TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE dealer_time_clock (
id TEXT PRIMARY KEY,
dealer_id TEXT NOT NULL REFERENCES dealers(id),
schedule_id TEXT REFERENCES dealer_schedules(id),
clock_in DATETIME NOT NULL,
clock_out DATETIME,
break_start DATETIME,
break_end DATETIME,
total_hours REAL, -- Calculated on clock-out
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- =====================
-- LOYALTY SYSTEM
-- =====================
CREATE TABLE loyalty_config (
id TEXT PRIMARY KEY,
venue_id TEXT NOT NULL,
point_expiry_months INTEGER, -- NULL = never expire
evaluation_period TEXT DEFAULT 'quarterly', -- monthly, quarterly, annual
grace_period_days INTEGER DEFAULT 30,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_tiers (
id TEXT PRIMARY KEY,
name TEXT NOT NULL, -- "Gold"
sort_order INTEGER NOT NULL,
threshold_points INTEGER NOT NULL, -- Points needed per evaluation period
point_multiplier REAL NOT NULL DEFAULT 1.0,
color TEXT, -- Hex color for UI
icon TEXT, -- Icon identifier
benefits_json TEXT, -- JSON description of benefits
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_accrual_rules (
id TEXT PRIMARY KEY,
activity_type TEXT NOT NULL, -- tournament_entry, cash_hour, cash_buyin, league_event, referral, custom
points_per_unit REAL NOT NULL, -- Points per €1, per hour, per event, etc.
unit TEXT NOT NULL, -- "currency", "hour", "event", "flat"
conditions_json TEXT, -- Optional JSON conditions (game type, stakes, time window)
is_active BOOLEAN NOT NULL DEFAULT true,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_multipliers (
id TEXT PRIMARY KEY,
name TEXT NOT NULL, -- "Tuesday Double Points"
multiplier REAL NOT NULL, -- 2.0 for double
conditions_json TEXT NOT NULL, -- Time windows, game types, tier requirements
start_date DATETIME,
end_date DATETIME,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE player_loyalty (
id TEXT PRIMARY KEY,
player_id TEXT NOT NULL REFERENCES players(id) UNIQUE,
current_tier_id TEXT REFERENCES loyalty_tiers(id),
current_points INTEGER NOT NULL DEFAULT 0,
lifetime_points INTEGER NOT NULL DEFAULT 0,
period_points INTEGER NOT NULL DEFAULT 0, -- Points in current evaluation period
tier_locked_until DATETIME, -- Grace period end
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_transactions (
id TEXT PRIMARY KEY,
player_id TEXT NOT NULL REFERENCES players(id),
type TEXT NOT NULL, -- earn, redeem, expire, adjust
points INTEGER NOT NULL, -- Positive for earn, negative for redeem/expire
source TEXT, -- tournament_id, session_id, promotion_id, reward_id
description TEXT, -- "Tournament entry: Friday €50 NLH"
balance_after INTEGER NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_rewards (
id TEXT PRIMARY KEY,
name TEXT NOT NULL, -- "Free Tournament Entry"
description TEXT,
category TEXT NOT NULL, -- tournament, food_beverage, merchandise, seat, cash_game, event, custom
points_cost INTEGER NOT NULL,
min_tier_id TEXT REFERENCES loyalty_tiers(id), -- Minimum tier to access this reward
quantity_available INTEGER, -- NULL = unlimited
quantity_redeemed INTEGER NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_redemptions (
id TEXT PRIMARY KEY,
player_id TEXT NOT NULL REFERENCES players(id),
reward_id TEXT NOT NULL REFERENCES loyalty_rewards(id),
points_spent INTEGER NOT NULL,
voucher_code TEXT NOT NULL UNIQUE,
status TEXT NOT NULL DEFAULT 'issued', -- issued, redeemed, expired, cancelled
redeemed_at DATETIME,
redeemed_by TEXT, -- Staff member who confirmed redemption
expires_at DATETIME,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE loyalty_promotions (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL, -- time_based, birthday, winback, achievement, seasonal, referral
config_json TEXT NOT NULL, -- Trigger conditions, point amounts, multipliers
start_date DATETIME,
end_date DATETIME,
is_active BOOLEAN NOT NULL DEFAULT true,
auto_apply BOOLEAN NOT NULL DEFAULT true,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- =====================
-- MEMBERSHIPS
-- =====================
CREATE TABLE membership_tiers (
id TEXT PRIMARY KEY,
name TEXT NOT NULL, -- "VIP"
description TEXT,
monthly_fee INTEGER, -- Cents (NULL = free tier)
annual_fee INTEGER, -- Cents (discounted annual option)
max_members INTEGER, -- NULL = unlimited
guest_passes_monthly INTEGER DEFAULT 0,
benefits_json TEXT, -- JSON description of access and benefits
sort_order INTEGER NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE memberships (
id TEXT PRIMARY KEY,
player_id TEXT NOT NULL REFERENCES players(id),
tier_id TEXT NOT NULL REFERENCES membership_tiers(id),
status TEXT NOT NULL DEFAULT 'pending', -- pending, active, suspended, cancelled, expired
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
approved_at DATETIME,
approved_by TEXT,
billing_cycle TEXT DEFAULT 'monthly', -- monthly, annual
current_period_start DATETIME,
current_period_end DATETIME,
auto_renew BOOLEAN NOT NULL DEFAULT true,
cancelled_at DATETIME,
cancel_reason TEXT,
invited_by TEXT REFERENCES players(id),
invite_code TEXT,
notes TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE guest_passes (
id TEXT PRIMARY KEY,
member_id TEXT NOT NULL REFERENCES memberships(id),
guest_name TEXT NOT NULL,
guest_email TEXT,
event_id TEXT, -- Specific event, or NULL for general access
valid_date DATE NOT NULL,
status TEXT NOT NULL DEFAULT 'issued', -- issued, used, expired, cancelled
used_at DATETIME,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE venue_settings_privacy (
id TEXT PRIMARY KEY,
privacy_mode TEXT NOT NULL DEFAULT 'public', -- public, semi_private, private
show_schedule BOOLEAN NOT NULL DEFAULT true,
show_games BOOLEAN NOT NULL DEFAULT true,
show_waitlist BOOLEAN NOT NULL DEFAULT false,
require_membership BOOLEAN NOT NULL DEFAULT false,
member_directory_enabled BOOLEAN NOT NULL DEFAULT false,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
8. API Design
Dealer Management
GET /dealers List dealers
POST /dealers Create dealer profile
GET /dealers/:id Get dealer detail
PUT /dealers/:id Update dealer
POST /dealers/:id/skills Add skill
DELETE /dealers/:id/skills/:skillId Remove skill
GET /schedule Get schedule (date range, filters)
POST /schedule Assign shift
PUT /schedule/:id Update shift
DELETE /schedule/:id Remove shift
GET /shifts/templates List shift templates
POST /shifts/templates Create template
POST /shifts/trades Post shift for trade
GET /shifts/trades List available trades
POST /shifts/trades/:id/offer Offer to take shift
POST /shifts/trades/:id/approve Approve trade (manager)
POST /dealers/:id/clock-in Clock in
POST /dealers/:id/clock-out Clock out
GET /dealers/:id/hours Hours report (date range)
Loyalty System
GET /loyalty/config Get loyalty configuration
PUT /loyalty/config Update loyalty configuration
GET /loyalty/tiers List tiers
POST /loyalty/tiers Create tier
PUT /loyalty/tiers/:id Update tier
GET /loyalty/rules List accrual rules
POST /loyalty/rules Create rule
GET /loyalty/multipliers List active multipliers
POST /loyalty/multipliers Create multiplier
GET /loyalty/rewards List available rewards
POST /loyalty/rewards Create reward
POST /loyalty/redeem Redeem reward (player)
POST /loyalty/redemptions/:id/confirm Confirm redemption (staff)
GET /loyalty/promotions List promotions
POST /loyalty/promotions Create promotion
GET /loyalty/leaderboard Loyalty leaderboard
Player Loyalty (Mobile)
GET /me/loyalty My loyalty status (tier, points, promotions)
GET /me/loyalty/history My point transaction history
GET /me/loyalty/rewards Available rewards for my tier
POST /me/loyalty/redeem Redeem a reward
GET /me/loyalty/vouchers My active vouchers
Memberships
GET /memberships/tiers List membership tiers
POST /memberships/apply Apply for membership
GET /memberships List all memberships (operator)
PUT /memberships/:id Update membership (approve, suspend, etc.)
POST /memberships/:id/renew Trigger renewal
POST /memberships/:id/guest-pass Issue guest pass
GET /memberships/:id/guest-passes List guest passes
GET /me/membership My membership status
POST /me/membership/cancel Cancel my membership
POST /me/membership/invite Generate invite link
Analytics
GET /analytics/revenue Revenue dashboard (date range, source filters)
GET /analytics/players Player engagement metrics
GET /analytics/tables Table utilization metrics
GET /analytics/tournaments Tournament performance metrics
GET /analytics/waitlist Waitlist analytics
GET /analytics/dealers Dealer metrics
GET /analytics/loyalty Loyalty program metrics
GET /analytics/export Export report (CSV/PDF)
Public Venue
GET /venue/profile Public venue profile
PUT /venue/profile Update venue profile (operator)
GET /venue/schedule Public event schedule
GET /venue/games Current games (public venues)
POST /venue/events/:id/register Register for event (player)
GET /venue/events/:id/registrations List registrations (operator)
9. Roadmap
v3.0 — Dealer Management
- Dealer profiles with skill tags
- Shift templates and schedule builder
- Shift trading system
- Clock-in/clock-out with hours tracking
- Dealer assignment to cash tables and tournaments
- Dealer mobile experience (schedule, trade board, clock)
- Basic reporting (hours, shifts, trades)
v3.1 — Player Loyalty
- Points engine with configurable accrual rules
- Tier system with automated evaluation
- Rewards catalog and redemption flow
- Point multipliers (time-based, game-based, tier-based)
- Loyalty display on mobile and venue screens
- Basic promotions (birthday, time-based)
v3.2 — Memberships & Privacy
- Venue privacy modes (public, semi-private, private)
- Membership tiers with fee tracking
- Application and approval workflow
- Invite system and guest passes
- Member communications
- Optional member directory
v3.3 — Analytics & Public Presence
- Revenue dashboards
- Player engagement analytics
- Operational analytics (tables, waitlists, tournaments)
- Public venue profile page
- Event publishing with online registration
- External publishing (Poker Atlas, Hendon Mob, social)
- Scheduled reports
v3.4 — Advanced Features
- Cross-venue loyalty (multi-venue operators)
- Multi-venue benchmarking analytics
- Dealer rotation automation
- Advanced promotions engine (winback, achievement, referral chains)
- Custom reporting builder
- API access for third-party integrations
- White-label options for enterprise
Phase 3 turns Felt from a poker management tool into the operating system for the venue. At this point, every tournament, every cash game, every dealer shift, every player visit, every dollar — it all flows through Felt. That's the endgame.