Last Updated: January 18, 2026 at 21:00 UTC
✓ CONFIRMATION FLOW MOSTLY WORKING (Jan 18, 2026)

What Works:

  • ✓ Custom JS triggers n8n webhook on confirmation
  • ✓ Subscriber marked as verified in database
  • ✓ Contest entry created automatically
  • ✓ Manual drip trigger works
  • ✓ SMTP password fixed (ForwardEmail)
🔴 BLOCKING ISSUE - n8n Webhook Caching

Problem: Added "Trigger Drip Campaign" node to Confirmation workflow but:

  • ✓ Node exists in database and API shows correct connections
  • ✗ Webhook execution uses cached OLD workflow version
  • ✗ Execution skips Trigger Drip Campaign node entirely
  • ✗ Restart/deactivate/reactivate does NOT clear cache

Workaround: Manual drip trigger: curl -X POST .../webhook/drip/trigger -d '{"subscriber_id":X,"email":"...","day":"0"}'

Next Steps: Try editing via n8n web UI or create fresh workflow

See Issues & Blockers for full details.

Architecture Note

Single Docker Host architecture:

  • NGINX SSL Proxy (10.0.0.251) - SSL Termination, Let's Encrypt, Reverse Proxy
  • BennyBeen (10.0.0.250) - PostgreSQL, Shlink, Listmonk, n8n, Traefik, Landing Page

External IP 76.150.65.61 is DYNAMIC - see DNS-UPDATE-PROCESS.md for update procedures.

Task Progress Management Your progress is automatically saved in your browser

Overall Progress

Phase Status Progress Blockers
Phase 1: Infrastructure Setup COMPLETED
100%
-
Phase 2: n8n Workflows 95% DONE
95%
n8n cache issue
Phase 3: QR Production PENDING
0%
Waiting on Phase 2
Phase 4: E2E Testing PENDING
0%
Waiting on Phase 2
Phase 5: Pilot Launch PENDING
0%
-
Phase 6: Full Deployment PENDING
0%
-

Phase 1: Infrastructure Setup

DNS Configuration

A record: @ -> 76.150.65.61 A record: www -> 76.150.65.61 A record: admin -> 76.150.65.61 Verify DNS propagation with dig/nslookup
A record: @ -> 10.0.0.60 A record: www -> 10.0.0.60 A record: hooks -> 76.150.65.61 A record: list -> 76.150.65.61 A record: mail -> 76.150.65.61 MX record: @ -> mail.mad-monkey-creations.com (priority 10) TXT record: SPF configuration TXT record: DKIM key (from ForwardMail.net) TXT record: DMARC policy Verify with mxtoolbox.com
A record: n8n -> 76.150.65.61 A record: traefik -> 76.150.65.61 Verify DNS propagation with dig/nslookup
Review DNS-UPDATE-PROCESS.md for update procedures Set up automated IP change detection Configure notifications for IP changes Test DNS update workflow

PostgreSQL Database

All containers run on single Docker host: bennybeen (10.0.0.250)
Create docker-compose.yml with postgres:16 image Set POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB env vars Mount persistent volume for data at /home/bennybeen/mad-monkey/ Expose port 5432 on 10.0.0.250 Test connection: psql -h 10.0.0.250 -U mm_user -d madmonkey Connection string: postgresql://mm_user:PASSWORD@10.0.0.250:5432/madmonkey Option: Use deploy.sh script for automated deployment
Create 'cards' table (qr_id, type, status, current_slug, move_code, etc.) Create 'scans' table (qr_id, ts, ip, ua, geo_city, geo_region, etc.) Create 'entries' table (qr_id, email, name, user_city, verified, month_bucket) Create 'moves' table (traveler_id, rev, mover_email, pickup_city, drop_city) Create 'nests' table (venue_id, name, city, contact_email, health_score) Create 'users' table (email PK, name, city, tags[], referral_code) Create 'referrals' table (inviter_email, invitee_email, status) Create 'prizes' table (month, winner_email, fulfillment_status) Add indexes on foreign keys and frequently queried fields Use docker exec commands with container names on bennybeen Verify table creation and relationships

Shlink URL Shortener

Pull shlinkio/shlink:stable image Configure docker-compose with PostgreSQL connection to 10.0.0.250:5432 Set DEFAULT_DOMAIN=mmlnk.us Expose port 8081 on 10.0.0.250 Generate API key via Shlink CLI Test API: curl -H "X-Api-Key: xxx" http://10.0.0.250:8081/rest/v3/short-urls Option: Use deploy.sh script for automated deployment
Deploy Traefik container on bennybeen (10.0.0.250:8080) Add Traefik labels to Shlink container Configure public routing: mmlnk.us -> Shlink Configure admin routing: admin.mmlnk.us/rest -> Shlink API (IP-restricted) Enable Let's Encrypt SSL for mmlnk.us Test https://mmlnk.us (should return 404 - no short URL) Test https://admin.mmlnk.us/rest/v3/short-urls Access Traefik dashboard at traefik.janness.com

Listmonk Email Platform

