Merchant Integration - Plan of Action (POA) โ
Document Version: 1.0
Date: 2026-01-11
Status: Planning Phase
Owner: Development Team
Executive Summary โ
This document outlines the plan of action for integrating merchant signup, onboarding, and access to the Lantern merchant dashboard. The current application has merchant UI components (#/merchant, #/merchant/new) but lacks:
- Discovery mechanism - No way for merchants to learn about or access merchant features
- Authentication/authorization - No merchant-specific roles or access control
- Signup flow - No dedicated merchant registration process
- Integration point - Unclear whether merchant portal should be:
- Same domain with role-based routing
- Separate subdomain (
merchant.ourlantern.app) - Settings panel within main app
Decision: Architecture Approach โ
Recommended: Phased Hybrid Approach โ
Phase 1 (Pilot - Current): Role-based routing on same domain
- Why: Fastest to implement, leverages existing Firebase Auth
- How: Add merchant role to user profiles, conditional routing based on role
- Timeline: 1-2 weeks
- Perfect for: San Diego pilot with 5-10 merchants
Phase 2 (Post-Pilot - 6+ months): Separate merchant subdomain
- Why: Clear separation, professional branding, independent deployment
- How: Deploy separate merchant portal at
merchant.ourlantern.app - Timeline: 2-4 weeks
- Trigger: When merchant count > 25 OR when building dedicated merchant mobile apps
Why Not Start with Separate Subdomain? โ
- Over-engineering for pilot: 5-10 merchants don't need enterprise infrastructure
- Auth complexity: Need to sync auth across domains or implement SSO
- Development overhead: Two deployment pipelines, two build processes
- Slower iteration: Changes require coordinating across two codebases
Phase 1: Pilot Implementation Plan โ
1. Data Model Changes โ
User Profile Enhancement โ
// Add to existing user profile schema in Firestore
{
uid: "user123",
email: "merchant@example.com",
lanternName: "Sunny Cafe Owner",
role: "merchant", // NEW: "user" | "merchant" | "admin"
merchantProfile: { // NEW: Optional merchant-specific data
businessName: "Sunny Cafe",
venueId: "venue_xyz", // Link to venue in venues collection
businessType: "cafe", // cafe, bar, restaurant, retail, etc.
approved: true, // Manual approval flag
onboardedAt: "2026-01-11T06:00:00Z"
}
// ... existing profile fields
}Merchant Applications Collection โ
// New collection: merchant_applications
{
id: "app_123",
applicantEmail: "merchant@example.com",
applicantName: "John Doe",
businessName: "Sunny Cafe",
venueAddress: "123 Main St, San Diego, CA",
businessType: "cafe",
phoneNumber: "+1234567890",
message: "I'd love to bring more customers in...",
status: "pending", // pending | approved | rejected
appliedAt: "2026-01-11T06:00:00Z",
reviewedAt: null,
reviewedBy: null,
notes: "" // Admin notes
}2. User-Facing Changes (Discovery & CTA) โ
A. Footer Call-to-Action (Dashboard) โ
Location: src/screens/dashboard/Dashboard.jsx bottom section
Design: Subtle, non-intrusive banner
{/* Merchant CTA - Bottom of dashboard */}
<div className="bg-gradient-to-r from-amber-500/10 to-orange-500/10 border border-amber-500/20 rounded-2xl p-6 mt-8">
<div className="flex items-center justify-between gap-4 flex-wrap">
<div>
<h3 className="text-lg font-semibold text-white mb-1">
Own a bar, cafe, or restaurant?
</h3>
<p className="text-zinc-300 text-sm">
Bring more customers through your doors with Lantern merchant offers.
</p>
</div>
<button
onClick={() => window.location.hash = '#/merchant/signup'}
className="bg-amber-500 text-black px-6 py-3 rounded-xl font-semibold hover:bg-amber-400 transition whitespace-nowrap"
>
Sign Up as Merchant
</button>
</div>
</div>Rationale:
- Non-intrusive placement (bottom, after main content)
- Clear value proposition
- Direct CTA
- Matches existing Lantern design language
B. Profile Settings Link (Optional Discovery) โ
Location: src/screens/profile/ProfileSettings.jsx
Design: Collapsible "Merchant Access" section at bottom
{/* In ProfileSettings component, after main sections */}
<div className="bg-white/5 border border-white/10 rounded-2xl p-6">
<h3 className="text-lg font-semibold text-white mb-2">
Business Owner?
</h3>
<p className="text-zinc-400 text-sm mb-4">
If you own or manage a venue, you can apply for merchant access to create offers and track engagement.
</p>
<button
onClick={() => window.location.hash = '#/merchant/signup'}
className="text-amber-400 hover:text-amber-300 text-sm font-medium"
>
Learn more about merchant features โ
</button>
</div>3. Merchant Signup Flow โ
New Route: #/merchant/signup โ
Location: src/screens/merchant/MerchantSignup.jsx (NEW FILE)
Flow:
- Introduction screen - Explain merchant benefits, pricing, pilot offer
- Application form - Collect business info (name, address, type, contact)
- Submission confirmation - "We'll review and email you within 48 hours"
- Manual review - Admin reviews application, creates merchant account
- Welcome email - Send login credentials + merchant dashboard link
Why manual approval for pilot?
- Quality control (only serious merchants)
- Relationship building (personal touch)
- Fraud prevention (verify business legitimacy)
- Low volume (5-10 merchants = manageable)
Form Fields โ
{
applicantName: string, // Contact person
applicantEmail: string, // Primary contact (becomes login)
businessName: string,
venueAddress: string, // Full address
businessType: select, // cafe | bar | restaurant | retail | other
phoneNumber: string,
website: string (optional),
existingVenue: boolean, // "Is your venue already on Lantern?"
venueId: string (optional), // If yes, link to existing venue
message: textarea, // "Tell us why you want to join" (optional)
agreeToTerms: boolean
}4. Access Control & Routing โ
App.jsx Changes โ
// Add merchant role check
const isMerchant = currentUser && userProfile?.role === 'merchant'
// Conditional routing
{route === '#/merchant' && (
isMerchant ? (
<MerchantDashboard />
) : (
<div className="min-h-screen bg-black flex items-center justify-center px-4">
<div className="max-w-md text-center">
<h2 className="text-2xl font-bold text-white mb-4">Merchant Access Required</h2>
<p className="text-neutral-400 mb-6">
You need merchant access to view this page.
</p>
<button
onClick={() => window.location.hash = '#/merchant/signup'}
className="bg-amber-400 text-black px-6 py-3 rounded-lg font-medium"
>
Apply for Merchant Access
</button>
</div>
</div>
)
)}
{route === '#/merchant/new' && (
isMerchant ? (
<OfferForm />
) : (
// Same access denied UI
)
)}
{route === '#/merchant/signup' && <MerchantSignup />}5. Admin Review Process โ
Admin Dashboard (Future) โ
Route: #/admin/merchant-applications
For now: Manual Firestore Console review
Manual Approval Workflow (Pilot):
- Merchant submits application โ Document created in
merchant_applications - Admin receives notification (email via Cloud Function)
- Admin reviews in Firestore Console:
- Check business legitimacy (Google Maps, website)
- Verify contact info
- Approve or reject
- If approved:
- Update user profile: add
role: "merchant",merchantProfile: {...} - Send welcome email with dashboard link
- Update user profile: add
- If rejected:
- Update application status, add rejection reason in notes
- Send polite rejection email with feedback
Automation (Post-Pilot):
- Cloud Function to send notification emails
- Admin UI to approve/reject with one click
- Automated welcome email with personalized onboarding checklist
6. Firestore Security Rules โ
// firestore.rules additions
// Merchant applications - anyone can create, only admins can read all
match /merchant_applications/{applicationId} {
allow create: if request.auth != null;
allow read: if request.auth.token.role == 'admin'
|| resource.data.applicantEmail == request.auth.token.email;
allow update, delete: if request.auth.token.role == 'admin';
}
// User profiles - enhance to check merchant role
match /users/{userId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == userId
&& (!request.resource.data.diff(resource.data).affectedKeys().hasAny(['role', 'merchantProfile']))
|| request.auth.token.role == 'admin'; // Only admins can change role
}Phase 2: Separate Merchant Portal (Post-Pilot) โ
When to Implement โ
- Trigger 1: Merchant count > 25
- Trigger 2: Building dedicated merchant mobile apps
- Trigger 3: Need for merchant-specific analytics/features diverges significantly from user app
Architecture โ
ourlantern.app โ User app (current)
merchant.ourlantern.app โ Merchant portal (new)
api.ourlantern.app โ Shared API/backend (Firebase Functions)Benefits โ
- Professional branding -
merchant.ourlantern.appfeels more serious - Independent deployment - Update merchant features without affecting user app
- Performance - Smaller bundle size for each app
- SEO - Separate marketing/SEO for merchant audience
Implementation Steps โ
- Create new Vite project in
/merchant-portaldirectory - Set up Cloudflare Pages project for
merchant.ourlantern.app - Implement SSO with Firebase Auth (same auth domain)
- Migrate merchant screens to new portal
- Build merchant-specific features (advanced analytics, multi-venue management)
- Redirect
#/merchantroutes to merchant portal
Timeline & Milestones โ
Week 1: Foundation โ
- [x] Create POA document (this document)
- [ ] Update TODO.md with merchant integration tasks
- [ ] Design merchant signup UI mockups
- [ ] Update Firestore schema and security rules
Week 2: Implementation โ
- [ ] Build
MerchantSignup.jsxcomponent - [ ] Add merchant CTA to Dashboard footer
- [ ] Add merchant role to user profile service
- [ ] Implement access control in App.jsx
- [ ] Test signup โ approval โ access flow
Week 3: Admin & Testing โ
- [ ] Create manual approval workflow documentation
- [ ] Set up notification emails (Cloud Function)
- [ ] Test end-to-end with 2-3 real merchant applications
- [ ] Create merchant onboarding guide documentation
Week 4: Launch Readiness โ
- [ ] Create merchant welcome email template
- [ ] Document merchant support process
- [ ] Add merchant FAQ section
- [ ] Soft launch to partner network (5 merchants)
Risks & Mitigations โ
Risk 1: Low Merchant Signup Rate โ
Mitigation:
- Personal outreach via partner's network
- Clear value prop in CTA (free pilot, no upfront cost)
- Testimonials from early merchants
Risk 2: Manual Approval Bottleneck โ
Mitigation:
- SLA: Review applications within 48 hours
- Automated email notifications
- Simple approve/reject process (no complex workflows)
Risk 3: User Confusion (Merchant CTA Spam) โ
Mitigation:
- Single, subtle CTA in footer (not intrusive)
- Only show to non-merchants
- A/B test placement and copy
Risk 4: Role-Based Auth Complexity โ
Mitigation:
- Use Firebase Custom Claims (built-in role support)
- Simple role check:
userProfile.role === 'merchant' - Document clearly in code comments
Success Metrics (Pilot Phase) โ
Merchant Acquisition โ
- Target: 5-10 approved merchants in 90 days
- Measure: Applications submitted, approval rate, time-to-approval
Merchant Engagement โ
- Target: 70%+ of merchants create at least 1 offer
- Measure: Offers created, active merchants (logged in last 30 days)
User Awareness โ
- Target: 5%+ click-through on merchant CTA
- Measure: CTA impressions, clicks, conversion to application
Operational Health โ
- Target: < 48hr approval SLA, < 5% rejection rate
- Measure: Avg time-to-approval, rejection reasons
Open Questions & Decisions Needed โ
Pricing during pilot?
- Recommendation: Free pilot (no payment integration yet)
- Document pricing in welcome email ("free for 90 days, then $150/month")
Merchant verification?
- Recommendation: Manual for pilot (Google Maps check, website verification)
- Automate post-pilot with business license API
Multi-venue support?
- Recommendation: Single venue for pilot
- Add multi-venue in Phase 2 when needed
Merchant analytics?
- Recommendation: Basic metrics already in MerchantDashboard
- Enhance post-pilot based on feedback
Related Documents โ
- BUSINESS.md - Monetization strategy, pricing models
- PILOT_STRATEGY.md - San Diego pilot plan
- QUICK_START_PILOT.md - Quick reference
- TODO.md - Development task tracker
Changelog โ
- 2026-01-11: Initial POA creation