Pull listmonk/listmonk:latest image Create config.toml with PostgreSQL connection to 10.0.0.250:5432 Run initial setup: ./listmonk --install Expose port 9000 on 10.0.0.250 Access web UI: http://10.0.0.250:9000 API endpoint: http://10.0.0.250:9000/api/ Create admin account Option: Use deploy.sh script for automated deployment
Get SMTP credentials from ForwardMail.net Configure SMTP settings in Listmonk UI SMTP server: smtp.forwardemail.net:587 Set sender: hello@mad-monkey-creations.com Test email delivery to personal email Verify SPF/DKIM/DMARC pass with mail-tester.com
Create list: "Mad Monkey - Benny Campaign" Enable double opt-in for list Create template: Welcome email Create template: Story email (Day 1) Create template: Reward email (Day 3 - BANANAS10 code) Create template: Monthly winner announcement Configure webhook endpoint for confirmation events

n8n Workflow Platform

Pull n8nio/n8n:latest image Configure docker-compose with PostgreSQL connection to 10.0.0.250:5432 Expose port 5678 on 10.0.0.250 Access web UI: http://10.0.0.250:5678 Configure external webhook URL: hooks.mad-monkey-creations.com Set up Traefik routing for n8n.janness.com Option: Use deploy.sh script for automated deployment

Landing Page

Design form layout (Name, Email, "Where did you find Benny?") Add Benny branding and imagery Implement form validation (client-side) Add consent checkbox with privacy policy link Configure form POST to n8n webhook endpoint (hooks.mad-monkey-creations.com/webhook/entry) Add CAPTCHA (Cloudflare Turnstile or hCaptcha) - OPTIONAL Test responsive design on mobile devices Deploy mm-adventure container with nginx:alpine Configure Traefik routing for adventure.mad-monkey-creations.com Configure NGINX SSL Proxy (10.0.0.251) for adventure subdomain

Deployment Automation

Review deploy.sh script in /home/bennybeen/mad-monkey/ Execute deploy.sh to deploy all containers Verify all containers are running on 10.0.0.250 Check container health status

Phase 2: n8n Workflow Creation

Workflow 1: Scan Intake

Create webhook trigger: /scan?qr_id=X on n8n (10.0.0.250:5678) Extract qr_id, IP, User-Agent from request Call IP geolocation API (ipapi.co or ipinfo) Anonymize IP address (remove last octet) Insert scan record to PostgreSQL 'scans' table (10.0.0.250:5432) Update 'cards.last_scan_ts' for qr_id Return 302 redirect to mad-monkey-creations.com/benny?qr_id=X Add error handling for invalid qr_id Test with curl: curl -L https://hooks.mad-monkey-creations.com/scan?qr_id=T42

Workflow 2: Email Capture

Create webhook trigger: POST /entry on n8n (10.0.0.250:5678) Extract form data: qr_id, email, name, user_city Validate email format and required fields Check rate limits (monthly entry limit per email) Insert to PostgreSQL 'entries' table (verified=false) at 10.0.0.250:5432 Call Listmonk API (http://10.0.0.250:9000/api/) to create/update subscriber Add tags: qr_campaign, benny, entry_month_YYYY-MM Trigger double opt-in email via Listmonk Return success response to landing page Add error handling for duplicate entries

Workflow 3: Confirmation Handler

Create webhook trigger: POST /listmonk/confirm on n8n (10.0.0.250:5678) Validate webhook signature (if supported by Listmonk) Extract subscriber email from webhook payload Update PostgreSQL 'entries.verified=true' for email at 10.0.0.250:5432 Update 'users' table with confirmed status Trigger Welcome email workflow via Listmonk API (10.0.0.250:9000) Schedule Story email (Day 1 delay) Schedule Reward email (Day 3 delay) Test with manual webhook POST

Workflow 4: Email Drip Campaign

Create scheduled trigger (daily cron) in n8n (10.0.0.250:5678) Query users eligible for Day 1 story email from PostgreSQL (10.0.0.250:5432) Fetch card scan history and build story content Send story email via Listmonk API (http://10.0.0.250:9000/api/) Query users eligible for Day 3 reward email Send reward email with BANANAS10 code Mark drip status in database to avoid duplicates Test with test subscriber

Workflow 5: Monthly Winner Selection

Create cron trigger (1st of each month at 9 AM) in n8n (10.0.0.250:5678) Query all verified entries from previous month from PostgreSQL (10.0.0.250:5432) Select random entry (ORDER BY RANDOM() LIMIT 1) Insert winner to 'prizes' table Send winner notification email via Listmonk (10.0.0.250:9000) Send announcement to full list Log winner selection event Test with mock data

Workflow 6: Card Health Monitoring

Create cron trigger (daily at 8 AM) in n8n (10.0.0.250:5678) Query cards with no scans in 10+ days from PostgreSQL (10.0.0.250:5432) Query cards with no scans in 45+ days (stagnant threshold) Send alert email with card locations via Listmonk (10.0.0.250:9000) Trigger "rescue mission" re-engagement campaign Update 'nests.health_score' based on card activity Test with aged test data

Workflow Testing

Export each workflow as JSON from n8n (10.0.0.250:5678) Store in version control repository at /home/bennybeen/mad-monkey/ Document environment variables required (DB: 10.0.0.250:5432, Listmonk: 10.0.0.250:9000) Test import on fresh n8n instance

Phase 3: QR Card Production

Test Batch

Create 5 test Nest cards (N01-N05) Create 5 test Traveler cards (T01-T05) Register cards in PostgreSQL 'cards' table (10.0.0.250:5432) Generate unique move codes for travelers Create short URLs in Shlink via API (http://10.0.0.250:8081/rest/v3/...) Generate QR codes using mini-qr or qrencode Verify all QR codes scan correctly
Create front design with Big Benny graphic Add tagline: "Track My Monkey" Create back design with QR code Add short URL below QR code Add instructions: "Scan. Tell us where. Confirm email. Monthly winner!" Add move code for traveler cards Export as print-ready PDF (300 DPI, CMYK)
Get quotes from PVC card printers Order 10 business card size (3.5" x 2") PVC cards Verify print quality and QR code scannability Test durability (water resistance, scratch resistance)

Full Production

Create 200-300 Nest card IDs (N001-N300) Create 50-100 Traveler card IDs (T001-T100) Bulk insert to PostgreSQL 'cards' table (10.0.0.250:5432) Bulk create short URLs via Shlink API (http://10.0.0.250:8081/rest/v3/short-urls) Generate all QR codes Create print-ready PDF sheets (multiple cards per page)
Finalize card quantities based on pilot results Get bulk pricing quotes Submit print order Quality check received cards Verify random sample of QR codes scan correctly

Phase 4: End-to-End Testing

Integration Testing

Scan test QR code on mobile device Verify redirect to landing page Submit form with test data Receive double opt-in email Click confirmation link Verify entry marked as verified in database Receive welcome email Receive story email (Day 1) Receive reward email with discount code (Day 3) Verify all database records created correctly
Scan traveler card in City A Submit entry form with move code Move card to City B (simulate with VPN) Scan again in City B Verify 'moves' table records distance and cities Verify story email includes movement narrative

Load and Performance Testing

Attempt rapid-fire scans from same IP Verify rate limiting triggers Attempt multiple entries with same email Verify monthly entry limit enforcement Test CAPTCHA with bot tools Verify VPN detection and validation
Send test emails to Gmail Send test emails to Outlook Send test emails to Yahoo Verify SPF/DKIM/DMARC pass on all providers Check spam score with mail-tester.com (aim for 10/10) Verify unsubscribe links work correctly

Error Handling

Test invalid QR code ID Test malformed email addresses Test database connection failure Test Listmonk API unavailability Test geolocation API failure Verify graceful error messages shown to users Verify errors logged for debugging

Phase 5: Pilot Launch (20-50 cards)

Pilot Deployment

Print 20-50 pilot cards (mix of Nest and Traveler) Identify 10-15 friendly local venues Place Nest cards at venues Distribute Traveler cards to trusted testers Record venue information in 'nests' table Brief venue owners on the campaign

Monitoring and Analytics

Create SQL queries for key metrics Track: Total scans, form submissions, verified entries Track: Scan-to-submission rate, submission-to-verified rate Track: Email deliverability (bounces, opens, clicks) Track: Stuck cards, stagnant cards Track: Geographic distribution of scans Create Grafana or Metabase dashboard (optional)
Daily check of scan activity for first week Review email delivery logs Check for errors or workflow failures Gather feedback from venue owners Gather feedback from participants Identify underperforming venues or cards

Optimization

Adjust email copy based on open/click rates Refine landing page based on conversion rates Fine-tune drip campaign timing Optimize CAPTCHA settings to reduce friction Identify and fix any UX pain points Document lessons learned

Phase 6: Full Deployment (200-300 cards)

Scaling

Review database performance on bennybeen (10.0.0.250:5432) and add indexes if needed Increase PostgreSQL container resources if necessary Configure database backups (daily automated) on bennybeen Set up monitoring alerts (email/SMS for failures) Document disaster recovery procedures for single-server architecture Verify all containers running on 10.0.0.250
Place 200-300 Nest cards at venues across region Distribute 50-100 Traveler cards Create venue partnership agreements Provide venues with marketing materials Track all venue locations in 'nests' table

Ongoing Operations

Set up weekly reporting on key metrics Create playbook for stuck card retrieval Create playbook for monthly winner fulfillment Document venue onboarding process Set up support email for participant questions Create FAQ page on website
Execute monthly winner workflow Contact winner and collect shipping details Order tee-shirt via Printify API Track fulfillment in 'prizes' table Send announcement to email list Post winner announcement on social media

Growth and Iteration

Implement referral system (share Benny, earn extra entries) Create leaderboard for most active cards Add seasonal or themed campaigns Integrate with Etsy shop for product recommendations Create "Benny Ambassador" program for top participants Expand to new geographic regions