INDULGON — Platform Operations Manual
> ## ADMIN USE ONLY — STRICTLY CONFIDENTIAL
>
> This document is for Jillian Janson (platform owner/admin) only. Do NOT share, screenshot, forward, or reference this document with anyone — including partners, investors, developers, contractors, or employees — without explicit written authorization from Jillian.
>
> This manual contains the complete architecture, proprietary scraping methods, database schemas, API internals, competitive advantages, and trade secrets of the Indulgon platform. Anyone with this document and access to the codebase could replicate the entire platform, including features that took months to build. This includes:
>
> - Exact scraping techniques that bypass bot protection on industry databases
> - The full database schema (55+ tables, all columns, all relationships)
> - Every API endpoint, its parameters, and its internal logic
> - The performer tagging viral growth engine and how it works
> - Payment processing architecture and fee calculations
> - Data import/export pipelines for 10+ competitor platforms
>
> If this document is leaked, a competitor could clone Indulgon's core features in weeks instead of the year it took to build them.
>
> Store this file securely. Do not commit it to any public repository. Do not upload it to shared drives. Do not paste sections into AI tools, chat messages, or emails.
Table of Contents
1. [Glossary — Terms You Need to Know](#1-glossary)
2. [Architecture Overview](#2-architecture)
3. [Every Page & What It Does](#3-pages)
4. [Every Route (Backend API) & What It Does](#4-routes)
5. [Every Database Table & What It Stores](#5-tables)
6. [The Connection Map — What Connects to What](#6-connections)
7. [The 7 Layers of a Feature](#7-layers)
8. [How to Ask for Changes — Prompt Templates](#8-prompts)
9. [What Happens When You Add a Feature](#9-checklist)
10. [File Map — Where Everything Lives](#10-files)
1. Glossary — Terms You Need to Know {#1-glossary}
The Basics
| Term | What It Means | Example |
| **Page (HTML)** | What you SEE in the browser. The visual interface. A `.html` file. | `financial.html` is the Financial Hub page |
| **Route (API)** | The BACKEND code that handles data. When a page needs data, it calls a route. A `.js` file in `/routes/`. | `financial-hub.js` handles all money data |
| **Database Table** | Where data is permanently STORED. Lives in PostgreSQL. | `transactions` table stores every dollar |
| **Endpoint** | A specific URL the page calls to get/send data. Part of a route. | `GET /api/financial/transactions` fetches transactions |
| **Frontend** | Everything the user sees — HTML pages, CSS styling, JavaScript interactions | The buttons, forms, lists, colors |
| **Backend** | Everything behind the scenes — routes, database, logic, security | The code that processes data when you click a button |
Feature Components
| Term | What It Means | Why It Matters |
| **UI (User Interface)** | The visual part — buttons, forms, modals, tabs, lists | If something looks wrong or is missing visually, it's a UI issue |
| **API (Application Programming Interface)** | The data pipeline between frontend and backend | If a page loads but shows no data, the API might be broken |
| **Connection** | A link between two features so data flows between them | Booking creates a calendar event = connection |
| **Cross-connection** | When one action updates MULTIPLE other features | Recording a scene → creates transaction + calendar block + timeline event + contacts |
| **Auto-trigger** | Something that happens AUTOMATICALLY when an event occurs | Auto-post to feed when a booking is confirmed |
| **Sync** | Keeping two systems in agreement (e.g., Platform ↔ Notion) | Edit a transaction on platform → updates in Notion too |
| **Entity Link** | A universal connector in the database that links ANY two things | Links a film to a transaction, a contact to a booking, etc. |
| **Cascade** | One action that creates MANY records across multiple tables | Scene cascade: 1 API call → 11 records across 7 tables |
| **Middleware** | Code that runs BEFORE your request reaches the route (security, parsing) | Security middleware checks if you're logged in |
| **Widget** | A small data display embedded in a larger page | Dashboard widgets show pending requests, upcoming events |
| **Modal** | A popup dialog/form that appears over the current page | "Add Transaction" modal on Financial Hub |
| **Toggle** | An on/off switch for a feature | Auto-post toggles in Settings |
| **Tab** | A sub-section within a page | Financial Hub has tabs: Summary, Transactions, Bookings, etc. |
Data Terms
| Term | What It Means |
| **Source of Truth** | The PRIMARY place data lives. For Indulgon, this is PostgreSQL (PG). Notion is a mirror. |
| **Dual-write** | When data is saved to PG first, then also pushed to Notion |
| **Fire-and-forget** | The Notion push doesn't block the main operation — if Notion fails, PG still has the data |
| **Deduplication (Dedup)** | Detecting and linking duplicate records so the same dollar isn't counted twice |
| **Soft delete** | Data is never truly removed — an `is_deleted` flag is set to true. Everything is recoverable. |
| **JSONB** | A PostgreSQL column type that stores flexible JSON data (arrays, objects) |
| **Entity** | Any record in the system — a transaction, film, contact, booking, post, etc. |
| **User scoping** | Every record has a `user_id` so users only see their own data |
Connection Types
| Term | What It Means | Example |
| **Button connection** | A button on Page A that sends you to Page B or triggers Page B's API | "Rebook" button on Financial Hub calls booking API |
| **Data connection** | Page A's data automatically appears on Page B | Scene work transactions show on Filmography page |
| **Auto-create connection** | Creating something on Page A automatically creates a record on Page B | Accepting a booking auto-creates a calendar block |
| **Sync connection** | Two-way data flow between Page A and an external service | Notion bidirectional sync, iCloud Calendar export/import |
| **Cross-page link** | A clickable link on Page A that navigates to a related item on Page B | Contact card → View in Filmography |
| **API dependency** | Page A calls Page B's API to get data it needs | Dashboard calls `/api/dashboard-widgets/summary` which pulls from 10 other APIs |
2. Architecture Overview {#2-architecture}
USER'S BROWSER
│
▼
┌─────────────────────────────────┐
│ HTML Pages (64 files) │ ← What you see (frontend)
│ /public/app/*.html │
│ Styled by: platform.css, │
│ themes.css, editorial-base, │
│ color-customizer.css │
│ Powered by: nav.js, api.js, │
│ themes.js, accessibility.js │
└────────────┬────────────────────┘
│ HTTP requests (fetch)
▼
┌─────────────────────────────────┐
│ Express Server (server.js) │ ← Traffic cop
│ Port 3000, managed by PM2 │
│ Middleware: security, CSV, │
│ mailer, notion-client │
└────────────┬────────────────────┘
│
▼
┌─────────────────────────────────┐
│ Route Modules (137 files) │ ← Business logic (backend)
│ /routes/*.js │
│ 142 mounted API paths │
│ Registered in _register.js │
└────────────┬────────────────────┘
│
┌────┴────┐
▼ ▼
┌──────────┐ ┌──────────┐
│PostgreSQL│ │ Notion │ ← Data storage
│237 tables│ │ 60 DBs │
│SOURCE OF │ │ MIRROR │
│TRUTH │ │(sync copy)│
└──────────┘ └──────────┘
Key Infrastructure
| Component | Location | What It Does |
| **server.js** | `/platform-server/server.js` | Main entry point. Starts Express, loads middleware, registers routes |
| **_register.js** | `/routes/_register.js` | Imports and mounts ALL 142 route modules |
| **PM2** | Process manager | Keeps server running. `pm2 restart platform` to restart |
| **Caddy** | HTTPS proxy | Handles SSL. Routes `indulgon.com` → localhost:3000 |
| **PostgreSQL** | Database | 237 tables. Source of truth for all data |
| **Notion** | Synced mirror | 60 databases. Bidirectional sync. Dashboard/spreadsheet view of data |
Shared JavaScript (loaded on EVERY page)
| File | What It Does |
| `nav.js` | Navigation bar with logo, main links, More dropdown grouped by category |
| `api.js` | Helper functions for API calls |
| `themes.js` | Theme switching (dark/light), monochrome enforcement |
| `editorial-theme.js` | Default "Editorial" template styling |
| `color-customizer.js` | Color wheel for customizing theme colors |
| `accessibility.js` | Voice narration, screen reader, keyboard shortcuts |
| `page-editor.js` | Drag-and-drop layout editing |
| `share-button.js` | Share button functionality |
| `quick-add.js` | Quick-add shortcuts |
| `template-engine.js` | Template switching system |
| `safety-sw.js` | Service Worker for offline panic button |
| `auth-guard.js` | Login requirement enforcement |
3. Every Page & What It Does {#3-pages}
Top Bar (customizable — click "Edit Top Bar" in More dropdown)
Default top bar: Dashboard, Profile, Feed, Bookings, Messages, Safety
Users can add/remove ANY page to the top bar in three ways:
1. +Nav / -Nav buttons — subtle inline buttons next to each page name in the dropdown. Click to instantly add/remove from top bar.
2. Eye icon toggle — bottom-left of dropdown. Click to show/hide the +Nav/-Nav buttons (reduces clutter when not editing).
3. Edit All — bottom-right of dropdown. Opens full checkbox editor overlay.
Show in Both toggle (bottom center of dropdown, or in editor): Controls whether pages pinned to the top bar also appear in their dropdown section, or are hidden from sections to reduce duplication.
All preferences stored in localStorage: nav-topbar (array of hrefs), nav-show-edit-buttons (true/false), nav-show-in-both (true/false).
| Page | File | What It Does |
| Dashboard | `dashboard.html` | Home screen. Stats, widgets, quick links, recent activity, upcoming events |
| Profile | `profile.html` | Public website view. Toggle to edit mode. Awards showcase, timeline |
| Feed | `feed.html` | Social feed. Create posts, cross-post to Twitter, archive, PPV content |
| Bookings | `bookings.html` | All bookings unified. Scene work, strip clubs, video calls. Requests tab. Source filter |
| Messages | `messages-v2.html` | Direct messaging. Free between friends, paid for non-friends to performers |
| Safety | `safety.html` | 11 safety toggles, panic button (3s hold), ride tracking, travel check-ins |
More Dropdown → CONTENT
| Page | File | What It Does |
| Calendar | `content-calendar.html` | Unified calendar. Content, bookings, publicist, strip clubs, shifts. Create Post from events |
| Smart Post | `smart-post.html` | AI-assisted posting. Captions, scheduling, backlog, drip-feed |
| Community | `community.html` | Forums, groups, discussions |
| Portfolio | `portfolio.html` | Professional portfolio/resume display |
| Templates | `templates.html` | Template marketplace. Preview mobile+desktop. Style collections |
| Page Builder | `page-builder.html` | Custom page creation with 37 embeddable feature blocks |
More Dropdown → COMMERCE
| Page | File | What It Does |
| Store | `store-v2.html` | Public-facing storefront where fans browse and buy |
| Marketplace | `marketplace.html` | Browse listings from all sellers |
| Products | `products.html` | **NEW** Inventory management. Physical, digital, worn items. Stats, filters, categories |
| Services | `services.html` | **NEW** Rate card, video calls, cam shows, custom content, companion. Service revenue stats |
| Pricing | `pricing.html` | Subscription tiers and pricing bundles |
More Dropdown → PROFESSIONAL
| Page | File | What It Does |
| Address Book | `address-book.html` | Industry contacts, sync status, Request Booking + Message buttons |
| Publicist | `publicist.html` | PR management. 6 tabs. Engagements auto-create expenses, calendar blocks, timeline events |
| Shifts & Schedule | `shifts.html` | Universal shift management. All user types. Syncs to calendar + bookings + financial |
| Rider | `rider.html` | Hospitality rider for club appearances. Explains what a rider is |
More Dropdown → ENTERTAINMENT
| Page | File | What It Does |
| Live Cams | `cam.html` | Webcam streaming. Credit billing, room types, auto-save all streams |
| Video Calls | `video-calls.html` | Paid video call bookings |
| Music | `music.html` | Connected music library. Spotify/Apple Music sync. Share to feed |
| Gaming | `gaming.html` | Xbox/gaming connections. Tipping feature for play-with-performer |
| Discover | `discover.html` | Browse other users. Empty until users sign up |
More Dropdown → FINANCES
| Page | File | What It Does |
| Financial Hub | `financial.html` | THE money page. All income/expenses/tips/payouts. Dedup engine. Rebook from transactions |
| Earnings | `earnings-v2.html` | Unified income view. 8 stats, 7 tabs, potential vs actual, bookings filter |
| Expenses | `expenses-v2.html` | Expense tracking, categorization, tax-deductible flags |
| Payments | `payments.html` | Stripe + payout methods (Cash App, Venmo, PayPal, etc.) |
| Reports | `reports.html` | Comprehensive reports from all data sources |
| Analytics | `analytics.html` | Social engagement, sales trends, subscriber growth |
More Dropdown → FILES
| Page | File | What It Does |
| Cloud Services | `files.html` | iCloud Drive, Google Drive, etc. connections. Bidirectional sync |
| Vault | `vault.html` | Locked/Private/Hidden media. Scene photos/videos. Version history |
More Dropdown → LIFESTYLE
| Page | File | What It Does |
| Wishlists | `wishlists.html` | Amazon + custom wishlists. Gift tracking. Auto-post when gifted |
| Watchlist | `watchlist.html` | Movies/shows/content to watch |
| Recipes & Nutrition | `recipes.html` | Recipe sharing, food photo analysis, meal planning, nutrition tracking |
| Fitness | `fitness.html` | Workouts, body tracking, YouTube workout embeds |
| Bookmarks | `bookmarks.html` | Save anything from the web. Collections |
More Dropdown → ABOUT
| Page | File | What It Does |
| Biography | `performer.html` | Performer bio, career stats, history. Public sections configurable |
| Filmography | `filmography.html` | All films/scenes. Performer view (all data) vs public view (no financials). Rebook buttons |
| Achievements | `achievements.html` | Milestones, badges, unlocks |
| Social | `social.html` | Unified social notification inbox from all connected platforms |
More Dropdown → ACCOUNT
| Page | File | What It Does |
| Settings | `settings.html` | All preferences. Auto-post toggles, booking prefs, notifications, theme, nav layout |
| Connections | `connections.html` | 33 platform connections. Full walkthroughs. Connection type table. Auth-gated API key reveal (eye toggle requires password/OAuth re-verification). Stripe permission reference modal. |
| Data Import | `import.html` | Universal platform data import. Upload GDPR exports from OnlyFans, SextPanther, Chaturbate, ManyVids, Fansly, MyFreeCams. Auto-detect platform + data type from CSV headers. Per-platform summary cards with earnings breakdown, subscriber overview, message stats. Social Connect section for Hootsuite-style OAuth (Twitter live, Instagram/TikTok/YouTube coming soon). |
Indulgon Connect SDK (Partner Integration)
Indulgon offers an embeddable SDK for partner platforms. Partners embed a JS snippet and get buttons for data import and verification.
Route: partner-sdk.js at /api/connect
Products:
1. Data Export Button — Partner embeds , user clicks, data flows to Indulgon
2. Verification Check — Partner queries /api/connect/api/verify-user to check if a user is verified on Indulgon
3. Push Data API — Partner pushes data to a user's Indulgon account via /api/connect/api/push-data
Pricing: Free (1K calls/mo), Basic $99 (10K), Pro $299 (100K), Enterprise (custom/unlimited)
SDK embed:
<script src="https://api.indulgon.com/connect/sdk.js?key=PARTNER_API_KEY"></script>
<div data-indulgon="import" data-platform="platform-name"></div>
<div data-indulgon="verify"></div>
Identity Verification Passport
Route: verification-passport.js at /api/verification
Performers verify identity once on Indulgon (government ID + selfie, 2257 age verification). Verification is stored as a portable credential that can be shared with partner platforms via time-limited tokens.
Flow: Start verification → Stripe Identity or admin review → Verified status stored → Generate share token → Partner checks token → Returns verified/age/2257 status
Tables: identity_verifications, verification_shares, partner_integrations, partner_api_logs
Share tokens: Time-limited (default 24h), single-use, revocable, scoped (identity/age/2257)
Public-Facing Pages
| Page | Purpose |
| `partners.html` | Partner landing page with pitch, live SDK demo, pricing table, partnership application form, FAQ |
| `sdk-docs.html` | Technical SDK documentation with API reference, code examples, data schemas, rate limits, error codes |
| `import.html` | User-facing data import dashboard with per-platform upload, summary cards, social connect |
Help Center / Support System
Page: support.html — 5-tab help center
Tabs:
| Tab | Content |
| FAQ | General, data, payments, safety questions with expandable answers |
| Your Data | Export, preview, recovery requests, GDPR rights boxes (Articles 15-18, 20) |
| Account | Delete (30-day grace), recover (password/locked/deleted/hacked), merge duplicates |
| Legal/Privacy | Full privacy policy, data usage, what we do NOT do, retention, cookies, GDPR/CCPA, 2257 |
| Support Tickets | Create ticket (8 categories), auto-responses, track history |
Routes:
| Route | Purpose |
| `POST /api/support/create` | Create ticket with auto-tagging and auto-response |
| `POST /api/support/:id/reply` | User replies to ticket |
| `POST /api/support/:id/admin-reply` | Admin replies (with internal notes option) |
| `GET /api/support/:id` | Get ticket + message thread |
| `GET /api/support/` | List user's tickets |
| `PATCH /api/support/:id/status` | Close/reopen ticket |
| `POST /api/account/delete/request` | Request account deletion (generates confirmation code) |
| `POST /api/account/delete/confirm` | Confirm with code, schedules 30-day deletion |
| `POST /api/account/delete/cancel` | Cancel pending deletion |
| `GET /api/account/delete/status` | Check deletion status |
| `POST /api/account/recover/request` | Request recovery (password, locked, deleted, hacked) |
| `POST /api/account/recover/verify` | Verify recovery code |
| `POST /api/account/merge/request` | Request account merge |
Auto-email templates: ticket_created, ticket_resolved, data_request, account_deletion, account_recovery
New tables: support_tickets, ticket_messages, account_deletion_requests, account_recovery_requests, account_merge_requests, auto_email_templates
Performer Tagging System (Viral Growth)
Route: performer-tags.js at /api/tags
When a performer tags someone who isn't on Indulgon (in filmography, financial records, bookings, etc.):
1. A placeholder account is created with the tagged person's name
2. The name is clickable on the tagger's profile (shows a placeholder page)
3. System attempts to find them on social media (Twitter, Instagram)
4. They receive a notification: "[Tagger] created an account for you on Indulgon"
5. When they join, they claim the placeholder — all tags transfer to their real account
6. If they already have a Indulgon account, they merge with the placeholder
| Route | Purpose |
| `POST /api/tags/tag` | Tag a performer (auto-creates placeholder if not on Indulgon) |
| `GET /api/tags/search?q=` | Search real users + placeholders (for autocomplete) |
| `GET /api/tags/placeholder/:id` | View placeholder profile + all tags |
| `POST /api/tags/placeholder/:id/claim` | Claim placeholder, transfer all tags to real account |
| `GET /api/tags/my-tags` | Tags where I was tagged (incoming) |
| `GET /api/tags/my-created-tags` | Tags I created (outgoing) |
| `DELETE /api/tags/tag/:id` | Remove a tag |
| `GET /api/tags/pending-invitations` | Admin: unclaimed placeholders to invite |
| `POST /api/tags/placeholder/:id/mark-invited` | Admin: mark invitation sent |
Tables: placeholder_accounts, performer_tags
Tag contexts: filmography, financial, booking, content, feed_post, scene
Tag roles: co-star, director, photographer, producer, agent, studio
Multi-Signal Lookup System (4 signals):
1. Provided handles (high confidence) — Tagger gives Twitter/Instagram handle directly
2. Industry databases (high/medium) — IAFD, Indexxx search by performer name. Discovers social links, aliases, scene counts, active years
3. Cross-reference handles (low) — If tagger says "@JohnDoe on OnlyFans", system checks Twitter/Instagram for the same username
4. Email (high) — If tagger provides email, direct invitation sent
What we CAN'T use for lookup (privacy/legal):
- IP address (we don't have it, and unsolicited tracking violates GDPR)
- Birthday (useful for verification after they join, not for searching)
- Location (can't search platforms by location for outreach)
Data Export (GDPR Portability)
Users can export ALL their data from Indulgon at any time.
| Route | Purpose |
| `GET /api/export/preview` | Show what data exists (counts by source platform) |
| `POST /api/export/request` | Start an export (full, indulgon_only, imported_only, custom) |
| `GET /api/export/status/:id` | Check export progress (0-100%) |
| `GET /api/export/download/:id` | Download the ZIP file |
| `GET /api/export/history` | List past exports |
| `DELETE /api/export/:id` | Delete an export |
Format: ZIP containing CSV files (one per data type) + manifest.json + README.txt
Source tagging: Every row in every CSV has a data_source column: "indulgon", "onlyfans", "sextpanther", etc.
Includes: Indulgon-native data (uploads, transactions, bookings, profile) + all imported data (earnings, subscribers, messages, payouts from every platform)
Limits: Exports available 7 days, max 5 downloads per export
Data Recovery System
For performers who lost access to platforms (banned, suspended, deleted, locked out).
| Route | Purpose |
| `GET /api/recovery/platforms` | List all supported platforms with GDPR contact info |
| `POST /api/recovery/request` | Create a recovery request (platform, status, what happened, proof) |
| `POST /api/recovery/request/:id/acknowledge` | Accept terms + auto-generate formal GDPR/CCPA letter |
| `POST /api/recovery/request/:id/send` | Send the letter (email or manual) |
| `POST /api/recovery/request/:id/follow-up` | Generate follow-up letter (references deadlines + supervisory authorities) |
| `GET /api/recovery/requests` | List all recovery requests |
| `PATCH /api/recovery/request/:id/status` | Update when platform responds or data arrives |
Legal basis: GDPR Article 15 (right of access) + Article 20 (data portability) or CCPA. Platforms must respond within 30 days (GDPR) / 45 days (CCPA) regardless of account status.
Supported platforms: OnlyFans, SextPanther, Chaturbate, ManyVids, Fansly, MyFreeCams, Pornhub, Stripchat, CAM4, Clips4Sale, LoyalFans, + custom.
Fan Integration (Two-Sided Migration)
When partners add the Indulgon button for both models AND fans:
| Route | Purpose |
| `POST /api/fans/fan-migrate` | Fan onboards from partner platform (with consent choices) |
| `GET /api/fans/model/reconnected-fans` | Model sees which of their fans migrated |
| `GET /api/fans/fan/reconnected-models` | Fan sees which models they follow migrated |
| `GET /api/fans/summary` | Per-platform reconnection counts |
| `POST /api/fans/fan/revoke-consent` | Fan withdraws data sharing consent |
Auto-matching: When both a model and their fan migrate from the same platform, the system automatically reconnects the relationship. Both get notified.
Fan consent is granular: Basic profile (always), payment method (opt-in), message history (opt-in), spending history (opt-in). All logged with timestamps for GDPR audit. |
| Address Book | `address-book.html` | Industry contacts, sync status, Request Booking + Message buttons |
| Rider | `rider.html` | Hospitality rider for club appearances. Explains what a rider is |
| Legal | `legal.html` | Legal documents, 2257 records, GDPR |
| FAQ & Hosting | `faq.html` | Help center |
| Admin | `admin.html` | Admin controls |
| Setup Guide | `setup-guide.html` | Interactive step-by-step guide for everything |
Other Pages (not in nav)
| Page | File | Purpose |
| `login.html` | Login/signup |
| `onboarding.html` | New user onboarding flow (basic 5-step) |
| `tutorial.html` | Interactive demo: 35-step walkthrough across 8 phases. Shows example data, accepts real user input. Covers: account creation, platform connections, data import, native content, financial setup, bookings/safety, content/social, advanced features |
| `pricing.html` | Platform pricing display |
| `tos.html` | Terms of service |
| `oauth-callback.html` | OAuth return handler |
| `companion-services.html` | Companion booking services |
| `asmr.html` | ASMR content features |
| `house-girl.html` | House/live-in content features |
| `findom.html` | Financial domination features |
| `fundraiser.html` | Crowdfunding/fundraiser features |
| `archive.html` | Archived content (preserves original timestamps) |
| `used-items.html` | Legacy used items (replaced by Store Items tab) |
| `store.html` | Legacy store (replaced by store-v2) |
| `messages.html` | Legacy messages (replaced by messages-v2) |
| `earnings-v2.html` | Earnings breakdown |
| `expenses.html` | Legacy expenses |
| `mockup-dashboard.html` | Design mockup |
| `cost-comparison.html` | Platform cost comparison tool |
| `management-guide.html` | Management/operations guide |
4. Every Route (Backend API) & What It Does {#4-routes}
Routes are the BACKEND code. When a page needs data, it calls a route's endpoint.
Core Data Routes
| Route File | API Path | What It Handles |
| `financial-hub.js` | `/api/financial` | Transactions, CSV import, Plaid sync, categories, dedup scan, clean totals, screenshot import |
| `filmography.js` | `/api/filmography` | Films, performer earnings, costars, favorites, award-worthy flags |
| `bookings-full.js` | `/api/bookings` | Unified bookings (scene work + platform bookings) |
| `booking-requests.js` | `/api/booking-system` | Booking requests, preferences, calendar blocks, availability, rebook, promote, publicists, strip clubs, calendar-to-post |
| `feed.js` | `/api/feed` | Posts, likes, comments, PPV, cross-posting |
| `commerce.js` | `/api/commerce` | Products, orders, store operations |
| `store-v2.js` | `/api/store` | Store items, listings, sales |
| `payments.js` | `/api/payments` | Tips, subscriptions, payment processing |
| `payouts.js` | `/api/payouts` | Payout requests, commission tracking, fee models |
| `earnings.js` | `/api/earnings` | Earnings breakdown, statements |
| `expenses.js` | `/api/expenses` | Expense tracking, categorization |
User & Profile Routes
| Route File | API Path | What It Handles |
| `auth.js` | `/api/auth` | Login, signup, OAuth, test users |
| `settings.js` | `/api/settings` | User preferences, notification settings |
| `performer-profile.js` | `/api/performer` | Performer bio, stats, profile data |
| `profile-discovery.js` | `/api/profile` | Aliases, Wikipedia, news articles |
| `performers.js` | `/api/performers` | Performer directory/search |
| `user-types.js` | `/api/user-types` | User type management (performer, studio, agent, publicist, strip_club, fan) |
| `account-types.js` | `/api/account-types` | Account tier management |
| `onboarding-flows.js` | `/api/onboarding` | New user onboarding steps |
Content Routes
| Route File | API Path | What It Handles |
| `content-calendar.js` | `/api/calendar`, `/api/content-calendar` | Content scheduling, calendar events |
| `custom-pages.js` | `/api/pages` | Custom page builder with 37 feature blocks |
| `templates-marketplace.js` | `/api/templates` | 133 templates, marketplace, purchases, ratings |
| `vault.js` | `/api/vault` | Locked/private/hidden media, version history |
| `archive.js` | `/api/archive` | Content archival (preserves timestamps) |
| `portfolio.js` | `/api/portfolio` | Professional portfolio items |
| `smart-post.js` | `/api/smart-post` | AI captions, scheduling, backlog, drip-feed |
Social & Communication Routes
| Route File | API Path | What It Handles |
| `messages.js` | `/api/dm` | Direct messaging, conversations |
| `social.js` | `/api/social` | Social accounts, notifications from connected platforms |
| `social-mirror.js` | `/api/social-mirror` | Import content from Twitter/Instagram/websites |
| `twitter.js` | `/api/twitter` | Twitter cross-post, profile, media upload |
| `cross-post.js` | `/api/cross-post` | Multi-platform cross-posting |
| `community.js` | (inline) | Forums, groups, discussions |
| `friends.js` | `/api/friends` | Friend requests, friend list |
| `mass-messaging.js` | `/api/messaging` | Mass/broadcast messaging |
| `notifications.js` | `/api/notifications` | Push/email/SMS notifications |
| `notification-prefs.js` | `/api/notification-prefs` | Per-type notification preferences |
Entertainment Routes
| Route File | API Path | What It Handles |
| `cam-rooms.js` | `/api/cam` | Live webcam streaming, chat, tips, private shows, auto-save |
| `music.js` | `/api/music` | Playlists, tracks, Spotify/Apple Music sync |
| `gaming.js` | `/api/gaming` | Gaming profiles, sessions, tipping |
| `gaming-subs.js` | `/api/gaming-subs` | Gaming subscription management |
| `video-calls.js` | `/api/video-calls` | Paid video call sessions |
Money & Financial Routes
| Route File | API Path | What It Handles |
| `dedup-engine.js` | `/api/financial` (integrated) | Duplicate detection across all sources |
| `categorization.js` | `/api/categorize` | Auto-categorization engine (22 rule sets) |
| `bank-import.js` | `/api/bank-import` | Bank statement CSV import |
| `bank-alternatives.js` | `/api/bank-sync` | Plaid, Yodlee, MX, Finicity, Akoya connections |
| `tax-reporting.js` | `/api/tax` | Tax reports, 1099 forms, deductions |
| `cashapp.js` | `/api/cashapp` | Cash App integration |
| `credits.js` | `/api/credits` | Credit packages, balance, spend, gift |
| `subscription-tiers.js` | `/api/tiers` | Subscription tier management |
| `pricing.js` | `/api/pricing` | Pricing bundles, rates |
| `reports.js` | `/api/reports` | Comprehensive reports |
| `earnings-widget.js` | `/api/earnings-widget` | Embeddable earnings display |
| `holiday-discounts.js` | `/api/discounts` | 13 holiday auto-discounts |
| `spending-badges.js` | `/api/badges` | Top fan badges, dual-consent visibility |
Notion & Database Routes
| Route File | API Path | What It Handles |
| `notion-live.js` | `/api/notion` | Live Notion queries, financial sync, property mapping |
| `notion-writeback.js` | (integrated) | Platform → Notion bidirectional sync |
| `notion-db-scanner.js` | (integrated) | Universal database discovery (scans 200+ DBs) |
| `connected-databases.js` | `/api/databases` | Connected database management |
| `db-api.js` | `/api/v2` | Generic PostgreSQL CRUD for any table |
Cross-Connection Routes (the glue)
| Route File | API Path | What It Handles |
| `entity-links.js` | `/api/entities` | Universal entity linking (any record ↔ any record) |
| `scene-cascade.js` | `/api/scenes` | One-call scene recording (creates 11 records across 7 tables) |
| `industry-contacts.js` | `/api/contacts` | Industry contacts, auto-populate from filmography |
| `contact-import.js` | `/api/contacts` | Apple/Google/Outlook/vCard/CSV import |
| `contact-sync.js` | `/api/contacts` | Bidirectional contact sync engine |
| `cross-connections.js` | `/api/cross-connect` | Shifts→bookings, contracts→calendar, store→income, vault→scenes, reports, profile, messages |
| `auto-post-events.js` | `/api/auto-post-events` | 12 auto-post triggers with per-user toggles |
| `calendar-sync.js` | `/api/calendar-sync` | 8-source calendar sync + ICS export/import |
| `dashboard-widgets.js` | `/api/dashboard-widgets` | 10-source dashboard summary |
| `used-items.js` | `/api/used-items` | Used/worn item lifecycle |
Safety Routes
| Route File | API Path | What It Handles |
| `safety.js` | `/api/safety` | 11 safety toggles, panic button, escalation |
| `safety-enhanced.js` | `/api/safety-v2` | Ride tracking, offline panic, travel check-ins |
| `location-proximity.js` | `/api/location` | Location sharing, proximity alerts |
| `geo-blocking.js` | `/api/geo-block` | Geographic content blocking |
Lifestyle Routes
| Route File | API Path | What It Handles |
| `wishlists.js` | `/api/wishlists` | Wishlists, items, gift tracking |
| `amazon-wishlists.js` | `/api/amazon-wishlists` | Amazon wishlist sync |
| `recipes.js` | `/api/recipes` | Recipes, food photo analysis, nutrition |
| `fitness.js` | `/api/fitness` | Workouts, body tracking, measurements |
| `bookmarks.js` | `/api/bookmarks` | Bookmark collections |
| `watchlist.js` | `/api/watchlist` | Movies/shows watchlist |
Other Routes
| Route File | API Path | What It Handles |
| `legal.js` | `/api/legal` | Legal documents, 2257 compliance |
| `gdpr.js` | `/api/gdpr` | GDPR/CCPA data requests, export, deletion |
| `dmca.js` | `/api/dmca` | DMCA takedown requests |
| `mail.js` | `/api/mail` | Email sending |
| `email-templates.js` | `/api/email-templates` | Email template management |
| `ai-tools.js` | `/api/ai` | AI-powered features (captions, analysis) |
| `forms.js` | `/api/forms` | Custom form builder |
| `ppv.js` | `/api/ppv` | Pay-per-view content |
| `polls.js` | `/api/polls` | Polls and voting |
| `referral.js` | `/api/referral` | Referral program |
| `rider.js` | `/api/rider` | Hospitality rider management |
| `watermark.js` | `/api/watermark` | Media watermarking |
| `embed-widgets.js` | `/api/embed` | Embeddable widgets for external sites |
| `discover.js` | `/api/discover` | Content/user discovery |
| `connectors.js` | `/api/connectors` | Platform connection handlers |
| `event-scraper.js` | `/api/events` | Industry event discovery |
| `content-preservation.js` | `/api/preservation` | Content import protection (never auto-deleted) |
| `fan-tags.js` | `/api/fan-tags` | Private fan CRM tagging |
| `fan-questions.js` | `/api/questions` | Fan Q&A |
| `counter-offers.js` | `/api/counter-offers` | Price negotiation |
| `funded-scenes.js` | `/api/funded-scenes` | Crowdfunded scene requests |
| `amateur-content.js` | `/api/amateur` | Amateur content features |
| `companion-services.js` | `/api/companion` | Companion booking services |
| `house-features.js` | `/api/venues`, `/api/house` | House/venue features |
| `youtuber-asmr.js` | `/api/creators` | YouTube/ASMR creator features |
| `findom.js` | `/api/findom` | Financial domination sessions/tributes |
| `fundraiser.js` | `/api/fundraiser` | Crowdfunding campaigns |
| `marketplace.js` | `/api/marketplace` | Marketplace listings |
5. Database Tables — Grouped by Feature {#5-tables}
237 tables total. Here are the key ones grouped by what they support.
Users & Auth
users (user_type: performer/studio/agent/publicist/strip_club/fan/admin), user_settings, user_verifications, user_aliases, user_blocks, user_businesses, user_credits, user_domains, user_photos, user_achievements, sessions, age_verifications, tos_acceptances
Financial
transactions (THE main money table), earnings, expenses, earning_statements, financial_accounts, bank_connections, bank_transactions, budgets, recurring_transactions, tax_reports, platform_revenue, platform_transactions, import_jobs, screenshot_imports, transaction_links
Content & Feed
posts (THE feed table), comments, post_edits, post_engagements, post_likes, post_update_alerts, posting_triggers, albums, album_items, content_calendar, content_reports, auto_post_settings, auto_post_queue, auto_post_groups, captions, caption_library
Bookings & Calendar
bookings, booking_requests, booking_preferences, booking_verifications, calendar_blocks, calendar_events, strip_clubs, strip_club_appearances
Films & Career
films, film_performers, film_performer_earnings, film_transactions, film_tag_requests, scenes, scene_contacts, award_submissions, career_timeline, contracts
Contacts
industry_contacts, contact_sync_state, addresses, emergency_contacts, client_interactions, client_relationships
Store & Commerce
products, orders, marketplace_listings, used_items, closet_items, item_requests, used_item_orders, pricing_bundles, pricing_rates, promo_codes
Messaging
conversations, messages, message_attachments, mass_messages, welcome_messages, birthday_messages
Social
social_accounts, cross_post_log, follows, friends, friend_requests, friendships
Entertainment
cam_rooms, cam_chat_messages, cam_tips, cam_private_requests, cam_viewer_sessions, cam_schedules, music_playlists, music_tracks, playlist_tracks, playlists, gaming_profiles, gaming_sessions, gaming_participants, gaming_subscriptions, game_wishlist, video_call_sessions
Safety
safety_alerts, safety_check_ins, safety_checkins, safety_incidents, safety_reports, safety_scores, ride_tracking, travel_checkpoints, travel_trips, location_shares, proximity_alerts, geo_blocks, geo_rules
Files & Media
vault_files, file_versions, file_duplicates, cloud_connections, cloud_sync_folders, media_downloads, photo_albums
Templates
templates (133 CSS templates), template_purchases, template_ratings
Notion Sync
connected_notion_databases, connected_databases, sync_history
Subscriptions & Payments
subscriptions, subscription_configs, subscription_tiers, credit_packages, credit_transactions, payment_methods, payout_requests, ppv_content, ppv_unlocks, spending_badges, spending_visibility, holiday_discounts
Other
entity_links (universal connector), custom_pages, page_blocks, custom_forms, form_submissions, notifications, notification_preferences, achievements, achievement_awards, legal_documents, records_2257, dmca_requests, referrals, reports, feedback, embed_widgets, scraped_events, polls, poll_votes, wishlists, wishlist_items, wishlist_goals, amazon_wishlists, amazon_wishlist_items, bookmarks, bookmark_collections, watchlist, recipes, fitness_workouts, body_measurements, health_logs, meal_plans, mood_entries, mileage_log, tip_menu_items, tip_songs, riders, rider_requirements, portfolios, portfolio_items, presenters, publicists, publicist_engagements, custom_categories, custom_requests, draft_campaigns, campaigns, special_accounts, donations, fundraisers, fundraiser_donations, funded_scenes, funded_scene_campaigns, funded_scene_requests, scene_funding, asmr_bookings, asmr_sessions, companion_bookings, companion_clients, companion_profiles, companion_rates, house_content_sales, house_costumes, house_shifts, house_tip_outs, house_tips, findom_sessions, findom_tributes, amateur_content, amateur_profiles, analytics_events, fan_event_schedules, fan_profiles, fan_questions, fan_tags, performer_holiday_settings, performer_ratings, platform_rules, preservation_jobs, profile_articles, public_profile_data, testing_records, team_members, vip_events, vip_event_attendees, vip_event_rsvps, blacklist, award_orders, auto_post_albums, live_photos (if exists)
6. The Connection Map — What Connects to What {#6-connections}
This is the most important section. When you modify ANY feature, check this map to see what else needs updating.
DASHBOARD connects to:
- Financial Hub → earnings this month stat
- Booking Requests → pending requests count
- Calendar → today's events + next 3 days
- Career Timeline → recent milestones
- Industry Contacts → people worked with this month
- Closet/Store → items for sale count
- Publicist → upcoming interviews
- Strip Clubs → upcoming appearances
- Safety → active ride tracking indicator
- Messages → unread count
- Notifications → unread count
FEED connects to:
- Auto-Post Events → 12 trigger types auto-create posts
- Twitter → cross-posting checkbox
- Social Mirror → imported content from other platforms
- Bookings → "Create Post" from calendar events
- Filmography → scene release auto-post
- Awards → nomination/win auto-post
- Store → new listing auto-post
- Strip Clubs → appearance auto-post
- Cam → "Going live!" auto-post
- Wishlists → gift received auto-post
- Fitness → workout completed auto-post
- Recipes → recipe share auto-post
- Music → song/playlist share auto-post
- Archive → archived posts preserve timestamps
FINANCIAL HUB connects to:
- Bookings → scene work transactions, booking tab
- Strip Clubs → appearance income + house fee expenses
- Publicist → engagement expenses
- Filmography → film-linked transactions
- Closet → purchase expenses, sale income
- Shifts → shift earnings auto-create transactions
- Store → sale income
- Notion → bidirectional sync (7 Notion DBs)
- Bank Import → CSV, Plaid, Yodlee, MX, Finicity
- Dedup Engine → prevents double-counting
- Auto-Categorize → 22 rule sets
- Recurring Detection → auto-detect subscriptions
- Tax Reports → deductible flags
- Screenshot Import → photo-to-transaction
- Templates → template sale income
BOOKINGS connects to:
- Calendar → auto-creates calendar blocks
- Financial Hub → booking creates transaction
- Career Timeline → booking acceptance milestone
- Filmography → scene work bookings appear in filmography
- Contacts → booking party added as contact
- Strip Clubs → club appearances are bookings
- Publicist → publicist engagements are bookings
- Safety → travel check-in auto-created
- Rebook System → 4 modes from any source
- Booking Preferences → 10 routing toggles
- Entity Links → connects booking to all related records
FILMOGRAPHY connects to:
- Financial Hub → film-linked transactions show earnings per scene
- Industry Contacts → costars/directors auto-populated
- Career Timeline → film awards, first scenes
- Store/Closet → scene-worn items linked
- Bookings → rebook buttons (Same Setup / New Scene)
- Vault → scene photos/videos
- Feed → scene release auto-post
- Entity Links → film ↔ transaction ↔ contact ↔ closet_item
- Awards → award-worthy flags, nominations, wins
CALENDAR connects to:
- Bookings → accepted bookings create blocks
- Strip Clubs → appearances on calendar
- Publicist → engagement dates on calendar
- Cam Sessions → scheduled streams
- Video Calls → scheduled calls
- Shifts → shift schedule
- Amazon → delivery dates
- Contracts → start/end/renewal dates
- Fitness → scheduled workouts
- Films → release dates
- Awards → ceremony dates
- iCloud → ICS export/import
- Feed → "Create Post" from any calendar event
ADDRESS BOOK connects to:
- Filmography → costars auto-populated from scene data
- Bookings → "Request Booking" button per contact
- Messages → "Message" button per contact
- Calendar → upcoming events with this contact
- Contact Sync → Apple/Google/Outlook bidirectional
- Scene Cascade → new contacts auto-created
- Strip Clubs → club booking contacts auto-added
PUBLICIST connects to:
- Financial Hub → engagement expenses auto-created
- Calendar → engagement dates auto-blocked
- Career Timeline → engagement events auto-added
- Feed → auto-post option per engagement
- Address Book → publicist as industry contact
- Bookings → publicist-booked appearances
- Contracts → publicist contracts
- Entity Links → engagement ↔ expense ↔ calendar ↔ timeline
STRIP CLUBS connects to:
- Financial Hub → income + house fee expense auto-created
- Calendar → appearance dates blocked
- Career Timeline → first appearance milestone
- Industry Contacts → club booking contact auto-added
- Safety → travel check-in auto-created
- Feed → appearance auto-post
- Bookings → appearances shown in bookings
- Contracts → appearance contracts linked
STORE connects to:
- Financial Hub → sale income auto-created
- Closet → items listed from closet lifecycle
- Feed → new listing auto-post
- Filmography → scene-worn provenance
- Stripe → payment processing
- Entity Links → product ↔ transaction ↔ closet_item
CLOSET (lifecycle) connects to:
- Wishlists → wishlisted items
- Store → purchased items
- Filmography → scene-worn tracking
- Financial Hub → purchase expense + sale income
- Feed → outfit posts
- Item Requests → fan outfit requests from scenes
SETTINGS connects to:
- Auto-Post Events → 10 toggle switches
- Booking Preferences → 9 routing toggles
- Notifications → email/push/SMS/marketing toggles
- Theme → dark/light/system
- Nav Layout → top/side/icons
- Safety → all 11 safety toggles
SAFETY connects to:
- Ride Tracking → Uber/Lyft connections
- Emergency Contacts → notification chain
- Calendar → travel check-ins tied to events
- Dashboard → active tracking indicator
- Bookings → auto-travel check-in
- Strip Clubs → auto-travel check-in
- Offline → Service Worker for panic without internet
EARNINGS connects to:
- Financial Hub → pulls ALL income transactions (source of truth)
- Bookings → completed bookings = actual income, pending = potential income
- Booking Requests → pending requests count as potential income
- Strip Clubs → appearance income (guaranteed + tips - house fees)
- Filmography → scene work earnings (Scene Work tab)
- Tips → aggregated from feed/cam/message tips
- Subscriptions → recurring subscriber payments
- Store → product sale income
- PPV → pay-per-view unlocks
- Custom Requests → paid custom content
- Gaming → credit purchases from fans
- Templates → original template sales
- Payments → payout settings and methods
- Reports → annual report data
- Connections → platform earnings imports
CONNECTIONS connects to:
- ALL pages → every platform connection feeds data somewhere
- Setup Guide → walkthroughs for each connection
- Financial Hub → bank/platform connections
- Social → platform notification sync
- Calendar → iCloud, Amazon
- Contacts → Apple/Google/Outlook sync
- Music → Spotify/Apple Music
- Gaming → Xbox
7. The 7 Layers of a Feature {#7-layers}
Every complete feature has up to 7 layers. When you ask for a new feature or a change, ALL relevant layers must be updated. Here's what they are:
Layer 1: DATABASE TABLE
What: The PostgreSQL table(s) that store the data.
File: Column additions in route files or schema.sql
Example: strip_clubs table stores club name, city, state, house_fee, rating
Layer 2: API ROUTE
What: The backend code that creates/reads/updates/deletes data.
File: /routes/feature-name.js
Example: POST /api/booking-system/strip-clubs creates a new club
Layer 3: HTML PAGE
What: The visual interface the user interacts with.
File: /public/app/feature-name.html
Example: publicist.html with 6 tabs, modals, forms
Layer 4: CROSS-CONNECTIONS
What: Auto-created records in OTHER features when this feature is used.
File: Within the route file OR in cross-connections.js
Example: Creating a strip club appearance auto-creates:
- Income transaction in Financial Hub
- House fee expense in Financial Hub
- Calendar block
- Industry contact (booking contact)
- Career timeline milestone (if first appearance)
- Travel check-in (safety)
- Feed post (if auto-post toggle is on)
Layer 5: UI BUTTONS & LINKS
What: Buttons/links on OTHER pages that reference this feature.
File: Other HTML files that need buttons added
Example: "Rebook" buttons on Filmography and Financial Hub pages
Layer 6: SETUP GUIDE
What: Documentation in the interactive setup guide.
File: /public/app/setup-guide.html
Example: Strip Clubs section explains how to add clubs, log appearances, what gets auto-created
Layer 7: SETTINGS & TOGGLES
What: User-configurable options for this feature.
File: settings.html + route's preferences endpoint
Example: Auto-post toggle for strip_club_appearance in Settings → Auto-Post Settings
Quick Reference: Which Layers Does Each Change Need?
| Change Type | Layers Needed |
| Add a brand new feature | ALL 7 |
| Add a new field to existing feature | 1 (DB) + 2 (API) + 3 (HTML) |
| Connect two existing features | 4 (cross-connection) + 5 (buttons) + 6 (guide) |
| Add auto-post for something | 4 (trigger) + 7 (toggle in settings) + 6 (guide) |
| Change how something looks | 3 (HTML/CSS only) |
| Fix broken data | 2 (API route logic) |
| Add a new page | 3 (HTML) + `nav.js` (add to nav) + 2 (API if needed) |
8. How to Ask for Changes — Prompt Templates {#8-prompts}
Use these exact prompts when asking for modifications. They ensure nothing gets missed.
Adding a Brand New Feature
Add [FEATURE NAME] to the platform. This should include:
- Database table with [describe fields]
- API endpoints for CRUD
- HTML page with [describe layout/tabs]
- Cross-connections to [list related features]
- Auto-post trigger (if applicable)
- Setup guide section
- Settings toggles (if applicable)
- Add to nav under [CATEGORY]
Build ALL 7 layers.
Example:
Add a Podcast feature to the platform. This should include:
- Database table with episode title, description, audio_url, duration, guest_name, publish_date
- API endpoints for CRUD
- HTML page with episodes list, upload form, player
- Cross-connections to: Feed (auto-post new episode), Calendar (scheduled releases), Financial Hub (sponsorship income), Contacts (guests as contacts)
- Auto-post trigger for new episode published
- Setup guide section
- Settings toggle for auto-post
- Add to nav under ENTERTAINMENT
Build ALL 7 layers.
Adding a New Field to an Existing Feature
Add [FIELD NAME] to [FEATURE]. Update:
- Database column on [TABLE]
- API to accept/return the new field
- HTML form/display to show it
- Any cross-connections that should use this field
Example:
Add a "mood" field to Bookings. Update:
- Database column on bookings table (mood VARCHAR)
- API to accept/return mood in booking creation/listing
- HTML booking card to show mood tag
- Calendar event title should include mood
Connecting Two Existing Features
Connect [FEATURE A] to [FEATURE B]:
- When [ACTION] happens on Feature A, auto-create [WHAT] on Feature B
- Add [BUTTON/LINK] on Feature A's page linking to Feature B
- Add [BUTTON/LINK] on Feature B's page linking back to Feature A
- Update setup guide with the new connection
- Update CONNECTION-AUDIT.md
Example:
Connect Recipes to Financial Hub:
- When a recipe ingredient list is saved, auto-create a grocery expense estimate in Financial Hub
- Add "View Expenses" link on recipe cards
- Add recipe tag on grocery expenses in Financial Hub
- Update setup guide
- Update CONNECTION-AUDIT.md
Modifying an Existing Feature
Change [WHAT] on [FEATURE]:
- [Describe the change]
- Check all cross-connections (see Operations Manual section 6)
- Update any pages that display this data
- Update setup guide if behavior changed
Adding Auto-Post for Something
Add auto-post trigger for [EVENT TYPE]:
- Add trigger in auto-post-events.js
- Add toggle in auto_post_settings table
- Add toggle switch in Settings page
- Add to setup guide Auto-Post section
- Test with: POST /api/auto-post-events/trigger { type: "[type]", data: {...} }
Adding a Platform Connection
Add [PLATFORM] connection:
- Add connection card to connections.html with setup steps
- Add to connections.html walkthrough section
- Add to setup-guide.html connections section
- Create API handler if needed
- Add "usedFor" description
- Add connection type (Full OAuth / Limited OAuth / Import Only / etc.)
- Connect data flow to relevant pages
UI-Only Change (Visual Only, No Data)
Change the [VISUAL ELEMENT] on [PAGE]:
- This is UI-only, no backend changes needed
- Update [specific HTML file]
- Make sure dark mode / monochrome / theme still works
- No cross-connections affected
The "Do Everything" Prompt (when unsure)
Add/change [DESCRIPTION]. Apply to ALL layers:
1. Database changes needed?
2. API route changes needed?
3. HTML page changes needed?
4. Cross-connections to other features?
5. Buttons/links on other pages?
6. Setup guide update?
7. Settings/toggles?
Check the Connection Map in the Operations Manual for all related features.
9. What Happens When You Add a Feature — Complete Checklist {#9-checklist}
Use this checklist every time a feature is added or modified:
Pre-Build
- [ ] Identify which of the 7 layers are needed
- [ ] Check Connection Map (section 6) for related features
- [ ] Check if similar feature already exists (avoid duplicates)
Build
- [ ] Database: table/columns created
- [ ] Route: API endpoints working (test with curl)
- [ ] HTML: page created/updated, loads data correctly
- [ ] CSS: respects dark mode, monochrome, theme colors, no emojis
- [ ] No hardcoded colors (use CSS variables)
- [ ] Buttons have sharp corners (border-radius: 0)
- [ ] All action buttons use var(--text)/var(--bg)
Connect
- [ ] Cross-connections: auto-create records in related features
- [ ] Entity links: connect to universal entity_links table where needed
- [ ] Buttons/links: add to other pages that reference this feature
- [ ] Calendar: does this have dates that belong on the calendar?
- [ ] Financial Hub: does this involve money? Auto-create transaction?
- [ ] Feed: should this auto-post? Add trigger + toggle
- [ ] Contacts: does this involve people? Add/link industry contacts
- [ ] Career Timeline: is this a milestone? Add timeline event
Document
- [ ] Setup guide: add section explaining the feature
- [ ] CONNECTION-AUDIT.md: update connection status
- [ ] This manual: add to relevant sections if it's a major feature
Test
- [ ] API returns 200
- [ ] Page loads without errors
- [ ] Data displays correctly
- [ ] Cross-connections fire correctly
- [ ] Dark mode looks right
- [ ] Monochrome mode has no color splashes
Deploy
- [ ]
pm2 restart platform
- [ ] Verify route count (should be previous count + new routes)
- [ ] Verify 0 failed routes
- [ ] Git commit with descriptive message
10. File Map — Where Everything Lives {#10-files}
/home/work/.openclaw/workspace/platform-server/
├── server.js ← Main entry point
├── package.json ← Dependencies
├── .env ← Environment variables (DB password, API keys)
│
├── routes/ ← ALL backend logic (137 files)
│ ├── _register.js ← Imports & mounts all routes
│ ├── financial-hub.js ← Financial Hub endpoints
│ ├── booking-requests.js ← Booking system (537+ lines, most complex route)
│ ├── scene-cascade.js ← Scene recording cascade
│ ├── entity-links.js ← Universal entity linking
│ ├── cross-connections.js ← Cross-page connections
│ ├── auto-post-events.js ← Auto-post triggers
│ ├── calendar-sync.js ← Calendar sync engine
│ ├── dashboard-widgets.js ← Dashboard widgets
│ ├── notion-live.js ← Notion sync + queries
│ ├── notion-writeback.js ← Platform → Notion sync
│ ├── dedup-engine.js ← Duplicate detection
│ └── ... (124 more route files)
│
├── middleware/ ← Runs before routes
│ ├── security.js ← Auth & access control
│ ├── csv-parser.js ← CSV upload parsing
│ ├── mailer.js ← Email sending
│ ├── notion-client.js ← Notion API client
│ └── validate.js ← Input validation
│
├── db/ ← Database layer
│ ├── client.js ← PostgreSQL connection
│ ├── data-layer.js ← Dual-write (PG + Notion)
│ ├── models.js ← Data models
│ ├── defaults.js ← Default values
│ ├── notion-dbs.js ← Notion database IDs
│ └── schema.sql ← Table definitions
│
├── public/app/ ← ALL frontend files
│ ├── dashboard.html ← Dashboard page
│ ├── financial.html ← Financial Hub page
│ ├── ... (62 more HTML files)
│ │
│ ├── css/
│ │ ├── platform.css ← Main styles + monochrome vars
│ │ ├── themes.css ← Dark/light theme variables
│ │ ├── editorial-base.css ← Default template base
│ │ ├── color-customizer.css ← Color wheel styles
│ │ └── templates/ ← 135 template CSS files
│ │
│ └── js/
│ ├── nav.js ← Navigation (CRITICAL — all pages load this)
│ ├── api.js ← API helper functions
│ ├── themes.js ← Theme switching
│ ├── editorial-theme.js ← Default template JS
│ ├── color-customizer.js ← Color wheel functionality
│ ├── accessibility.js ← Screen reader, voice, keyboard
│ ├── page-editor.js ← Drag-and-drop layout
│ ├── template-engine.js ← Template switching
│ ├── safety-sw.js ← Offline panic Service Worker
│ ├── share-button.js ← Share functionality
│ ├── quick-add.js ← Quick add shortcuts
│ └── auth-guard.js ← Login requirement
│
├── PLATFORM-OPERATIONS-MANUAL.md ← THIS FILE
│
└── core-files/ ← Project documentation
├── CONNECTION-AUDIT.md ← All connections status
├── MASTER-TASK-LIST.md ← Task tracking
├── E2E-TESTING-LOG.md ← Test results
└── CONSOLIDATED-FEATURE-MAP.md ← Feature inventory
Key Environment Variables (.env)
| Variable | What It Is |
| `PG_PASSWORD` | Database password |
| `PG_DATABASE` | Database name (`platform`) |
| `PG_USER` | Database user (`platformuser`) |
| `NOTION_TOKEN` | Notion API token |
| `TWITTER_*` | Twitter API credentials |
| `STRIPE_PUBLISHABLE_KEY` | Stripe publishable key (`pk_live_...`) — used by frontend for checkout |
| `STRIPE_SECRET_KEY` | Stripe restricted key (`rk_live_...`) — used by server for API calls |
| `STRIPE_CLIENT_ID` | Stripe Connect OAuth client ID (`ca_...`) — needed only for Standard OAuth path |
| `STRIPE_REDIRECT_URI` | OAuth callback URL for Standard connect |
Stripe Connect Setup Status
Stripe Connect requires completing these steps in the [Stripe Dashboard](https://dashboard.stripe.com/settings/connect) before live payments work:
"Tell us about your platform" — 6 screens in order:
1. Funds flow → "Buyers will purchase from you" (platform collects, pays out to sellers)
2. How sellers get paid → "Sellers will be paid out individually" (one buyer, one seller)
3. Industry → "On-demand services" (closest to creator/service marketplace)
4. Account creation → "Onboarding hosted by Stripe" (Express — performers redirected to Stripe form)
5. Account management → "Express Dashboard" (Stripe-hosted payout dashboard for performers)
6. Summary → Review and confirm
Then complete remaining items:
- Verify an identity document (REQUIRED) — Government photo ID + selfie (KYC requirement)
- Confirm final details (REQUIRED) — Business details, bank account for platform fees, accept TOS
- Access integration guide / Try out integration — SKIP (already handled by platform code)
Fee Model D: Customer pays product price + Stripe fee (2.9% + $0.30). Performer pays only 15% platform fee. Stripe fee never touches performer money.
All payment endpoints (payments.js) use real Stripe API calls when a valid key is configured, with automatic simulation fallback. Every API response includes live: true/false so the frontend knows which mode is active.
Commands You Need to Know
| Command | What It Does |
| `pm2 restart platform` | Restart the server (do this after code changes) |
| `pm2 logs platform` | View server logs |
| `pm2 status` | Check if server is running |
| `curl -sk https://indulgon.com/api/[endpoint]` | Test an API endpoint |
Appendix A: The Auto-Post Trigger Types
| Trigger | What Creates It | Toggle Key |
| Scene Released | Film added/published | `scene_released` |
| Award Nominated | Award submission created | `award_nominated` |
| Award Won | Award submission status → won | `award_won` |
| New Store Listing | Product listed | `new_store_listing` |
| Club Appearance | Strip club appearance logged | `strip_club_appearance` |
| Booking Confirmed | Booking request accepted | `booking_confirmed` |
| Milestone Reached | Career timeline event created | `milestone_reached` |
| Going Live | Cam room started | `going_live` |
| Wishlist Gift | Wishlist item purchased by fan | `wishlist_gift_received` |
| Workout Completed | Fitness workout logged | `workout_completed` |
| Recipe Shared | Recipe created/shared | `recipe_shared` |
| Music Shared | Song/playlist shared | `music_shared` |
All toggles live in auto_post_settings table and are configurable in Settings page.
Appendix B: The Scene Cascade — What 1 API Call Creates
POST /api/scenes/record with scene data creates:
1. Transaction (income) in transactions
2. Film in films
3. Film-transaction link in film_transactions
4. Calendar block in calendar_blocks
5. Career timeline event in career_timeline
6. Industry contacts for each costar/director in industry_contacts
7. Scene-contact links in scene_contacts
8. Closet items for wardrobe in closet_items
9. Entity links connecting everything in entity_links
10. Booking if from a booking request
11. Feed post if auto-post is enabled
All operations are idempotent — running twice with the same data won't create duplicates.
Appendix C: The Booking Request Flow
Sender → POST /api/booking-system/requests
│
▼
Routing Engine (checks booking_preferences)
│
├─ agent_receives_requests=true → notify agent
├─ i_receive_requests=true → notify performer
├─ auto_accept_if_open=true + calendar open → auto-accept
│
▼
Recipient sees in Bookings → Requests tab
│
├─ Accept → acceptBooking() runs:
│ ├─ Calendar block created
│ ├─ Booking record created
│ ├─ Career timeline event
│ ├─ Auto-post (if toggle on)
│ └─ Notification to sender
│
├─ Decline → notification to sender
├─ Reschedule → counter-date sent back
└─ Counter → counter-rate/terms sent back
Appendix D: User Types & What They Can Do
| User Type | Can Send Bookings | Can Accept Bookings | Has Filmography | Has Store | Has Cam |
| Performer | Yes | Yes | Yes | Yes | Yes |
| Studio | Yes | Yes | No | No | No |
| Agent | Yes | Yes (on behalf) | No | No | No |
| Publicist | Yes | No | No | No | No |
| Strip Club | Yes | Yes | No | No | No |
| Fan | Yes | No | No | No | No |
| Admin | Yes | Yes | Yes | Yes | Yes |
All user types share the SAME booking features, preferences, and calendar.
> Last Updated: 2026-04-29 04:35 EDT
> Route Count: 142/142 loaded, 0 failed
> Table Count: 237
> Page Count: 64
> Connection Status: 280+ connections, 0 missing
Automatic Filmography Import (IAFD Integration)
Overview
Indulgon automatically imports performer filmographies from the Internet Adult Film Database (IAFD). This is a competitive advantage -- no other platform offers automatic filmography import.
Technical Architecture
HTTP Scraper (Primary — `/api/tags/iafd-import`)
1. Search phase: Makes two HTTP requests to IAFD's search endpoint:
- Comprehensive search: iafd.com/results.asp?searchtype=comprehensive&searchstring=[name] (returns top 50 scenes + performer profile data)
- Title search: iafd.com/results.asp?searchtype=title&searchstring=[name] (returns up to ~120 additional scene matches)
- Both requests use standard HTTP with User-Agent: Mozilla/5.0 (compatible; IndulgonBot/1.0)
- IAFD's search results pages are NOT behind Cloudflare (no bot challenge)
2. Data extracted from search results (no Cloudflare issue):
- Performer profile URL (direct link)
- Exact name match verification
- All known aliases (e.g., "Anna Lynn, Annalynn Grace, Jillian Brookes")
- Active years (e.g., "2013-2025")
- Total scene count (e.g., 787)
- Scene list: title, IAFD ID, year, studio/distributor, IAFD URL
3. Import phase: For each scene found:
- Dedup check: SELECT FROM films WHERE external_id = [iafd_id] OR (LOWER(title) = LOWER([title]) AND year = [year])
- If new: INSERT into films table with source = 'iafd'
- INSERT into film_performers linking the requesting user
- If import_as_transactions = true: INSERT into transactions with source = 'iafd_import', amount = 0, category = 'Scene Work'
4. Limitations of HTTP scraper:
- Search results show top 50 (comprehensive) + ~120 (title) = ~134 unique scenes max
- Full filmography (e.g., 787 scenes) is only on the profile page, which has Cloudflare
- No social media handles from search results (those are on the profile page)
Browser Scraper (Cloudflare Bypass — `/api/iafd/scrape-profile`)
1. Purpose: Accesses IAFD profile pages that are behind Cloudflare bot protection
2. Method: Uses the Chromium browser running on the VM via Chrome DevTools Protocol (CDP)
- Connects to ws://127.0.0.1:9222 (Chromium's CDP WebSocket)
- Navigates to the IAFD profile URL in the real browser
- Waits 8-10 seconds for Cloudflare challenge to auto-solve
- Extracts rendered HTML via Runtime.evaluate
3. Data extracted from profile page (requires browser):
- Full biographical data: birthday, birthplace, ethnicity, measurements
- Social handles: Twitter/X, Instagram, OnlyFans, personal website
- Complete alias list
- Active years and scene count
4. Bulk scraper (POST /api/iafd/bulk-scrape):
- Iterates through placeholder accounts that have IAFD URLs but missing social handles
- Rate-limited: 3-second delay between requests
- Updates placeholder_accounts with discovered handles
5. Browser requirements:
- systemctl --user start openclaw-browser must be running
- Chromium CDP available at port 9222
- Node.js built-in WebSocket (Node 22+) for CDP communication
Database Tables Involved
| Table | Role |
| `films` | Stores imported scenes. `source = 'iafd'`, `external_id = iafd_uuid` |
| `film_performers` | Links performer to each film. `billing_order`, `is_platform_user` |
| `transactions` | Scene Work income entries. `source = 'iafd_import'`, `amount = 0` |
| `placeholder_accounts` | Stores IAFD data for performers not on Indulgon |
| `performer_tags` | Links taggers to tagged performers with context |
| `entity_links` | Links films to closet items (`source_type = 'film'`, `target_type = 'closet_item'`) |
API Endpoints
| Endpoint | Method | Purpose |
| `/api/tags/iafd-import` | POST | Import filmography via HTTP scraper |
| `/api/tags/scene-closet/:filmId` | POST | Link closet items to a film |
| `/api/tags/lookup/:name` | GET | Manual IAFD lookup (search only) |
| `/api/iafd/scrape-profile` | POST | Browser-based profile scrape (Cloudflare bypass) |
| `/api/iafd/bulk-scrape` | POST | Batch scrape all placeholders |
Security & Legal Notes
> ADMIN USE ONLY — This section describes proprietary scraping methods that are a key competitive advantage. If a competitor learns how we bypass Cloudflare to access IAFD profile data, they can replicate the feature. If IAFD learns the specific technique, they can block it. Never discuss these methods outside this document.
- User-facing messaging: Always say "Indulgon imports from industry databases." NEVER mention: scraping, Cloudflare bypass, CDP, Chrome DevTools Protocol, headless browser, WebSocket, bot protection, or any technical method. This applies to marketing, support responses, FAQ, partner communications, investor decks, and press.
- If asked by users how it works: "We aggregate publicly available career data from industry databases to build your filmography automatically." That is the only answer.
- If asked by developers/contractors: They get API endpoint documentation only. They do not need to know about the IAFD scraper internals. The scraper routes are self-contained and do not need modification for normal platform development.
- IAFD Terms: Data is publicly accessible. We access it the same way a human browser would. This is legally defensible but drawing attention to it invites countermeasures.
- Rate limiting: Browser scraper has 3-second delays between requests. HTTP scraper makes max 2 requests per import. Do not increase these rates — staying under the radar is more important than speed.
- No caching of full HTML: Only extracted structured data is stored. Raw HTML is discarded immediately after parsing.
- If IAFD blocks us: The HTTP scraper (search results) will likely continue working even if profile pages get harder to access. The search results page has never had Cloudflare protection. If both are blocked, we fall back to cached data already imported.
- Competitor risk: As of April 2026, no other adult industry platform offers automatic filmography import. This is a significant first-mover advantage. Protect it.
Performer Tagging System
Overview
Performers can tag other performers in any context (filmography, feed, financial, bookings, content calendar). If the tagged person is not on Indulgon, a placeholder account is created and they receive an invitation.
Tag Creation Flow
1. Tagger enters a name (e.g., "Johnny Castle")
2. System searches users table by display_name or username (case-insensitive)
3. If found: Creates performer_tags entry with tagged_user_id pointing to real user
4. If NOT found:
a. Searches placeholder_accounts by display_name or stage_name
b. If existing placeholder: increment invitation_count
c. If no placeholder: CREATE new one with name, invited_by, metadata
d. Creates performer_tags entry with tagged_placeholder_id
e. IAFD lookup runs automatically to enrich the placeholder
Claim Flow (When Tagged Person Joins)
1. New user hits POST /api/tags/placeholder/:id/claim
2. System updates placeholder_accounts: status = 'claimed', claimed_by = user_id
3. All performer_tags with tagged_placeholder_id are updated: tagged_user_id = new_user_id, tagged_placeholder_id = NULL
4. All film_performers with placeholder_id are updated: user_id = new_user_id, placeholder_id = NULL
5. All bookings with coworker_placeholder_id updated
6. All content_calendar with collaborator_placeholder_id updated
7. Notification sent to every tagger: "[Name] just joined Indulgon!"
8. Response includes full attribution: which contexts transferred, who tagged what
Attribution (Who Added What)
GET /api/tags/profile/:userId returns two groups:
- tagged_by_others: Items where other performers tagged this user
- tagged_by_self: Items where this user tagged others
- Each tag has
context_type (filmography, financial, feed_post, booking, content_calendar)
- UI shows "Tagged by [Tagger Name]" vs. items the user added themselves
Connected Systems
| System | Field | Creates Placeholder? |
| Filmography (scene creation) | `coworkers` array | Yes |
| Feed (post creation) | `tagged_performers` array | Yes |
| Financial Hub (transaction) | `coworkers` array | Yes |
| Bookings (booking creation) | `coworkers` array | Yes |
| Content Calendar (event creation) | `collaborators` array | Yes |
| Scene Cascade | via `tagPerformerInScene()` helper | Yes |
Database Tables
| Table | Key Columns |
| `performer_tags` | `tagger_user_id`, `tagged_user_id`, `tagged_placeholder_id`, `context_type`, `context_id`, `context_title`, `role`, `status` |
| `placeholder_accounts` | `display_name`, `stage_name`, `twitter_handle`, `instagram_handle`, `invited_by`, `invitation_count`, `claimed_by`, `status`, `metadata` |
| `film_performers` | `film_id`, `user_id`, `placeholder_id`, `performer_name`, `role`, `billing_order` |
| `notifications` | `user_id`, `type`, `title`, `message`, `reference_id`, `reference_type`, `is_read` |
Scene-to-Closet Connection
How It Works
1. Every film entry (whether from IAFD import, manual entry, or CSV) has a closet_item_ids JSON array
2. POST /api/tags/scene-closet/:filmId with { closet_item_ids: ['uuid1', 'uuid2'] } links items
3. Entity links are created: entity_links row with source_type = 'film', target_type = 'closet_item'
4. Film is marked has_closet_items = true
5. Store listings for linked items show scene provenance: "As worn in [Title] ([Studio], [Year])"
Resale Value Impact
- Items with scene provenance typically sell for 2-5x more than unlinked items
- Multiple-scene items ("worn in 3 scenes") are even more valuable
- Scene photos can be attached to both the film entry and the store listing
Credit System Architecture (Option C)
Overview
Credits are the platform's internal currency. 1 credit = $1 display value. Customers buy credit packs to spend on the platform. All money flows through Indulgon's Stripe account first.
Money Flow
1. Customer buys $100 credit pack (gets 120 credits with bonus) → $100 goes to Indulgon's Stripe
2. Customer spends credits on performers → system logs the transaction instantly
3. Performer sees "Earned X credits" on their dashboard
4. At payout time: Indulgon transfers performer's share from its Stripe to performer's bank/debit
Option C: Payout Based on Actual Dollars Paid
- A $100 pack gives 120 credits, so each credit = $0.833 real dollars
- When 120 credits are spent on a performer: dollar_value = 120 × ($100/120) = $100
- Performer gets: $100 × 85% = $85
- Platform keeps: $100 × 15% = $15
- The bonus credits are a customer incentive — they do NOT create a deficit
Promotional Credits
- Admin can grant promotional credits via
POST /api/credits/admin/grant
- Promo credits have $0 real dollar value
- When spent on performers, the payout comes from platform revenue (Jillian's pocket)
- Tracked separately:
user_credits.promotional_balance vs purchased_balance
- Promo credits are spent FIRST before purchased credits
Credit Packs
| Pack | Price | Credits | Bonus | Effective Rate |
| Starter | $10 | 10 | 0% | $1.00/credit |
| Standard | $50 | 55 | 10% | $0.909/credit |
| Premium | $100 | 120 | 20% | $0.833/credit |
| Elite | $500 | 650 | 30% | $0.769/credit |
Performer Payout Methods (at launch)
| Method | Status | How |
| Bank Transfer (ACH) | Available | Stripe sends directly to performer's bank |
| Debit Card | Available | Stripe Instant Payouts to Visa/Mastercard |
| PayPal | Post-launch | Requires PayPal Business account on platform |
| Venmo | Post-launch | Same as PayPal (Venmo is owned by PayPal) |
| CashApp | Post-launch | No API — performer provides bank info instead |
| Crypto (USDC) | Post-launch | Requires Circle or Coinbase integration |
Performers Do NOT Need Stripe
- Performers fill out a form on the Payments page (name, DOB, SSN last 4, address, bank/debit)
- This creates a Stripe Connect Express account behind the scenes
- They never see Stripe, never log into Stripe, never create a Stripe account
- Optionally, they CAN connect an existing Stripe account for self-service dashboard access
Admin Endpoints
| Endpoint | Purpose |
| `GET /api/payments/admin/funds-overview` | YOUR money vs PERFORMER money separation |
| `GET /api/credits/admin/credit-overview` | Total credits outstanding (purchased vs promotional) |
| `POST /api/credits/admin/grant` | Grant promotional credits (with out-of-pocket warning) |
Custom Pricing (Performer-Controlled)
| Setting | Default | Where |
| Text message rate | 1 credit | Settings > Pricing |
| Photo message rate | 3 credits | Settings > Pricing |
| Video message rate | 5 credits | Settings > Pricing |
| Video call rate/min | 5 credits | Settings > Pricing |
| Subscription tiers | Performer sets | Payments page |
| PPV prices | Performer sets | Feed / Post creation |
| Store prices | Performer sets | Store |
| Custom order prices | Performer sets | Custom Requests |
Indulgon always takes 15% regardless of what the performer charges.
Multi-Role System
Overview
Users can have multiple roles simultaneously. Stored as TEXT[] roles on the users table.
Valid Roles
fan, performer, creator, studio, agent, escort, publicist, house_girl, companion, amateur
API Endpoints
| Endpoint | Method | Purpose |
| `/api/settings/roles` | GET | Get current roles |
| `/api/settings/roles` | PUT | Set roles array `{ "roles": ["performer", "studio", "agent"] }` |
Registration
POST /api/auth/register accepts roles: ["performer", "studio"] array. Primary role = first in array. Falls back to single role field for backward compatibility.
Dashboard Behavior
- Primary role (first in array) determines default dashboard layout
- All features for all selected roles are accessible
- No data is lost when roles change
Cloud Storage — Bidirectional Sync and Cross-Service Transfers
Overview
Cloud files route supports 7 cloud services with full bidirectional sync and cross-service file transfers.
Supported Services
iCloud, Google Drive, Dropbox, OneDrive, Mega, Box, Amazon S3
Sync Direction
Default: bidirectional. Set per-connection in cloud_connections.sync_direction.
Cross-Service Move
POST /api/cloud/move — transfers files between cloud services through the platform. File is downloaded from source, uploaded to destination. User never downloads to their device.
Deduplication
SHA256 hash comparison. Duplicates detected on sync and removed automatically.
Deletion Policy
Files deleted on Indulgon go to trash (recoverable). Original files on cloud services are NEVER deleted by Indulgon.
AI Assistant System
Architecture
- Backend:
routes/ai-assistant.js - Intent detection + action handlers + knowledge base
- Integrations:
routes/ai-integrations.js - Calendar, email, push, docs, reviews scaffolding
- Frontend:
ai-assistant.html - Full-page chat + sidebar + Genspark promo
- Widget:
js/ai-widget.js - Floating chat bubble on all 68 dashboard pages
- API:
/api/ai/chat (POST), /api/ai/history (GET/DELETE), /api/ai/memory (GET/DELETE)
- Integration API:
/api/ai-integrations/calendar, /email, /push, /docs, /reviews
Database Tables (9 new)
ai_chat_history - User chat logs
ai_user_memory - Per-user persistent memory (key/value)
calendar_events - Synced calendar events
calendar_sync_config - Google/Apple Calendar OAuth tokens
email_integration - Gmail/Outlook OAuth tokens
email_summaries - AI-categorized email summaries
push_notification_config - Per-user push settings
push_queue - Queued push notifications
ai_generated_docs - Slideshow/document generation records
performance_reviews - Auto-generated reviews
blocked_dates - Schedule blocked dates
Intent Detection (14 intents)
1. Profile update 2. Memory save/recall 3. Earnings queries
4. Metrics queries 5. Message summaries 6. Booking queries
7. Content drafting 8. Schedule management 9. Performance reviews
10. Morning briefings 11. Document generation 12. Calendar
13. Email integration 14. Knowledge base (13 static topics)
Genspark Integration
- Invite link:
PLACEHOLDER_GENSPARK_INVITE_LINK in ai-assistant.html
- Affiliate link:
PLACEHOLDER_GENSPARK_AFFILIATE_LINK in ai-assistant.html
- Replace when Jillian provides actual links from Impact dashboard
Fan Request Aggregation (routes/fan-requests.js)
- API: GET
/api/fan-requests (aggregated), GET /api/fan-requests/counts (quick counts)
- POST
/api/fan-requests (create), PUT /api/fan-requests/:id (accept/decline)
- DB:
fan_requests table with source tracking
- Pulls from 7 sources: direct requests, paid messages, video calls (cam_sessions), custom_orders, store orders, tips (unfulfilled), new subscribers (unwelcomed)
- "What needs my attention?" combines: professional bookings + fan requests + unread messages + today's schedule
- Morning briefing includes fan request breakdown by type
Post-Launch Activation Checklist
- [ ] Google Calendar: GOOGLE_CALENDAR_CLIENT_ID + SECRET in .env
- [ ] Apple Calendar: APPLE_CALDAV_URL in .env
- [ ] Gmail: GOOGLE_EMAIL_CLIENT_ID + SECRET (gmail.readonly, gmail.send scopes)
- [ ] Outlook: OUTLOOK_CLIENT_ID + SECRET (Mail.Read, Mail.Send scopes)
- [ ] Web Push: VAPID_PUBLIC_KEY + VAPID_PRIVATE_KEY
- [ ] Genspark API key for document generation
- [ ] Replace placeholder links in ai-assistant.html
News (routes/news.js)
- API: GET/POST
/api/news, GET/PUT /api/news/moratorium, POST /api/news/:id/publish
- DB:
news_articles, moratorium_status
- 5 tabs: Feed, Safety Alerts, Platform Updates, Press Releases, Submit News
- Moratorium tracker: green/red banner, PASS/APAC source
- Anonymous submissions verified before publishing
Politics (routes/politics.js)
- API: GET/POST
/api/politics, POST /api/politics/:id/react, GET/POST /api/politics/:id/comments
- DB:
political_posts, political_reactions, political_comments
- 5 tabs: Feed, Industry, World, Advocacy, Write
- Anonymous: shows role not name, identity never revealed even to admins
- Reactions: Agree, Discuss, Share (not likes)
- Show-on-profile toggle per post
News vs Politics Rule
- News = facts/events ("this happened") — moratorium declared = News
- Politics = opinions/debate ("this is what I think") — "moratorium policy is flawed" = Politics
Signup and Session System
Split Signup Flow
login.html > "Sign Up" > onboarding.html (chooser) > signup-performer.html OR signup-fan.html
- Performer page: 7 incentives, fee comparison, 9-role multi-selector
- Fan page: 6 benefits, credit pack pricing, social login
- Onboarding: account safety policy displayed prominently
Session Persistence
- Duration: 90 days (set in
db/models.js)
- Token in localStorage persists across browser restarts
- Server restarts do not invalidate sessions
- Logout:
doLogout() in nav.js, calls POST /api/auth/logout
Account Safety Policy
- No bans for: mentioning competitors, adult content, linking other platforms
- Removal ONLY for: harassment, cyberbullying, threats, non-consensual content, rape/incest (step-family accepted), illegal activity
News and Politics Pages
News (routes/news.js)
- API: GET/POST
/api/news, GET/PUT /api/news/moratorium, POST /api/news/:id/publish
- DB:
news_articles, moratorium_status
- 5 tabs: Feed, Safety Alerts, Platform Updates, Press Releases, Submit News
- Moratorium tracker: green/red banner, PASS/APAC source
- Anonymous submissions verified before publishing
Politics (routes/politics.js)
- API: GET/POST
/api/politics, POST /api/politics/:id/react, GET/POST /api/politics/:id/comments
- DB:
political_posts, political_reactions, political_comments
- 5 tabs: Feed, Industry, World, Advocacy, Write
- Anonymous: shows role not name, identity never revealed even to admins
- Reactions: Agree, Discuss, Share (not likes)
- Show-on-profile toggle per post
News vs Politics Rule
- News = facts/events ("this happened") — moratorium declared = News
- Politics = opinions/debate ("this is what I think") — "moratorium policy is flawed" = Politics
Universal Role System
Architecture
- Roles stored as TEXT[] array in
users.roles column
- Primary role = first element, determines default dashboard layout
- All features accessible regardless of role selection
- Multi-role: users can hold any combination simultaneously
Role List (20 total)
| Role ID | Display Name | Target Audience | Key Platforms |
| performer | Performer | Adult industry performers | OnlyFans, SextPanther, Chaturbate, Fansly, ManyVids |
| creator | Content Creator | General content creators | YouTube, TikTok, Instagram, Patreon |
| studio | Studio | Production studios | Multi-performer management |
| agent | Agent / Manager | Talent managers | Booking management, commission splits |
| companion | Companion | Companion services | Client management, rate cards |
| escort | Escort | Escort services | Booking, safety, client screening |
| publicist | Publicist | PR/media | Press contacts, media kits |
| house_girl | House Girl | Club/venue performers | Shift scheduling, tip tracking |
| amateur | Amateur / New | Industry newcomers | Guided onboarding |
| musician | Musician / DJ | Musicians, DJs, producers | Spotify, Apple Music, SoundCloud, Bandcamp |
| athlete | Athlete | Athletes, fitness | Strava, Nike Run Club, Garmin, Cameo |
| streamer | Streamer | Live streamers | Twitch, YouTube Live, Kick, StreamElements |
| influencer | Influencer | Social media influencers | Instagram, TikTok, YouTube, Twitter/X |
| podcaster | Podcaster | Podcast hosts | Spotify for Podcasters, Apple Podcasts, Podbean |
| model | Model | Fashion/commercial models | Model Mayhem, Casting Networks, agencies |
| artist | Artist | Visual artists, photographers | Etsy, DeviantArt, ArtStation, Redbubble |
| writer | Writer / Author | Authors, bloggers, journalists | Substack, Medium, Amazon KDP, Wattpad |
| chef | Chef / Food Creator | Chefs, food content creators | YouTube, AllRecipes, Food Network |
| cosplayer | Cosplayer | Cosplayers, prop makers | Etsy, convention circuit, Patreon |
| fan | Fan | Audience members | Follow creators, purchase content |
Role-Platform Mapping
Each role has associated platforms for the Connections and Import pages. Platform connections are additive — if a user has multiple roles, they see all associated platforms.
Where Roles Are Referenced
1. settings.html — ALL_ROLES array (role checkboxes)
2. signup-performer.html — role chip buttons
3. onboarding.html — chooser card descriptions
4. auth.js — VALID_ROLES validation, registration
5. db/schema.sql — role column definition
6. connections.html — platform connection cards
7. import.html — platform import cards
8. discover.js — discovery categories
9. ai-assistant.js — ROLE_KNOWLEDGE object
10. setup-guide.html — Universal Roles section
11. tutorial.html — Choose Your Roles step
12. support.html — Role FAQs
Adding a New Role (Checklist)
When adding a new role, update ALL of these:
1. settings.html ALL_ROLES array
2. signup-performer.html role chips
3. auth.js VALID_ROLES
4. db/schema.sql role comment
5. connections.html platform cards
6. import.html import cards
7. discover.js categories
8. ai-assistant.js ROLE_KNOWLEDGE
9. setup-guide.html roles table
10. tutorial.html role buttons
11. support.html role FAQ answer
12. PLATFORM-OPERATIONS-MANUAL.md role table
13. onboarding.html if card text needs updating
Platform Connection Architecture
- 60+ platform connections supported
- Each connection stores: platform_id, api_key (encrypted), oauth_token, refresh_token, connected_at, last_sync
- Earnings import tagged by platform source (
data_source column)
- Cross-platform analytics aggregated in Financial Hub
Connections Page Layout
- 82 platform connections in
connections[] array (connections.html)
- 16 collapsible categories rendered by
renderCollapsibleSections()
- Categories: payments, social, music, streaming, podcasting, fitness, gaming, writing, marketplace, modeling, creator_economy, food, banking, entertainment, ride, other
- Each platform has: id, name, cat, desc, usedFor, fields[], links[], steps
- Connected state stored in localStorage (
indulgon_connections)
- Import page uses same collapsible pattern with 12 categories
Batch 1 Updates (May 2, 2026)
FAB Bar Architecture
- 5 floating action buttons in
js/ai-widget.js (replaces old standalone buttons)
- Order: Voice Narration | Panic/Safety | Color Customizer | Light/Dark Mode | AI Chat
- Old
.theme-toggle and .color-toggle CSS classes hidden via display: none !important
- Old button injection in
editorial-theme.js DOMContentLoaded disabled
- FAB bar uses
.indulgon-fab-bar and .indulgon-fab-btn CSS classes in editorial-base.css
- Panic popup:
.panic-popup with 3-second hold mechanism via JS timer
- Immediate threats (physical_danger, coercion, threatening_person) route to authorities first
- Panic API: POST
/api/safety/emergency and POST /api/safety/location
Indulgon Game (Scaffold)
- Route:
routes/indulgon-game.js at /api/game (6 endpoints)
- DB tables:
game_profiles, game_progress, game_achievements, game_sessions
- Player stats: charisma, talent, business, fitness, reputation
- 7 stages: newcomer → established → award_nominee → award_winner → mentor → mogul → legend
- Page:
indulgon-game.html (Coming Soon)
Universal Comments System
- Route:
routes/comments.js at /api/comments (6 endpoints)
- DB table:
comments (target_type + target_id polymorphic)
- target_type values: post, photo, video, avatar, cover, album, product, article, press_release, profile, folder
- Threaded: parent_id for replies
- Supports anonymous posting, likes
Media Assignments (Set-As System)
- Route:
routes/media-assignments.js at /api/media (5 endpoints)
- DB table:
media_assignments with UNIQUE(user_id, assignment_type, target_id)
- assignment_type values: avatar, cover_photo, album_cover, product_image, folder_cover, gallery_feature
- Profile Album: GET
/api/media/profile-album returns all historical avatars with is_current_avatar flag
- Animated avatars: video-to-GIF trim tool (UI scaffold, full build later)
Press Releases & Publications
- Route:
routes/press-releases.js at /api/press (9 endpoints)
- DB table:
press_releases
- Status flow: draft → pending_review → revisions_needed → approved → published
- Auto-generate from scene releases: POST
/api/press/auto-generate
- PR override: publicist settings override performer settings when enabled
- Same chain for agent bookings
- Articles by Platforms: studios/news sources upload/migrate articles
- Articles by Indulgon: auto-generated from scene releases
Affiliate System (Scaffold)
- DB tables:
affiliate_programs, affiliate_links
- Two tracks: studio's own affiliate program OR Indulgon-managed affiliates
- Commission tracked per-link: clicks, conversions, earnings
- Full route implementation in Batch 2
Phone Notifications (Full Twilio Integration)
Route: routes/phone-notifications.js at /api/phone
DB Table: phone_numbers — 22 columns including verification, notification prefs, quiet hours, paid messaging
Endpoints:
| Method | Path | Purpose |
| GET | `/api/phone/status` | Connection + verification status |
| POST | `/api/phone/connect` | Enter number, sends 6-digit verification code |
| POST | `/api/phone/verify` | Submit code to verify number |
| POST | `/api/phone/resend` | Resend verification code |
| PUT | `/api/phone/preferences` | Update notification toggles, quiet hours |
| POST | `/api/phone/notify` | Internal: send SMS notification (called by other routes) |
| POST | `/api/phone/incoming` | Twilio webhook: incoming SMS replies |
| POST | `/api/phone/disconnect` | Disconnect phone |
| POST | `/api/phone/paid-setup` | Configure paid messaging rates |
| GET | `/api/phone/paid-info/:userId` | Public: check if performer has paid messaging |
| POST | `/api/phone/test` | Send test notification |
Verification Flow:
1. User enters phone number → normalized to E.164 format
2. 6-digit code generated, stored with 10-minute expiry
3. SMS sent via Twilio (or simulated in demo mode)
4. User enters code → max 5 attempts
5. On success: is_verified = true, is_active = true, code cleared
6. Welcome SMS sent confirming activation
Notification Types: messages, bookings, safety, earnings (each independently toggleable)
Quiet Hours: No SMS during set times, EXCEPT safety alerts which always bypass
STOP/HELP/START: Twilio handles natively + manual handling in /incoming webhook
Reply Flow: Incoming SMS → find user by phone → find most recent conversation → insert reply → auto-mark as read
Paid Messaging: Per-message or monthly rate, set by performer
Environment Variables:
TWILIO_ACCOUNT_SID — Account SID from Twilio Console
TWILIO_AUTH_TOKEN — Auth Token from Twilio Console
TWILIO_PHONE_NUMBER — The Twilio number (E.164 format, e.g. +15551234567)
PLATFORM_URL — Base URL for deep links in SMS (default: https://indulgon.com)
A2P 10DLC: Campaign registered as "Mixed" use case. All recipients are verified opt-in users. SMS content is transactional notifications only, never explicit content.
- Paid messaging: customers pay per-message or monthly for performer's number
Navigation Updates
- New INDULGON section in nav dropdown (after ACCOUNT): Indulgon AI, Indulgon App, Indulgon Game
- Glossary and Updates pages added to ACCOUNT section
- AI Assistant page renamed to INDULGON AI (feature name unchanged)
Route Count: 162 (was 158)
DB Table Count: 296 (was 287)
Page Count: 80 (was 76)
Tax Revenue Calculator
Route: routes/tax-calculator.js at /api/tax
DB Tables: tax_1099s, tax_transactions
Endpoints:
| Method | Path | Purpose |
| GET | `/api/tax/1099s` | List 1099 forms (optional ?year= filter) |
| POST | `/api/tax/1099s` | Add single 1099 |
| POST | `/api/tax/1099s/bulk` | Bulk import 1099s |
| DELETE | `/api/tax/1099s/:id` | Delete 1099 |
| POST | `/api/tax/parse-transcript` | Parse IRS Wage & Income Transcript text |
| GET | `/api/tax/transactions` | List bank transactions (filters: year, account, category, type) |
| POST | `/api/tax/transactions/import` | Import parsed bank transactions |
| POST | `/api/tax/transactions/parse-csv` | Parse bank CSV (auto-detect columns) |
| GET | `/api/tax/summary` | Year-by-year revenue summary |
| GET | `/api/tax/discrepancies` | Cross-reference 1099s vs bank deposits |
| GET | `/api/tax/report/:year` | Full tax report for a year |
| GET | `/api/tax/la-city-response/:startYear/:endYear` | Generate LA City tax response letter |
| POST | `/api/tax/categorize/:id` | Manually recategorize a transaction |
| GET | `/api/tax/accounts` | List imported bank accounts |
Auto-categorization: 172+ patterns, 114 categories covering all 20 user roles.
CSV parsing: Auto-detects column layout (Date, Description, Amount, Deposit/Withdrawal, Balance).
GIF Editor (Animated Avatars)
Route: routes/gif-editor.js at /api/gif
DB Table: user_gifs
Requires: ffmpeg (pre-installed on server)
Endpoints:
| Method | Path | Purpose |
| GET | `/api/gif/status` | Check ffmpeg availability |
| POST | `/api/gif/create` | Create GIF from video (start/end/width/fps) |
| GET | `/api/gif/my-gifs` | List user's GIFs |
| DELETE | `/api/gif/:id` | Delete a GIF |
| POST | `/api/gif/probe` | Get video info (duration, dimensions, fps) |
Two-pass creation: Palette generation + palette-applied GIF for better colors.
Limits: Max 6 seconds, max 480px width, max 20 fps.
Batch 2 Updates (May 2, 2026 — Afternoon Session)
Google OAuth (Sign in with Google)
- Project: Indulgon-Platform (Google Cloud Console)
- OAuth Client: Indulgon Web Client (Web application)
- Client ID env var:
GOOGLE_CLIENT_ID
- Client Secret env var:
GOOGLE_CLIENT_SECRET
- Authorized JS Origins:
https://indulgon.com, http://localhost:3000
- Authorized Redirect URIs:
https://indulgon.com/app/oauth-callback.html, http://localhost:3000/app/oauth-callback.html
- Publishing Status: Testing (100 user cap, [email protected] added as test user)
- To go live: Push to Production in Google Cloud Console → Audience → Publish App (requires Google verification, 1-3 days)
- Existing endpoint:
POST /api/auth/oauth handles Google token verification and account linking
- Config endpoint:
GET /api/auth/oauth/config returns { google: { enabled, clientId } }
Cross-Platform Handle Resolver
- Route:
routes/handle-resolver.js
- Prefix:
/api/handles
- DB Table:
resolved_handles (name, platform, handle, profile_url, confidence, source, verified)
- Endpoints:
- GET /api/handles/resolve?name=Aidra+Fox — multi-signal lookup (IAFD → web search → cache → platform users)
- POST /api/handles/verify — manually verify/correct a handle
- GET /api/handles/search?q=query — search resolved handles
- POST /api/handles/bulk-resolve — batch resolve up to 20 names
- Lookup chain: Platform users → Placeholder records → IAFD database → Web search (gsk search)
- Cache: 7-day TTL in resolved_handles table, unique on (LOWER(name), platform)
- Supported platforms: twitter, instagram, tiktok, onlyfans, fansly, chaturbate, myfreecams, manyvids, youtube, facebook, reddit, twitch, threads
Scene Promo Composer
- Route:
routes/scene-promo.js
- Prefix:
/api/scene-promo
- DB Tables:
scene_promos (promo tracking + affiliate clicks), extended films table (+7 columns)
- Endpoints:
- GET /api/scene-promo/films — list filmography available for promotion
- GET /api/scene-promo/film/:filmId/photos?search=true — get/search photos for a film
- POST /api/scene-promo/create — create promo post with cross-platform handles, affiliate links, BTS photos
- POST /api/scene-promo/film/:filmId/affiliate — set affiliate/buy URL
- POST /api/scene-promo/film/:filmId/bts — add BTS photos
- GET /api/scene-promo/stats — promo performance stats
- Films table new columns: affiliate_url, affiliate_program, buy_url, cover_photo_url, bts_photos (jsonb), promo_post_ids (jsonb), dvd_info (jsonb)
Photo Import / Search
- Route:
routes/photo-import.js
- Prefix:
/api/photo-import
- DB Table:
imported_photos (source, urls, linked_film_id, album_id, photo_type, is_hd)
- Endpoints:
- GET /api/photo-import/search?q=name&type=headshot|bts|scene — web image search with HD detection
- POST /api/photo-import/import — import photo to profile/album/filmography
- GET /api/photo-import/imported — list imported photos
- DELETE /api/photo-import/:id — remove imported photo
Social Post Queue
- Route:
routes/social-queue.js
- Prefix:
/api/social-queue
- DB Table:
social_post_queue (platform, action_type, content, queue_position, status)
- Queue position ranges: retweets=100-199, quote_rt=200-299, original=300-399, cross_post=400-499
- Endpoints:
- GET /api/social-queue?platform=twitter — view queue
- POST /api/social-queue/add — add item (action_type: retweet|quote_retweet|original|cross_post)
- POST /api/social-queue/import-tagged — bulk import tagged posts as retweet queue
- POST /api/social-queue/process — publish next N items (respects ordering)
- GET /api/social-queue/preview — preview publish order
- POST /api/social-queue/reorder — move item (top/bottom/position)
- DELETE /api/social-queue/:id — remove from queue
- POST /api/social-queue/clear — clear published items
- GET /api/social-queue/settings — queue behavior settings
- PUT /api/social-queue/settings — update settings
Universal Media Search
- Route:
routes/media-search.js
- Prefix:
/api/media-search
- DB Table:
media_usage_log (tracking which images are used where)
- Endpoints:
- GET /api/media-search?q=query&source=all|web|platform|filmography|imports — unified search
- POST /api/media-search/use — attach search result to context (post, profile, film, product, album)
- Sources searched: web (gsk img-search), user posts with media, filmography (covers, BTS, scene photos), photo albums, imported photos
- FAB bar button: 6th button (image search icon), keyboard shortcut Ctrl+Shift+I
- Event dispatch:
indulgon-media-selected CustomEvent on window when user selects a result
Smart Calendar Enhancements
- Booth numbers:
POST /api/smart-calendar/generate-post now accepts booth_number, company_name, tags fields
- Company tag mapping:
KNOWN_TAGS dictionary maps 12+ companies to platform-specific handles
- Tag search:
GET /api/smart-calendar/tags?q=query — autocomplete for company/event tags
- Custom tags:
POST /api/smart-calendar/tags — add custom company tag mappings
- Platform versions: Generated posts include
platform_versions with handle replacements per platform
Feed Cross-Platform Tags
POST /api/feed/posts now accepts cross_post_to array and tagged_performers array
- Resolves handles from
resolved_handles table for each tagged performer
- Returns
platform_versions with correct @handles per platform
- Stores platform_versions + resolved_handles in post metadata (jsonb)
Posts Table Schema Update
- Added
metadata column (JSONB) for storing platform_versions, resolved_handles, cross_post_to
Clean URL Routing
server.js scans APP_DIR and creates routes for all .html files
/login, /dashboard, /tax, /feed, etc. all work
- Old
/app/*.html paths still work for backward compatibility
/ redirects to /login
Updated Counts
- Route files: 170 (was 171, consolidated)
- DB Tables: 306 (was 301)
- Pages: 82
- Setup guide sections: 46 (was 36)
- Tutorial steps: 61 (was 55)
- FAQ entries: 76 (was 67)
- FAB bar buttons: 6 (was 5)
- New tables this session: resolved_handles, scene_promos, imported_photos, social_post_queue, media_usage_log
Features Added 2026-05-07
Multi-Account Connections (`/api/accounts`)
- Universal multi-account support for ALL platform connections
- Multiple accounts per platform (e.g., personal + business Twitter)
- Default account selection, per-action account choosing
- DB:
platform_connections with account_label, account_type, is_default, is_active, capabilities
- Route:
routes/multi-account.js (8 endpoints)
Email Intelligence (`/api/email-intel`)
- Auto-extracts flights, invoices, platform notifications, shipping from email
- Cross-connects: flights→bookings+calendar+transactions, invoices→transactions, platform notifs→earnings
- 10 airline patterns, 5 shipping carrier patterns, 10 platform patterns
- Route:
routes/email-intelligence.js (6 endpoints)
- DB: uses existing tables (bookings, transactions, imported_earnings, wishlist_items)
Service Menu (`/api/service-menu`)
- Replaces Tally.so form — native ordering for custom videos, photo sets, Skype shows
- Performer configures: prices, styles, roles, outfits (linked to closet)
- 3 outfit paths: closet item, generic label, customer-provided (Amazon link)
- Customer-provided outfit cost added to their total (performer pays $0)
- Queue management, subscriber discounts, traffic source analytics
- Route:
routes/service-menu.js (14 endpoints)
- DB:
custom_requests.request_type, custom_requests.metadata, customer_identities, analytics_events
Unfulfilled Request Detector (`/api/unfulfilled`)
- Scans imported messages/tips across all platforms
- Detects: incremental payments, follow-up messages, large tips without delivery
- Confidence scoring: 0.95 (paid+unfulfilled) to 0.30 (asked, no payment)
- Route:
routes/unfulfilled-requests.js (5 endpoints)
Product Menu (`/api/product-menu`)
- Full product ordering: worn items, merchandise, digital, accessories, collectibles, custom
- 10 worn item add-ons (extra days, perfume, polaroid, etc.)
- Closet-to-product listing (worn item or store product)
- 3-path product selection matching service menu
- Route:
routes/product-menu.js (14 endpoints)
- DB:
orders.items, orders.total_price, orders.metadata
Live Queue (`/api/live-queue`)
- Real-time performer status: available, filming, editing, on_call, busy, break, offline
- Customer queue visibility with privacy controls
- Video call auto-connect: Skype, Zoom, Teams, FaceTime, Google Meet, Discord
- Buffer time between requests (fixed or per-type)
- Live show request/accept/decline/reschedule workflow
- Route:
routes/live-queue.js (14 endpoints)
Content Gallery (`/api/content-gallery`)
- Shoot management: create shoots, add files, select best, deliver to customer
- Delivery tracking: what was sent to whom, when
- Apple Photos-style timeline: all media chronologically by captured_at date
- Extras/upsell: unsent photos from shoots available for later delivery
- Route:
routes/content-gallery.js (12 endpoints)
- DB:
content_shoots, content_shoot_files, content_deliveries, media_timeline
Amazon/Shipping Order Tracking
- Added to wishlist items:
order_number, tracking_number, carrier, shipping_status, estimated_delivery
- Full lifecycle: wishlisted→cart→purchased→shipped→delivered→closet
- DB:
order_events table for order lifecycle event log
- 4 new endpoints on
routes/wishlists.js
Quote Automation System (Make.com Replacement)
Overview
Replaces all 6 Make.com scenarios with native platform functionality. Route: routes/quote-automation.js (1060 lines). Mounted at /api/quotes.
Endpoints
| Method | Path | Purpose |
| POST | `/api/quotes/receive` | Create new request + send confirmation email |
| POST | `/api/quotes/approve/:id` | Set price, create Stripe Payment Link, email customer |
| POST | `/api/quotes/start/:id` | Mark in-progress, email customer |
| POST | `/api/quotes/complete/:id` | Mark done, attach delivery URL, email customer |
| POST | `/api/quotes/deliver/:id` | Confirm delivery (digital/physical), email customer |
| POST | `/api/quotes/decline/:id` | Decline + suggest alternatives, email customer |
| POST | `/api/quotes/check-expirations` | Cron: renew expired links or expire quotes (Monday 9am) |
| POST | `/api/quotes/webhook` | Stripe webhook: payment success/fail/checkout |
| GET | `/api/quotes/dashboard` | Stats: pending, approved, in_queue, completed, revenue |
| GET | `/api/quotes/alternatives` | List alternative suggestions for performer |
| POST | `/api/quotes/alternatives` | Create new alternative suggestion |
| PUT | `/api/quotes/alternatives/:id` | Update alternative suggestion |
| GET | `/api/quotes/status/:quoteId` | Public quote status lookup |
| GET | `/api/quotes/events/:requestId` | Payment event audit trail |
Database Tables
custom_requests — extended with 17 new columns (quote tracking, payment links, lifecycle)
alternative_suggestions — counter-suggestion rotation (name, description, price, times_suggested)
payment_link_events — full audit trail of all payment events
Stripe Integration
- Payment Links API: Creates dynamic payment links with metadata (quote_id, request_id)
- Webhook: Receives
payment_intent.succeeded, payment_intent.payment_failed, checkout.session.completed
- Webhook Secret:
STRIPE_WEBHOOK_SECRET in .env for signature verification
- Webhook Endpoint ID:
we_1TUbdxHT3gKCK68N0cDtXkl8
Notion Database Mappings (Make.com equivalent)
| Notion Database | Platform Table | Sync Direction |
| Master Requests Queue | custom_requests | Bidirectional |
| Custom Quote Requests | custom_requests | Bidirectional |
| Custom Quote Requests (Special) | custom_quotes | Bidirectional |
| Alternative Suggestions | alternative_suggestions | Bidirectional |
| Transaction/Payment Log | payment_link_events | Platform → Notion |
Email Templates (12)
1. Request Received
2. Quote Approved (with payment button)
3. Full Payment Received (queue position)
4. Partial Payment (remaining balance + pay button)
5. Payment Failed (retry button)
6. Work Started (production status)
7. Content Ready (download link)
8. Content Delivered (digital) / Order Shipped (physical with tracking)
9. Link Expired - 1st Reminder (new link)
10. Link Expired - Last Chance (new link)
11. Quote Final Expiration
12. Decline with Alternatives
Cron Job
- Payment Link Expiration Check: Every Monday 9am ET
- Crontab:
0 9 * * 1 curl -s -X POST http://localhost:3000/api/quotes/check-expirations
- 3-tier system: reminder → last chance → final expiration (42 days total)
Payment Flow
1. Customer submits request → POST /api/quotes/receive
2. Performer sets price + approves → POST /api/quotes/approve/:id → Stripe Payment Link created
3. Customer clicks link → pays on Stripe-hosted page → redirected to indulgon.com/order-confirmed
4. Stripe webhook fires → POST /api/quotes/webhook → updates payment status
5. Full payment → auto-adds to production queue with position number
6. Partial payment → tracks amount_paid, sends receipt with remaining balance
Security
- Webhook signature verification via
STRIPE_WEBHOOK_SECRET
- Raw body parsing for webhook endpoint (before JSON middleware)
- Payment link metadata includes quote_id for matching
Smart Request Detection (Custom vs Quote)
Overview
Detects when a customer's Quote Request description matches existing menu options and offers to redirect them to a Custom Request with set pricing.
Endpoint
POST /api/service-menu/:performerId/smart-match — Accepts { text }, returns matched styles, roles, outfits, service types
Customer-Facing Page
order.html at /order?performer=[id] — Dual-mode form with Custom Request / Quote Request toggle
How It Works
1. Customer types in Quote Request description textarea
2. 800ms debounce triggers POST /smart-match with their text
3. Backend matches against performer's: styles, creator_roles, customer_roles, outfits, custom_services, and request type keywords
4. If matches found, popup shows what was detected with option to switch
5. Switching copies description to Special Instructions, pre-selects matched options, transfers name/email
Custom Request Features
- Type selector: Custom Video, Photo Set, Video Call/Skype, custom services
- Duration/quantity chip selectors with live pricing
- Style multi-select chips (JOI, POV, Roleplay, etc.)
- Creator/customer role dropdowns
- Outfit dropdown (closet items, generic text, or custom)
- Special Instructions textarea — always visible, optional
- Live price breakdown display
- HD photo upgrade toggle
Quote Request Features
- Free-form description textarea with smart detection
- Budget range dropdown
- Timeline preference
- Reference links/images
- Submits to
POST /api/quotes/receive
Request Inbox System
Overview
The Request Inbox (/request-inbox) is the performer's central workspace for managing Custom Requests and Quote Requests. It provides filtering, searching, sorting, saved filter presets, and sentence-format request summaries.
Endpoints
| Method | Path | Description |
| GET | `/api/service-menu/requests/inbox` | Filter/search/sort/paginate requests |
| PUT | `/api/service-menu/requests/saved-filter` | Save a named filter preset |
| GET | `/api/service-menu/requests/saved-filters` | List all saved filter presets |
Inbox Query Parameters
status — pending, quote_pending, quoted, in_progress, completed, delivered, declined, expired
request_type — custom_video, photo_set, skype_show, custom_quote, product_request
style — JOI, POV, Roleplay, Humiliation, ASMR, CEI, Countdown
outfit — Free text search (matches against outfit field)
category — Any of the 15 service categories
duration — 5, 10, 15, 20, 25, 30, 45, 60
min_price, max_price — Price range filter
search — Free text across name, email, instructions, formats, quote_id
sort_by — newest, oldest, price_high, price_low, status, type, queue, duration
page, per_page — Pagination (default 30 per page)
Response Includes
requests[] — Array of request objects with summary (sentence format), styles[], outfits[], service_categories[], status, price, dates
facets.statuses[] — Count of requests by status
total, page, total_pages — Pagination info
applied_filters — Echo of active filters
Sentence-Format Notifications
The generateRequestSummary() function creates human-readable summaries from order data:
"James Smith requested a Custom Video for 10 minutes (JOI, POV) in Schoolgirl as Teacher (customer wants to be called Daddy) for $300.00 [Categories: JOI, Foot Fetish] - 'Black heels and red panties, call me Daddy, countdown from 10'"
Used for: performer notifications, Request Inbox cards, customer email confirmations.
Saved Filter Presets
Filters are stored in user_settings with key service_menu_saved_filters. Each preset has a name and a filters object. Performers can save presets like "Red Panties", "JOI 10min", "Foot Fetish Requests" for one-click batch access.
Order Form (Customer-Facing)
Overview
The Order Form at /order?performer=[id] is the unified customer page for placing Custom Requests and Quote Requests. It serves as the parent page for all custom content.
Two Modes
| Feature | Custom Request | Quote Request |
| Service Types | Custom Video, Photo Set, Skype Show | Custom Video, Photo Set, Skype Show |
| Pricing | Set by performer rate card, shown instantly | Performer reviews and sends personalized quote |
| Payment | Immediate Stripe checkout | Payment link after quote approval |
| Best For | Standard orders | Unique/complex requests |
Form Fields (shared by both modes)
- 15 Service Categories: Foot Fetish, Pantyhose/Nylon, Leg Fetish, Hand Fetish, JOI, Ignore Fetish, ASMR/Sensory, Food Fetishes, Watersports, Balloon Popping, Smoking Fetish, Wet & Messy, Crush Fetish, Femdom/Domination, Other/Custom
- 10 Add-Ons: Anal, B/G, G/G, Toys, Oil/Lotion, Dirty Talk, Name Use, Extended Length, Rush Delivery, HD Upgrade
- Style Selection: Multi-select chips
- Creator/Customer Roles: Dropdown selects
- Outfit Selection + Color/Details: Main outfit dropdown + free text for specifics
- Special Instructions: Always-visible textarea
Quote Request Additional Fields
- Service Format: Multi-select chips (Custom Video, Photo Set, Skype Show)
- Props & Supplies: Textarea for listing items needed
- Smart Request Detection: 800ms debounce, matches customer text against menu options
Constants (in service-menu.js)
DEFAULT_SERVICE_CATEGORIES — 15 categories
DEFAULT_ADD_ONS — 10 add-ons
Nav Page Search
Overview
Search bar in the navigation bar for instant page navigation. Accessible via click (magnifying glass icon, top-right) or keyboard shortcut (Ctrl+K / Cmd+K).
Implementation
Built into nav.js. Maintains a flat allSearchPages[] array built from corePages + all moreGroups. Searches by label, href, and group name. Results show page name + nav category. Enter navigates to first result. Escape closes.
Navigation Updates
- Order Form (
order.html) added to COMMERCE group
- Request Inbox (
request-inbox.html) added to COMMERCE group
Request Form Editor
Overview
The Request Form Editor (/request-form-editor) allows performers to fully customize their customer-facing order form. All settings are stored as service_menu_* keys in user_settings table.
5 Customization Tabs
| Tab | What It Controls |
| Form Fields | Toggle field visibility, reorder fields |
| Options & Selections | Add/remove/rename options in every dropdown/chip group (12 option sets) |
| Labels & Wording | Custom labels, help text, placeholders for every field |
| Policies & Pricing | Content policy lists, sales/refund policy, video/photo/Skype pricing |
| Email Templates | Subject and body for 6 lifecycle emails with {placeholder} support |
Option Sets (12)
Styles, Service Categories, Creator Roles, Customer Roles, Outfits, Moods, Color Schemes, Tools & Toys, Accessories, Locations, Add-Ons, Product Items
Endpoints
| Method | Path | Description |
| GET | `/api/service-menu/settings` | Get performer's current settings |
| PUT | `/api/service-menu/settings` | Save settings (any key-value pairs) |
| POST | `/api/service-menu/settings/reset` | Delete all custom settings, revert to defaults |
How Customization Propagates
GET /api/service-menu/:performerId returns form_config object with:
- field_visibility — which fields are hidden
- labels — custom field labels
- help_text — custom help text
- placeholders — custom placeholder text
- email_templates — custom email subjects/bodies
- Order form (
order.html) reads form_config and hides disabled fields
- Email sending functions check for custom templates before using defaults
- Notification summaries use the option names the performer configured
Storage
All settings stored as service_menu_{key} in user_settings table (PostgreSQL JSONB values).
Example keys: service_menu_styles, service_menu_label_outfits, service_menu_form_field_visibility, service_menu_email_request_received_subject.
Universal Undo System
Overview
Apple Markup-style undo available on all editor pages. Tracks individual changes, supports undo/redo one at a time, and "Revert All" to page-load state.
Implementation
js/undo-system.js (172 lines) — standalone module, no dependencies.
UndoSystem.track(key, oldValue, newValue, label) — record a change
UndoSystem.undo() / UndoSystem.redo() — one step at a time
UndoSystem.revertAll() — back to snapshot
- Keyboard: Ctrl+Z (undo), Ctrl+Y or Cmd+Shift+Z (redo)
- Floating undo bar appears bottom-right when changes exist
- Max 200 history entries per session
Pages Using Undo
request-form-editor.html — all option edits, field toggles, label changes
settings.html — available for future integration
Multi-Format Orders
Overview
Customers can select multiple request types (Custom Video + Photo Set + Skype Show) in a single order. Each type gets its own duration/quantity selector.
Multi-Outfit Ordering
Multiple outfits can be selected. When >1 outfit is chosen, an ordering hint appears asking which to wear first. The Special Instructions placeholder updates to prompt outfit order specification.
Notion Option Sync
Overview
When performers save option changes in the Form Editor, the platform syncs those options to connected Notion databases via the Notion API databases.update() endpoint.
Behavior
- New option added: Auto-created in Notion multi_select property
- Option renamed: New name added to Notion, old entries keep old name (Notion API limitation)
- Option removed: Not removed from Notion (would break existing entries)
- Sync is fire-and-forget: Failures logged but don't block the save
Notion Databases Synced
| Database | ID | Properties Synced |
| Customer Orders (Current) | 13fb8641... | Style, Attire, Creator Role, Customer Role, Mood, Color Scheme, Tools & Toys, Accessories, Service Category |
| Customer Orders (Completed) | 13fb8641... | Same as above |
| Custom Quote Requests (Special) | 2e8b8641... | Style, Creator Role, Customer Role, Mood, Color Scheme, Service Category |
API Method
notionClient.updateDatabaseProperties(databaseId, properties) — added to middleware/notion-client.js
Notion-Enriched Options (807 Total)
Data Source
All dropdown options pulled from Jillian's real Notion databases:
- Styles (enriched): 30eb8641... → 61 options
- Moods (enriched): 30eb8641... → 26 options
- Customer Roles (enriched): 30eb8641... → 73 options
- Creator Roles (enriched): 30eb8641... → 73 options
- Service Categories (enriched): 30eb8641... → 97 options
- Color Schemes (enriched): 30eb8641... → 79 options
- Materials: 30eb8641... → 44 options
- Scene Types: 30eb8641... → 8 options
- Interaction Styles: 310b8641... → 11 options
- Traffic Sources: 310b8641... → 15 options
- Supplies: 2e8b8641... (Supply Items Database) → 30 options
- Costume Groups: → 6 options
- Service Formats: → 6 options (Custom Video, Skype Show, Premade Video, Photo Set, Personalized Item, Dick Rating)
Full Notion Audit (1,152 databases)
| Category | Count | Notes |
| Business Orders | 79 | Customer Orders, Queue, dropdown DBs |
| Business Financial | 166 | Income, expenses, tax, bank, budget |
| Business Contacts | 48 | Clients, vendors, addresses |
| Business Projects | 38 | Tasks, milestones, goals |
| Business Products | 26 | Products, inventory, closet |
| Business Content | 32 | Media, portfolio, calendar |
| Business Marketing | 16 | Social, analytics, affiliates |
| Business Ops | 102 | Settings, templates, config |
| Platform Core Mapped | 34 | Already integrated |
| Personal Life | 66 | Habits, journal, health, goals |
| Personal Travel | 81 | Trips, flights, hotels, Airbnbs |
| Personal Finance | 58 | Budget, savings, subscriptions |
| Personal Entertainment | 22 | Movies, books, anime, music |
| Personal Home | 16 | Plants, recipes, gifts, shopping |
| Personal Education | 21 | Courses, grades, coding |
| Duplicates/Templates | 115 | Notion template instances |
| Uncategorized | 232 | Need review |
Dick Rating Service
Implementation
- Service format type:
dick_rating
- Rating styles: Honest, Generous, SPH, Worship (chip select)
- Simplified form: only rating style + attachments + special instructions
- No duration/outfit/location needed
- Pricing: performer-set rate for dick ratings
Order Attachments
Implementation
- Route:
POST /api/files/order-attachments
- Storage:
uploads/order-attachments/
- Limits: 10 files max, 10MB each
- Accepted: jpg, png, gif, webp, mp4, webm
- Reference links: textarea field stored in order metadata
Supply Items
Implementation
- 30 default supplies (Pies, Balloons, Oil, etc.)
- Stored as array in order metadata
- Quote emails include supplies as separate line item
- Performer sets supply cost during quote review
- Custom supplies can be added by customer (synced to Notion)
Role-Specific Pages (v0.35.0)
Overview
Specialized pages for specific creator roles. All users get shared features (Dashboard, Earnings, Bookings, etc.). Role-specific pages add tools tailored to each role's workflow. Accessible from More > Creative in navigation.
Podcaster Hub
- Page:
public/app/podcaster.html
- Route:
routes/podcaster.js mounted at /api/podcaster
- Endpoints: GET/POST
/episodes, GET /rss/:slug, GET /guests, POST /guests/invite
- Features: Episode management, download analytics, RSS feed generation, guest booking/invitations
- Tables:
podcast_episodes (with graceful simulation fallback)
Artist Studio
- Page:
public/app/artist.html
- Route:
routes/artist-portfolio.js mounted at /api/artist
- Endpoints: GET/POST
/portfolio, GET/POST /commissions, GET /prints
- Features: Portfolio gallery, commission tracker (3 tiers: Basic $50, Standard $150, Premium $400), print shop, WIP progress posts
- Tables:
artist_works, artist_commissions, artist_prints (with graceful simulation fallback)
Writer's Desk
- Page:
public/app/writer.html
- Route:
routes/writer.js mounted at /api/writer
- Endpoints: GET/POST
/publications, GET/POST /blog, GET/POST /serials, POST /serials/:id/chapters
- Features: Publication library, blog editor with draft/publish/subscriber-only, chapter-based serial publishing, readership analytics
- Tables:
writer_publications, writer_blog_posts, writer_serials, writer_chapters (with graceful simulation fallback)
Cosplay Workshop
- Page:
public/app/cosplayer.html
- Route:
routes/cosplay.js mounted at /api/cosplay
- Endpoints: GET/POST
/costumes, GET/POST /build-logs, GET /conventions, GET /commissions
- Features: Costume gallery, step-by-step build logs (materials, time, tips), convention calendar, custom costume commissions
- Tables:
cosplay_costumes, cosplay_build_logs, cosplay_conventions (with graceful simulation fallback)
Filmography Access
- Route:
routes/filmography.js mounted at /api/filmography
- No role restrictions on any endpoint
- All logged-in users can create scenes, tag co-performers, and import from IAFD
- Fans and unauthenticated users can browse the IMDB-style library (search by performer, studio, title)
- The
role field in film_performers refers to the role within the film (e.g., "performer", "director"), NOT the user's platform role
Existing Role Pages
- Music (
music.html, routes/music.js) -- Musicians
- Fitness (
fitness.html, routes/fitness.js) -- Athletes
- Gaming (
gaming.html, routes/gaming.js) -- Streamers
- Recipes (
recipes.html, routes/recipes.js) -- Chefs
- Cam (
cam.html, routes/cam-rooms.js) -- Performers (cam models)
- FinDom (
findom.html, routes/findom.js) -- Performers (financial domination)
- House Girl (
house-girl.html, routes/house-features.js) -- House Girls
Role-Specific Pages (v0.35.0)
Overview
Specialized pages for specific creator roles. All users get shared features (Dashboard, Earnings, Bookings, etc.). Role-specific pages add tools tailored to each role's workflow. Accessible from More > Creative in navigation.
Podcaster Hub
- Page: public/app/podcaster.html
- Route: routes/podcaster.js mounted at /api/podcaster
- Endpoints: GET/POST /episodes, GET /rss/:slug, GET /guests, POST /guests/invite
- Features: Episode management, download analytics, RSS feed generation, guest booking/invitations
Artist Studio
- Page: public/app/artist.html
- Route: routes/artist-portfolio.js mounted at /api/artist
- Endpoints: GET/POST /portfolio, GET/POST /commissions, GET /prints
- Features: Portfolio gallery, commission tracker (3 tiers), print shop, WIP progress posts
Writer's Desk
- Page: public/app/writer.html
- Route: routes/writer.js mounted at /api/writer
- Endpoints: GET/POST /publications, GET/POST /blog, GET/POST /serials, POST /serials/:id/chapters
- Features: Publication library, blog editor, chapter-based serial publishing, readership analytics
Cosplay Workshop
- Page: public/app/cosplayer.html
- Route: routes/cosplay.js mounted at /api/cosplay
- Endpoints: GET/POST /costumes, GET/POST /build-logs, GET /conventions, GET /commissions
- Features: Costume gallery, step-by-step build logs, convention calendar, custom costume commissions
Filmography Access
- No role restrictions on any endpoint
- All logged-in users can create scenes, tag co-performers, and import from IAFD
- Fans can browse the IMDB-style library (search by performer, studio, title)
- The role field in film_performers refers to the in-film role, NOT the platform role
All Role-Specific Pages
- Music (music.html) -- Musicians
- Podcaster Hub (podcaster.html) -- Podcasters
- Artist Studio (artist.html) -- Artists
- Writer's Desk (writer.html) -- Writers
- Cosplay Workshop (cosplayer.html) -- Cosplayers
- Fitness (fitness.html) -- Athletes
- Gaming (gaming.html) -- Streamers
- Recipes (recipes.html) -- Chefs
- Cam (cam.html) -- Performers
- FinDom (findom.html) -- Performers
- House Girl (house-girl.html) -- House Girls
Companion Services (Rebuilt v0.36.0)
Overview
Safety-first in-person meetup booking system. NOT for filming. Covers dinner dates, events, appearances. Every customer must be identity-verified before booking. Cross-performer review system ensures performers always know who they are meeting.
Page
public/app/companion-services.html (261 lines)
- 6 tabs: Dashboard, Bookings, Customer Profiles, Reviews, Safety, Rates
- Located in More > Professional > Companion in navigation
Route
routes/companion-services.js (197 lines) mounted at /api/companion
Endpoints
- GET / -- Dashboard stats (total bookings, verified clients, safety score, earnings)
- GET/PUT /profile -- Companion profile
- GET /bookings -- List bookings (filterable by status)
- POST /bookings -- Create booking request (checks customer verification)
- PUT /bookings/:id -- Update booking (accept/decline/counter/complete/cancel/no_show)
- GET /customers -- Customer list with verification status, avg rating, review count, warning flags
- GET /customers/:id -- Full customer profile with all reviews from all performers
- POST /customers/:id/block -- Block a customer
- POST /customers/:id/report -- Report a customer to safety team
- GET /reviews -- Written reviews, received reviews, reviews from other performers
- POST /reviews -- Submit post-booking review (rating, tags, text)
- GET/PUT /rates -- Rate structure (8 default types: 1hr, 2hr, dinner, event, half day, full day, overnight, weekend)
- GET/PUT /safety -- Safety settings
- POST /verify -- Customer submits ID for verification
- GET /verify/:id -- Check verification status
- POST /incidents -- File incident report
Customer Verification Flow
1. Customer uploads government ID photo (driver's license, passport, state ID)
2. Customer takes live selfie for photo match comparison
3. Admin or AI reviews and approves/rejects
4. Verified badge appears on customer profile, visible to all performers
5. Unverified customers cannot book (if performer has require_id_verification enabled)
Cross-Performer Review System
- After each completed booking, performer rates customer (1-5 stars)
- Tags: Respectful, On Time, Good Communicator, Professional, Generous Tipper
- Warning tags (red): Late, No-Show, Boundary Issues, Made Uncomfortable
- All reviews visible to ALL performers, not just the reviewer
- Warning flags aggregate across all reviews and show on customer cards
- Performers can auto-decline customers with warning flags (safety setting)
Safety Features
- Require ID verification (default: ON)
- Require deposit (default: ON, 50%)
- Safety check-ins during bookings (default: ON) -- missed check-in notifies emergency contact
- GPS sharing with emergency contacts (default: OFF)
- Auto-decline unverified customers (default: ON)
- Auto-decline customers with warning flags (default: OFF)
- Emergency contacts management
- Customer blacklist
- Incident reporting to platform safety team
Booking Statuses
Requested > Accepted > Deposit Paid > Confirmed > Completed (or Cancelled / No-Show)
11. Features Added Sessions 12-17 (2026-05-08 through 2026-05-12) {#11-new-features}
> This section covers every feature built since the Content Calendar overhaul. All routes, tables, and pages are production-ready and tested.
Creative Tools
Stories (`stories.html` / `routes/stories.js`)
- Tables:
stories, story_views, story_reactions, story_highlights
- Endpoints: CRUD +
/api/stories/archive, /api/stories/:id/repost, /api/stories/:id/highlight
- 24-hour visibility then permanent archive. Browsable by month, searchable by caption.
- Repost creates fresh 24-hour story from any archived story.
- View tracking with timestamps. Reaction system.
Reels (`reels.html` / `routes/reels.js`)
- Tables:
reels, reel_likes, reel_comments
- Short-form video with duets (side-by-side), stitches (clip + respond)
- Auto-captions enabled by default
- Sounds Library integration (
routes/sounds.js, sounds table, saved_sounds table)
Smart Video Editor (`video-editor.html` / `routes/video-editor.js`)
- Tables:
video_edit_jobs, video_edit_projects
- Two modes: Auto (4 AI modes: highlight reel, teaser, recap, best-of) and Custom (multi-track timeline)
- Export to Story or Reel with auto-captions
- Trim, cut, effects, transitions, speed control
Auto-Generated Closed Captions (`routes/captions.js`)
- Tables:
caption_jobs, video_captions, caption_settings
- Speech-to-text with 8 styles and 20 languages
- Burn-in (permanent in video) or overlay (viewer toggleable)
- Auto-enable configurable per content type in Settings
- Important: Parametric routes (
/:sourceType/:sourceId) must be LAST in Express router (catches /styles/list otherwise)
Transcripts (`transcripts.html` / `routes/transcripts.js`)
- Tables:
transcripts, transcript_settings
- Searchable text from 12 video source types
- Full-text search via PostgreSQL
tsvector + GIN index
- Reader modal with timestamped segments (click to jump)
- Auto-save settings: watched, bookmarked, messages, orders
- Stats dashboard: total transcripts, words, hours
Advanced Feed Features (`feed.html` / `routes/feed.js`)
- 10 media layout options (Auto through Carousel)
- Feed album system (auto at 20+ media, manual create, add-to-existing)
- 5 preview modes (Feed, Grid, Album, Carousel, Masonry)
- Timed posts (auto-expire to Timed History, NOT Archive)
- Schedule picker, drip-feed posting
- Post editing at any time (no time restrictions)
- Post engagement on all views (Drafts, Archive, Scheduled, Timed History)
- EXIF date extraction for chronological ordering
- Drag-and-drop media upload
PUT /api/feed/posts/:id for editing
Content Gallery (`content-gallery.html` / `routes/content-gallery.js`)
- Unified media library chronological by
captured_at (EXIF)
- Tabs: All, Albums, Create Post
- Shared
renderMedia() and mediaEl() functions
Productivity and Organization
Unified Inbox (`inbox.html` / `routes/inbox.js`)
- Aggregates: booking requests, custom requests, Ask Box questions, tips
- Tables:
tips (new), columns added: booking_requests.read_at, custom_requests.read_at
- Lifecycle: Unread → Read → Acted On
- Sort: received date, due date, amount, unread first, type
- Customer Notes Panel: slide-out with tabs (All Notes, per-page tabs)
- Technical:
ask_box.sender_id is VARCHAR, users.id is UUID — JOIN uses u.id::text=ab.sender_id
Notes (`notes.html` / `routes/notes.js`)
- New columns:
notes.category, notes.has_attachments, notes.source_page, notes.source_id, notes.is_sticky, note_folders.category, note_folders.icon
- 8 sort options (server-side SQL ORDER BY)
- Filter by type, category, attachments, text search
- Grouped rendering (Category/Folder/Type sorts show section headers)
- Customer context:
/api/notes/context/:contactId returns all_notes, by_page, sticky_notes, top_tags
- Quick note:
/api/notes/quick with auto-folder filing
- Auto-folders:
sourcePageToFolder() maps page names → folders
- Sticky toggle:
/api/notes/:id/sticky
Kanban Project Board (`kanban.html` / `routes/kanban.js`)
- Tables:
kanban_boards, kanban_cards
- Custom columns, drag-and-drop, labels, due dates, checklists
- Multiple boards per user
Ask Box (`ask-box.html` / `routes/ask-box.js`)
- Tables:
ask_box, ask_box_settings, ask_auto_answers
- Payment: free quota (default 3), paid ($5), priority ($15). 15% platform fee.
- Duplicate detection:
pg_trgm >60% similarity. Published answers free for future fans.
- Auto-response KB: auto-save answers, fuzzy matching >40%, auto_respond toggle per answer
- 3-tab UI: Inbox, Auto-Answers, Analytics
- Key columns:
is_priority, payment_status, payment_intent_id, amount_paid, platform_fee, performer_earnings, duplicate_of, auto_answer_id, suggested_answer_id
Expedite / Priority Bidding (`routes/expedite.js`)
- Tables:
expedite_settings, expedite_bids
- Added columns:
priority_fee_cents, is_expedited, queue_position, expedited_at on booking_requests and custom_requests
- Settings CRUD, queue view, bid placement, outbid + auto queue recalculation
- Default: $10 base fee, 3 max slots, bidding enabled, $5 min increment
Custom Phrases (`routes/custom-phrases.js`)
- Tables:
custom_phrases, phrase_settings
- Per-customer nicknames with
{{nickname}} template replacement
- Categories: tip_response, greeting, thank_you, farewell, general
- 5 rotation modes: least_used, most_used, random, sequential, weighted
- Auto-detect: scans messages for phrases used 3+ times to same person
- Sources: manual, auto_detected
Social Features
Audio Rooms (`spaces.html` / `routes/audio-rooms.js`)
- Tables:
audio_rooms, audio_room_participants
- Live audio with tip integration
Channel Points (`routes/channel-points.js`)
- Tables:
channel_points, channel_points_log, channel_rewards
- Earn points for engagement, redeem for custom rewards
Matching (`routes/matching.js`)
- Tables:
match_profiles, match_actions, matches
- Industry-specific profile matching
Raids (`routes/raids.js`)
- Tables:
raids
- Send audience to another creator's live content
Memories (`routes/memories.js`)
- "On This Day" from all content types
AR Filters (`routes/ar-filters.js`)
- Tables:
ar_filters
- Creator-uploaded camera effects
Visual Search (`routes/visual-search.js`)
- Image-based content/product discovery
Platform Systems
Change Trail (`routes/change-trail.js`)
- Single
change_trail table for all content types
- Universal edit history with diff tracking
- Visibility modes: Show, Hidden, Off (per-user in Settings)
- Server-side privacy enforcement (queries filter by
user_id)
Universal Undo System (`public/app/js/undo-system.js`)
- Collapsible FAB on 62 pages
- Reset page to defaults, undo filter/sort/view changes
- Theme-aware (inverted colors for visibility in light/dark modes)
Role Switcher (`public/app/js/role-switcher.js`)
- Switch between Combined/Performer/Studio/Agent/Admin views
- Available on 60+ pages
- Syncs via
/api/auth/whoami endpoint
- Active view persists in localStorage
Multi-Email Login (`routes/auth.js`)
linked_emails table
- Login with any linked email (password or OAuth)
Presence Modes (`routes/presence.js`)
- Online, Busy, Away, Incognito, Offline
- Per-mode visibility rules
Health Monitoring (`routes/health-monitor.js`)
- Client-side error tracking, API error tracking
- Auto-detect bug patterns (admin-only)
Loyalty Badges (`routes/loyalty-badges.js`)
- 10 badge types with earning criteria
- Custom badges per performer
Universal Platform Search (`routes/platform-search.js`)
- Ctrl+K from any page
- Keyword-rich search entries for all pages/features
External Payments (`routes/external-payments.js`)
- CashApp/Zelle/Venmo/PayPal display handles
- Transaction logging with 15% fee tracking
Credit Wallet (`routes/credits.js`)
- Credits for marketplace purchases
- Cashout with 15% fee
- Promotional credits tracked separately ($0 real value)
User Subdomains (`routes/user-subdomains.js`)
username.indulgon.com and indulgon.com/u/username
- Server routing built, requires Cloudflare wildcard DNS
Video/Voice Calls (`video-calls.html` / `routes/video-calls.js`)
- FaceTime-style calls
- Call queue: paid prioritized over free
- Per-minute rates, 15% platform fee
Bookmarks (`bookmarks.html` / `routes/bookmarks.js`)
- 3-level categorization: Category > Subcategory > Tag
Bots & Plugins (`bots.html` / `routes/bots.js`)
- Tables:
bots, bot_installs, bot_event_log
- 10 pre-built bots, marketplace
- Install/configure/disable/uninstall lifecycle
Activity Tracker (`routes/activity-tracker.js`)
- Action-agnostic
activity_log table
- Tracks any event type
Test Mode (`routes/test-mode.js`)
- Tester accounts bypass payment
- Invisible badges (visible only to admin)
- Token-based signup links
Auto-Sync & Updates
Updates Page (`updates.html` / `routes/updates.js`)
- Full database-style development history viewer
- Public View / Admin View toggle
- Markdown export + Notes import
- Session picker
startAutoSync(app) called in server.js after registerAllRoutes()
- Initial 10s delay, then hourly via setInterval
- Parses CHANGELOG.md, creates one note per session in "Platform Updates" folder
- Idempotent (skips existing by title match)
Email System
Email Templates (`routes/email-templates.js`)
- 21 templates across 7 categories
- All booking/request emails include full form details table
{{variable}} placeholders with conditional sections ({{#field}}...{{/field}})
- Mailer exports
sendEmail() not sendMail() — use require('../middleware/mailer').sendEmail()
Database Summary (New Tables This Sprint)
| Table | Purpose |
| stories | Story posts |
| story_views | View tracking |
| story_reactions | Reactions |
| story_highlights | Pinned stories |
| reels | Short-form video |
| reel_likes | Reel likes |
| reel_comments | Reel comments |
| audio_rooms | Live audio |
| audio_room_participants | Room members |
| kanban_boards | Project boards |
| kanban_cards | Board cards |
| ask_box | Fan questions |
| ask_box_settings | Pricing/quota config |
| ask_auto_answers | Knowledge base |
| channel_points | Point balances |
| channel_points_log | Point transactions |
| channel_rewards | Redeemable rewards |
| ar_filters | Camera effects |
| match_profiles | Matching profiles |
| match_actions | Like/pass actions |
| matches | Mutual matches |
| raids | Audience redirects |
| sounds | Audio library |
| saved_sounds | User saved sounds |
| bots | Bot definitions |
| bot_installs | User bot installations |
| bot_event_log | Bot activity |
| video_edit_jobs | Edit queue |
| video_edit_projects | Project files |
| caption_jobs | Caption generation |
| video_captions | Generated captions |
| caption_settings | Auto-caption config |
| transcripts | Searchable text |
| transcript_settings | Auto-save config |
| custom_phrases | Per-customer phrases |
| phrase_settings | Rotation mode config |
| tips | Tip records |
| expedite_settings | Queue priority config |
| expedite_bids | Priority bids |
Total new tables this sprint: 39
Platform total: 382+ tables
Cross-Platform Posting (`routes/cross-post.js`, `routes/social-queue.js`)
- 8 platform targets: Twitter/X, Instagram, Fansly, OnlyFans, Reddit, Chaturbate, ManyVids, Pornhub
- Twitter API live posting (1,500 posts/mo free tier)
- Social queue: retweets of tagged posts always before original content
- Cross-post dropdown in feed compose box
Progressive Web App (PWA)
sw.js service worker with offline cache
manifest.json for install prompt
- Push notifications via Web Push API
- Installable from browser on iOS, Android, iPad, desktop
- No App Store needed
pwa-install.js handles install prompt UI
Fan Migration (`routes/fan-integration.js`)
- Two-sided consent: performer tags fans, fans consent
- Granular consent per data type
- GDPR compliant
Partner SDK (`routes/partner-sdk.js`, `sdk-docs.html`)
- Full REST API documentation
- Webhook system, sandbox testing, API key management
Email Sync (`routes/email-sync.js`)
- Connect email accounts
- Auto-categorize, priority detection, action flagging
Admin Tools (`routes/admin-tools.js`)
- User impersonation, content moderation, user management
Content Moderation (`routes/content-moderation.js`, `routes/reports.js`)
- User reporting, admin review queue
Password Reset (in `routes/auth.js`)
- Email-based, secure token, 1-hour expiry
Daily Backups
- PostgreSQL pg_dump via cron, date-stamped
Tax Calculator (`routes/tax-calculator.js`)
- 1099s, bank statements, 172+ patterns, 114+ categories, all 19 roles
Tip Menu (`routes/tip-menu.js`)
- Customizable amounts and descriptions
Mass DM (`routes/mass-messaging.js`)
- Send to all, tiers, or filtered groups
Section 12: Account Snapshots, Analytics, and Data Retention
Account Snapshot System
- Route:
routes/account-snapshots.js → /api/snapshots
- DB Tables:
account_snapshots, account_restore_log
- Auto-scheduler: Daily snapshots at 3 AM via
startAutoSnapshots() (wired in server.js)
- Snapshot coverage: 35+ tables per user (profile, posts, orders, messages, settings, notes, bookmarks, etc.)
- Retention: 90 days regular, permanent for deletion snapshots
- Expired snapshot cleanup: Automatic during daily snapshot run
Analytics Endpoints
GET /api/snapshots/analytics/sales?period=30d — Top products, services, custom requests, revenue trend
GET /api/snapshots/analytics/engagement?period=30d — Top posts, failure analysis, top fans
GET /api/snapshots/analytics/trends?period=30d — Best days/hours, category performance, repeat rate
- Period options: 7d, 30d, 90d, 1y, all
Account Recovery
POST /api/snapshots — Create manual snapshot
POST /api/snapshots/restore/:id — Restore from snapshot (double confirmation in UI)
POST /api/snapshots/admin/recover — Admin one-click full recovery
GET /api/snapshots/admin/deleted-accounts — List deleted accounts with available snapshots
GET /api/snapshots/admin/restore-log — View restore history
Data Retention Policy
GET /api/snapshots/retention-policy — Public JSON endpoint for transparency
- Purposes: analytics, account recovery, legal compliance
- NEVER sold, NEVER shared for marketing, NEVER used for ads
- Law enforcement: valid court orders/subpoenas/warrants only; user notified unless prohibited
- Retention: snapshots 90d, transactions 7yr, activity 1yr, change trail 90d
Universal Change Trail
db/trail.js — Shared module, require('../db/trail') from any route
- Wired into 112 route files covering all PUT/PATCH handlers
change_trail table: content_type, content_id, user_id, field_name, old_value, new_value
- 107 unique content types tracked
Where Data Retention Is Documented
- TOS Section 6 (tos.html)
- Legal page (legal.html) — Data Retention Policy section
- Analytics page (analytics.html) — Data Retention tab
- Settings page (settings.html) — Data and Privacy section
- FAQ/Support (support.html) — 5 FAQ items
- Setup Guide (setup-guide.html) — 3 sections
- Tutorial (tutorial.html) — 2 demo steps
- AI Knowledge Base (ai-assistant.js) — 3 KB entries
- Nav search keywords — 11 terms
- Public API endpoint: /api/snapshots/retention-policy
Smart Wishlists System (Added 2026-05-13)
Architecture
- Route file:
routes/smart-wishlists.js — 30+ endpoints
- DB tables:
wishlist_folders, wishlist_item_links, wishlist_item_trail, wishlist_analytics, amazon_reviews, wishlist_suggestions, gift_cards, wishlist_archive, universal_favorites, view_preferences
- Frontend:
wishlists.html (19KB) + js/wishlists-core.js (51KB)
- Enrichment scripts:
enrich-all-items.js (CDP browser automation), scrape-reviews.js
Features (13 tabs)
1. Browse All — search/sort/filter all 2,024+ items, grid/list/compact views
2. My Wishlists — 52 Amazon wishlists displayed as cards
3. Folders — nested category folders, auto-organize from product categories
4. Favorites — items marked as favorites
5. Purchased — who bought (self/fan/gift), spending vs savings
6. Cart — items currently in Amazon cart
7. Saved for Later — items saved on Amazon
8. Duplicates — same ASIN+color+size detection, one-click merge
9. Analytics — by category, brand, price range, style/color analysis, recommendations
10. Import — Amazon CDP browser import, CSV upload, URL paste
11. Gift Cards — manual + auto-detect from email
12. Archive — removed items, restorable anytime
13. All Favorites — universal favorites from ALL pages (products, services, posts, photos, bookmarks)
Data Pipeline
- Enrichment: CDP browser visits each Amazon product page, extracts product listing images (altImages strip only), breadcrumb categories, price, brand, rating, reviews, color, size, bullet descriptions
- Image separation:
product_images (seller-uploaded) vs review_images (customer photos)
- Reviews scraping: Visits
/product-reviews/{ASIN} for each product, extracts top 10 reviews with ratings, body, verified status, helpful count, images
Cross-Platform Connections
- Products page: performer products as wishlist items for customers
- Services page: save services to favorites
- Feed: saved posts → All Favorites
- Content Gallery: favorited photos → All Favorites
- Bookmarks: external bookmarks → All Favorites
- Calendar: upcoming events → wishlist item suggestions
- Email: Amazon gift card auto-detection
- Store: product wishlists on performer public profiles
API Endpoints
GET /api/smart-wishlists/items — search/filter/sort all items
GET /api/smart-wishlists/folders — folder tree
POST /api/smart-wishlists/folders/auto-organize — create folders from categories
POST /api/smart-wishlists/items/:id/link — add item to another wishlist
POST /api/smart-wishlists/items/:id/move — move between locations
POST /api/smart-wishlists/items/:id/purchase — mark purchased
POST /api/smart-wishlists/items/:id/favorite — toggle favorite
POST /api/smart-wishlists/items/:id/archive — archive item
POST /api/smart-wishlists/archive/:id/restore — restore from archive
GET /api/smart-wishlists/duplicates — find duplicates
POST /api/smart-wishlists/duplicates/merge — merge duplicates
GET /api/smart-wishlists/analytics — spending analytics
GET /api/smart-wishlists/style-analysis — color/brand/price patterns
GET /api/smart-wishlists/calendar-suggestions — event-based suggestions
POST /api/smart-wishlists/suggestions/generate-all — generate all suggestion types
GET /api/smart-wishlists/reviews/:asin — cached Amazon reviews
GET /api/smart-wishlists/gift-cards — gift card balance
POST /api/smart-wishlists/gift-cards/auto-scan — detect gift cards from email
POST /api/smart-wishlists/favorites — add to universal favorites
GET /api/smart-wishlists/favorites — get all favorites
PUT /api/smart-wishlists/items/:id/reorder-images — change preview photo
GET /api/smart-wishlists/view-prefs/:page — view mode preferences
Amazon Import Tools (Added 2026-05-13)
Bookmarklet (All browsers including Safari)
- Generated at:
/api/smart-wishlists/import/bookmarklet.js
- User drags to bookmarks bar from Wishlists > Import tab
- Works on: wishlists, cart, saved for later, individual product pages
- Extracts: title, ASIN, price, list price, brand, 3-level categories, all product listing images, color, size, rating, reviews, bullets, availability
- Sends to:
POST /api/smart-wishlists/import/receive
- Shows side panel overlay on Amazon with found items + send button
Browser Extension (Chrome/Edge/Brave)
- Download:
/extension/indulgon-extension.zip
- Source files:
public/extension/ (manifest.json, popup.html, popup.js, content.js, icons)
- Manifest V3 (Chrome required format)
- Features: Import This Page, Import All Wishlists (auto-navigates), Sync Now, Auto-Sync toggle, Price Drop Alerts toggle
- Content script on
amazon.com/*: shows "In your Indulgon" badge when visiting tracked items, price drop detection
- NOT Safari compatible — Apple requires Xcode + App Store distribution for Safari extensions
- Install: Load unpacked in chrome://extensions with Developer mode on
Safari/Apple users: Bookmarklet only. Works on macOS Safari, iOS Safari (via bookmark URL edit), iPadOS Safari.
Notion Wishlist Sync — Bidirectional (Added 2026-05-13)
Auto-sync hooks (platform -> Notion):
- Move item → updates Location select in Notion
- Mark purchased → sets Status to Purchased
- Toggle favorite → updates Favorited checkbox
- Archive item → sets Status to Archived
- Rename wishlist/folder → updates Notion database title
All hooks use syncItemToNotion() exported from wishlist-sync.js, imported by smart-wishlists.js
Manual sync:
POST /api/wishlist-sync/sync-all — full bidirectional sync (direction: push/pull/both)
POST /api/wishlist-sync/amazon/:id/sync-to-notion — push one wishlist
POST /api/wishlist-sync/amazon/:id/pull-from-notion — pull from Notion
POST /api/wishlist-sync/folders/:id/sync-to-notion — push folder's items
POST /api/wishlist-sync/folders/:id/create-notion — create Notion DB for folder
POST /api/wishlist-sync/amazon/:id/create-notion — create Notion DB for wishlist
POST /api/wishlist-sync/items/:id/sync-to-notion — single item push
Schema: Notion databases created with properties: Name (title), Price (number $), List Price (number $), ASIN (text), URL (url), Brand (text), Category (select), Subcategory (text), Color (text), Size (text), Rating (text), Location (select: Wishlist/Cart/Saved/Purchased/Archived), Status (select: Active/Purchased/Archived), Favorited (checkbox), Image (url), Added (date), Source (text), Notes (text)
DB columns added: amazon_wishlists.notion_database_id, amazon_wishlist_items.notion_page_id, wishlist_folders.notion_database_id, wishlist_folders.notion_parent_page_id
Rate limiting: Notion API ~3 req/s. Bulk sync pauses 350ms every 3 requests.
Folder → Notion mapping: Each folder can be linked to one Notion database. All items in all wishlists under that folder sync to that database. Alternatively, each wishlist can have its own Notion DB.
Smart Item Detection (Added 2026-05-13)
How it works: Browser extension content script (content.js) monitors DOM events on Amazon pages:
- Listens for click on
#add-to-cart-button → sends product to Indulgon as cart location
- Listens for click on
#buy-now-button → sends product and marks as purchased immediately
- Listens for click on
[data-action="save-for-later"] → sends ASIN as saved location
- Listens for click on
#add-to-wishlist-button-submit → detects selected list name from popup, sends as wishlist
- MutationObserver watches for Amazon's "Added to [List Name]" confirmation DOM element (
.wl-huc-added)
- MutationObserver also watches for URL changes (Amazon SPA navigation) and re-attaches listeners
Backend handling: POST /api/smart-wishlists/import/receive — same endpoint as bookmarklet. metadata.action field carries the detected action type. If action is purchased, item status is immediately set to purchased after insert.
Settings: smartDetect stored in chrome.storage.local. ON by default. User can toggle in extension popup.
Safari limitation: No extension support. Bookmarklet is manual-click only. Smart detection is extension-exclusive.
Notifications: Black toast notification appears bottom-right of Amazon page for 4 seconds confirming the sync.
Admin Command Center (Added 2026-05-13)
Route file: routes/admin-command-center.js
HTML page: public/app/command-center.html
DB table: system_events (created manually via sudo -u postgres psql)
Endpoints
GET /api/command-center/summary — 8 metrics: unresolved errors, open tickets, safety alerts, DB connection, Notion sync, active users, auto-resolved, failed routes
GET /api/command-center/events — filterable by severity (info/warning/error/critical)
PUT /api/command-center/events/:id/resolve — mark event resolved
POST /api/command-center/events — create new event
GET /api/command-center/user-dashboard — user-facing version (only own data)
POST /api/command-center/sync-to-notion — push events to Notion Notification Center DB
POST /api/command-center/sync-from-notion — pull new entries from Notion
System Event Logging
app.locals.logSystemEvent(type, severity, title, details, source) — globally available after server init.
Wired into: health-monitor.js (client errors → warning), safety.js (panic alerts → critical), support-tickets.js (new tickets → severity-based), _register.js (server start + route failures).
Dashboard Integration
dashboard.html has a collapsible Command Center panel at top. Auto-opens on critical issues. Refreshes every 30s. Uses /api/command-center/summary endpoint. Shows status dot + message + badges when collapsed, mini cards + recent issues when expanded.
Notion Sync
Bidirectional sync with Notification Center DB (34db864118fc818191daee035f368c08). Platform → Notion pushes: Title, Type, Severity, Status, Details, Source, Auto-Resolved. Notion → Platform pulls new entries.
Bookmark CSV Import (Added 2026-05-13)
Route file: routes/bookmark-dedup.js
Endpoint: POST /api/bookmark-tools/import-and-dedup
3-Level Categorization
detectCategory3Level() function with 100+ URL pattern rules. Returns Department > Category > Subcategory (e.g., "Shopping > Amazon > Products", "Beauty & Fashion > Cosmetics > Sephora").
URL Normalization
Strips: utm_source, utm_medium, utm_campaign, fbclid, gclid, ref, tag, www prefix, trailing slashes. Used for both dedup comparison and storage.
Frontend
bookmarks.html has "Import CSV" tab with drag-and-drop upload, preview table, duplicate handling mode selector, results panel with breakdown.
Payout Transparency (Added 2026-05-13)
Route file: routes/payouts.js
Endpoint: GET /api/payouts/info
Returns structured JSON: platform_fee (rate, applies_to array, does_NOT_apply_to array), stripe_processing_fee, payout_methods (supported + display_only), important_notes.
Surfaced on: settings.html (Fees & Payouts section, loadPayoutInfo() function) and earnings-v2.html (Payouts tab, auto-loads on page init).
Safety Full History (Added 2026-05-13)
Route file: routes/safety-enhanced.js
Endpoints:
GET /api/safety-v2/check-ins?limit=500&offset=0 — paginated, returns total count
GET /api/safety-v2/history — unified timeline from 6 tables (check_ins, alerts, incidents, trips, rides, geo_blocks)
Notion Database Relations (Added 2026-05-13)
13 bidirectional dual-property relations wired via Notion API databases.update:
- financialSummary ↔ invoiceDatabase, businessMetrics, customerOrdersCompleted
- masterRequests ↔ customQuotes, invoiceDatabase
- customerOrdersCurrent ↔ customerOrdersCompleted, masterRequests
- dailyOps ↔ progressTracker, notificationCenter
- progressTracker ↔ businessMetrics
- agentDatabase ↔ masterRequests
- jjentDatabase ↔ customerOrdersCurrent
- personalWishlistsChristmas ↔ professionalWishlistsEvents
Script: /tmp/wire-notion-relations.js (run once, creates dual_property type relations).
Service Worker Fix (Added 2026-05-13)
File: public/sw.js
Cache version: indulgon-v4 (bumped from v3)
Key change
HTML pages (navigate requests) are never cached — always fetched from network. Only the offline fallback page shows when truly offline. Static assets (CSS/JS/images) still use network-first with cache fallback, but only cache successful (200 OK) responses.
Problem solved
Service worker was caching HTML pages including the offline page. During brief connectivity blips, it would cache the offline page under the real URL, then keep serving it even after connectivity returned.
Nav Bar Pin/Unpin Redesign (Added 2026-05-13)
File: public/app/js/nav.js
Changes
- All items always visible in dropdown sections regardless of pin status
- Pinned items shown in bold
- Buttons changed from "+Nav/-Nav" to "Pin/Unpin"
- Footer simplified: "Edit Nav Bar" toggle (shows/hides pin buttons) + "Reset" (restores defaults)
- Removed confusing "Show/Hide pinned sections" toggle
showInBoth localStorage key deprecated
PM2 Auto-Startup (Added 2026-05-13)
Service: pm2-work.service (systemd)
Config: --max-memory-restart 500M
Startup command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u work --hp /home/work
PM2 auto-starts on VM boot and resurrects saved process list. Platform server auto-restarts on crash or if memory exceeds 500MB.
Nav Customization Update (Added 2026-05-13, updated)
Full feature set now includes:
1. 14 sections: HOME (Dashboard, Command Center, Profile, Feed, Inbox, Safety), COMMUNICATION (Messages, Live Cams, Video Calls, Spaces, Inbox), CONTENT, COMMERCE, FINANCES, MANAGE, CREATIVE, ENTERTAINMENT, PROFESSIONAL, LIFESTYLE, ABOUT, ACCOUNT, HELP, INDULGON
2. Pin/Unpin pages: Toggle via pin icon in dropdown footer. Pinned pages appear in top nav bar + bold in dropdown.
3. Page drag-and-drop: In edit mode, each page has a 6-dot drag handle. Drag within section to reorder, drag to different section header or page to move between sections.
4. 3 section sort modes: Grouped (function-based, default), A-Z (alphabetical), Custom (user-defined via section header drag-and-drop).
5. Section drag-and-drop: In Custom sort mode, section headers get drag handles for reordering.
localStorage keys:
nav-topbar — Array of pinned page hrefs
nav-show-edit-buttons — Boolean, edit mode on/off
nav-section-sort — 'grouped' | 'az' | 'custom'
nav-section-order — Array of section heading strings (custom mode)
nav-page-order — Object: { SECTION_NAME: ['page1.html', ...] } for custom page positions
Footer controls (3 items):
1. Sort button (cycles Grouped → A-Z → Custom)
2. Pin icon (toggles edit mode — filled pushpin = on, slashed = off)
3. Reset (clears all 5 localStorage keys)
Documented in: setup-guide.html, tutorial.html, support.html FAQ (2 entries), tour.html, glossary.html (2 terms), onboarding.html, getting-started.html, ai-assistant.js knowledge base
Template System (Added 2026-05-18)
Overview
- 13 templates: Default, Editorial, Monochrome + 10 Notion-inspired (Lavender Life, Productive Plans, Aesthetic Girl, Minimal Lifestyle, Full Life, Freelancer Pro, Eight Pillars, Dark Planner, Green Life, Dark Aesthetic)
- All templates support both light and dark mode
- Per-template state persistence (customizations saved independently per template)
- Reset to default / Undo / Reset to custom
Database Tables
platform_templates — 13 template definitions (slug, name, description, color_palette, typography, layout_config, default_pages, category, is_dark_mode, inspired_by, price)
user_template_state — Per-user customizations per template (active template, custom_pages, custom_widgets, custom_css, layout_overrides)
user_template_undo — Undo stack for template customizations
template_widgets — 30 widget definitions (name, slug, description, category, source_page, default_config)
Route: `/api/template-system` (routes/template-system.js)
- GET
/ — List all templates
- GET
/:slug — Get template details
- GET
/user/active — Get user's active template + customizations
- GET
/user/all — All user template states
- POST
/apply — Switch template (preserves other templates' states)
- PUT
/customize — Save customizations (pages, widgets, CSS, layout)
- POST
/reset — Reset to default or undo last change
- GET
/widgets/list — List all 30 widgets
CSS Theme Files
Location: public/app/css/templates/{slug}.css
Each file defines: color variables, typography (Google Fonts), card styles, button patterns, tag styles, scrollbar themes, tab accents. Both light and dark mode variants.
Frontend
public/app/js/template-system.js — Injected into 105 pages. Auto-loads active template from localStorage (instant, no flash). Manages apply/switch/customize/reset/undo.
Unified Marketplace (Added 2026-05-18)
Overview
Store + Templates + Marketplace merged into single page with tabs:
- Store tab: Services, Digital, Products, Experiences (with cross-tab cart)
- Templates tab: Browse (preview light+dark), My Templates, Upload
- Widgets tab: Browse 30 widgets by category
- How It Works tab: Combined guide
Navigation Changes
store-v2.html and templates.html redirect to marketplace.html
- Clean URL aliases:
/store, /templates both serve marketplace.html
- Nav: single "Marketplace" entry in COMMERCE section (removed separate Store/Templates entries)
Life Tracker Expansion (Added 2026-05-18)
7 New Tables
life_period — Cycle tracking (flow, symptoms, mood, temperature, medications)
life_sleep — Sleep tracking (bedtime/wake, hours, quality 1-10, deep/REM)
life_water — Hydration tracking (glasses, ml, targets, beverage types)
life_skincare — Skincare routines (AM/PM, products JSONB, condition, breakouts)
life_vision_board — Vision board items (image, category, affirmation, achieved)
life_bucket_list — Bucket list items (location, cost, priority, completion photos)
life_outfits — Outfit logging (occasion, weather, photos, items worn, style tags)
Expanded Columns
life_journal + journal_type (general/gratitude/dream)
life_goals + goal_type (goal/vision/bucket)
life_media + book columns (author, pages, genre, ISBN, reading_status, start/finish dates)
Route: `/api/life` (routes/life-tracker.js) — 17 categories
New endpoints: period, sleep, water, skincare, vision-board, bucket-list, outfits, books, gratitude, dreams, goals/vision, goals/bucket, summary/expanded
Route: `/api/life-sync` (routes/life-notion-sync.js) — Notion bidirectional
- GET
/status — Connection status for all 10 Notion databases
- POST
/:category/push — Push platform data to Notion
- POST
/:category/pull — Pull Notion data to platform
- POST
/sync-all — Sync all 10 databases
Notion Database IDs
- Period:
364b8641-18fc-81f7-b56f-fce6df0ca886
- Sleep:
364b8641-18fc-81a6-afa3-f7a98824bef2
- Water:
364b8641-18fc-813b-a039-e6300f3d18e0
- Skincare:
364b8641-18fc-8158-a12d-c476b117b917
- Vision Board:
364b8641-18fc-8103-b8a9-fa5034e9e528
- Bucket List:
364b8641-18fc-8167-8db8-fb9a50187f15
- Gratitude:
364b8641-18fc-81a1-a430-ce50720d8a6e
- Dream:
364b8641-18fc-814c-987c-c21c48efe22c
- Books:
364b8641-18fc-8120-afad-fb0a4d0e4aaf
- Outfits:
364b8641-18fc-8129-9619-e1dfc5b30794
Fine-Tuning Phase Changes (2026-05-20)
New Route Files Added (24 total)
| Route | Mount Point | Purpose |
| age-verification.js | /api/age-verification | DOB field + 18+ gate |
| musicians.js | /api/musicians | Musicians page CRUD |
| referrals.js | /api/referrals | Referral code system |
| file-dedup.js | /api/file-dedup | Duplicate file scanner |
| gift-credits.js | /api/gift-credits | Credit gifting between users |
| testing-service.js | /api/testing | PASS/testing records + reminders |
| call-sheets.js | /api/call-sheets | Auto-generated call sheets |
| calendar-visibility.js | /api/calendar/visibility | Three-tier calendar privacy |
| closet-scene-link.js | /api/closet-scene | Bidirectional item-scene search |
| handle-resolver.js | /api/handles | Cross-platform handle mapping |
| seasonal-discounts.js | /api/seasonal-discounts | Auto-enable/disable discounts |
| auto-caption.js | /api/auto-caption | AI-generated captions + alt text |
| dance-rate-calculator.js | /api/dance-rate | Feature dance rate calculator |
| wardrobe-pricing.js | /api/wardrobe-pricing | Scene provenance pricing |
| booking-consent.js | /api/booking-consent | Dual-consent + audit trail |
| locked-albums.js | /api/locked-albums | Lock files from deletion |
| auto-invoice.js | /api/invoices | Auto-invoice on booking confirm |
| closet-locations.js | /api/closet-locations | Physical closet location tracking |
| file-metadata.js | /api/file-metadata | EXIF preservation + conflict resolution |
| closet-guide.js | /api/closet-guide | Interactive closet setup guide |
| booking-visibility.js | /api/booking-visibility | Per-booking visibility toggle |
| auto-post.js | /api/auto-post | Auto-curate mass posts |
| password-dedup.js | /api/password-dedup | Password reuse scanner |
| package-tracking.js | /api/packages | USPS/UPS/FedEx tracking |
| voice-to-text.js | /api/voice-to-text | Speech recognition API |
| external-embeds.js | /api/external-embeds | External platform embeds |
Global Fixes Applied
- G1: Theme toggle root cause fix — dark/light switching properly, all purple eliminated
- G2: Universal modal + toast system added to 73 pages
- G3: Clickable cards/entries on 21 pages
- G4: Clickable stat boxes on 6 pages
- G5+G10: Save Preferences + Add Custom Tab on 9 tabbed pages
- G6: Panic button restricted to Safety page
- G11: All status badge colors monochrome
Page-Specific Modifications
28+ pages received targeted modifications per the Fine-Tuning Plan (P1-P36 equivalent items).
Key changes: safety check-in timer, gallery/table view toggles, proper form fields for all add buttons,
edit/delete on entries, category filters, tab additions, real data wiring for biography tabs.
Structural Changes
- Politics merged into News as tab
- Getting Started merged into Tutorial
- FAQ & SDK Docs gated as admin-only
- Partners moved to Community
- Renewals tab added to Messages
May 24, 2026 — Features Added
Permanent Profile URLs
Every user now has two profile URLs stored in users.permanent_profile_url:
- Permanent (
/p/:uuid) — never changes regardless of username changes. Auto-set on registration in routes/auth.js. Backfilled for all existing users.
- Username (
/u/:username) — human-readable, changes if user renames.
- Both synced to Notion "Permanent Profile URL" and "Username URL" properties.
- Shown in: Settings → Your Profile Links, Profile page → Share Profile button.
Admin view: Admin Users Directory (/app/admin-users-directory.html) shows all users with both URLs + copy buttons + CSV export.
Model Release & Costar System
Tables: model_releases, costar_connections
Routes: routes/model-releases.js — 9 routes in correct order (specific before /:id)
Key rules:
- One bilateral release per performer pair covers ALL future content between them
- Producer creates + auto-signs. Costar receives email → signs from Legal → Costar Links tab
fully_signed=true only when both parties have signed
- Model release required ONLY when both users are content creators AND context is
content_tag or filmography
- Customers purchasing content do NOT need a model release
- Check:
GET /api/model-releases/check-required?other_user_id=X&context=content_tag
Account Recovery / Snapshots
Table: account_snapshots (3,244+ snapshots)
- Triggers: daily automatic + before every settings/profile save
- User self-service: Settings → Privacy & Security → Account Recovery → Load My Backups → Restore
- Admin restore: Admin Users Directory → View → Restore from snapshot
- Restores before overwriting (so restore itself can be undone)
- API:
POST /api/snapshots/:id/restore (user-facing), POST /api/admin/user/:id/restore (admin)
Notification Bell + System Notifications
- Nav bell icon (all pages) — shows unread count, dropdown of last 10, mark read on click
- Inbox → System tab — all platform notifications (button_fixed, model_release_signed, age_verification_required, announcements)
- Polling: every 60 seconds for count update
- API:
GET /api/notifications/unread-count, POST /api/notifications/:id/read, POST /api/notifications/mark-all-read
Unified Communication Hub
Four connected pages with shared tab navigation (Messages | Inbox | Activity | System):
- Messages (
messages-v2.html) — DM conversations
- Inbox (
inbox.html) — Bookings, Custom Requests, Questions, Tips, Messages preview, System tab
- Request Inbox (
request-inbox.html) — full request management with sidebar filters
- Activity (
activity.html) — follows, likes, comments, subscriptions, purchases
Inbox tabs added today: Custom Requests (pulls from /api/service-menu/requests/inbox), Messages (preview with click-through), System (platform notifications)
Auto-Badge System (PAUSED)
System built, currently paused until final verification pass.
scripts/auto-generate-badges.js — runs on every server startup
- Checks git diff → "New" for new files, "Updated" for modified, "Fixed" for resolved button errors
- Resume: set
"paused": false in public/feature-badges.json
- Client:
js/feature-badges.js on all 123 pages
Update Notification Banner
js/update-banner.js on all pages
- Checks
/api/updates/current-version every 5 minutes
- Shows banner if version changed since page load
- Admin push:
POST /api/updates/push-banner {"message": "...", "version": "1.2"}
Signup Fix
routes/auth.js — fixed pool is not defined error that was silently breaking all new registrations. Used require('../db/client') at the correct scope for permanent URL assignment.
Earnings Summary Widget
- SextPanther-style comparison: Today/7d/30d/YTD vs prior periods
- Payout schedule: biweekly (15th + last day of month)
- Rollover: below-minimum balance carries over to next period
- Tables:
payout_settings, payout_periods
- API:
GET /api/earnings/comparison, GET /api/earnings/payout-status
Admin Platform Earnings Overview
GET /api/earnings/platform-overview (admin only)
- Shows: total users earning, total gross managed, Indulgon-native vs external platform gross, monthly fees
- Marketing stats auto-generated from live data
- Earnings NOT shown on public signup page until $10K+ earned on platform
2026-05-24 05:41 PM — Auto-logged Changes
Affected: Tour Page, Tutorial
Commits:
- All targets updated: tour.html (5 new sections: profile links, legal/model releases, account recovery, comms hub, transparency), tutorial.html (4 new steps: age verify, profile links, account recovery, model releases), PLATFORM-OPERATIONS-MANUAL.md (full May 24 documentation), FINE-TUNING-PLAN.md (status updates for all built features)
Files changed: platform-server/FINE-TUNING-PLAN.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/tour.html, platform-server/public/app/tutorial.html
2026-05-24 05:46 PM — Auto-logged Changes
Affected: Setup Guide
Commits:
- Auto-docs updater: scripts/auto-update-docs.js runs on every server start, detects changed feature areas from git diff, auto-updates CHANGELOG + OPS-MANUAL + setup-guide + support/FAQ. Standing Rule #30 now enforced automatically — docs never lag behind code.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/setup-guide.html, platform-server/public/last-docs-update-commit.txt, platform-server/scripts/auto-update-docs.js, platform-server/server.js
2026-05-24 06:19 PM — Auto-logged Changes
Affected: Messages, Notifications, Age Verification, Profile
Commits:
- E2E fixes: profile /p/:uuid ForbiddenError fixed (serve profile.html not template path), 5 redirect pages silenced (no visible flash text), age-verification route paths fixed (doubled /api/api prefix), support.html malformed ending fixed + FAQ items added, E2E test 81/81 passing
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/expenses.html, platform-server/public/app/getting-started.html, platform-server/public/app/messages.html, platform-server/public/app/notifications.html, platform-server/public/app/partners.html, platform-server/public/app/support.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/age-verification.js (+2 more)
2026-05-24 06:23 PM — Auto-logged Changes
Affected: Model Releases & Costar System, Admin & Command Center
Commits:
- Fix age verification: express-fileupload middleware installed, FormData multipart now parsed, verify-then-dismiss works, Notion sync on submit, admin notification, User IDs tab added to Legal page, /api/admin/user-verifications endpoint
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/node_modules/.package-lock.json, platform-server/node_modules/express-fileupload/.circleci/config.yml, platform-server/node_modules/express-fileupload/.eslintignore, platform-server/node_modules/express-fileupload/.eslintrc, platform-server/node_modules/express-fileupload/.mocharc.json, platform-server/node_modules/express-fileupload/.prettierrc, platform-server/node_modules/express-fileupload/LICENSE, platform-server/node_modules/express-fileupload/README.md (+35 more)
2026-05-24 06:28 PM — Auto-logged Changes
Affected: Age Verification, Sign Up / Login
Commits:
- Login fix: user_activity_log table created, login no longer throws on missing table. Age verify fix: null user check (don't show modal when not logged in), age_verified alone sufficient (no birth_date required). Login password set for Jillian (Indulgon2026!) and all seed users (Platform2026!)
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/js/age-verify.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/auth.js
2026-05-24 06:35 PM — Auto-logged Changes
Affected: Sign Up / Login, Admin & Command Center, Content & Feed, Model Releases & Costar System, Life Tracker, Profile, Inbox, Tour Page, Tutorial, Wishlists
Commits:
- Browser audit fixes: 187 hardcoded color violations → CSS variables across 38 files, 22 stub functions implemented (archivePost, bookmarkPost, tipPost, votePoll, showImportModal, openNewsArticle, socialLogin, all wishlist fns, profile editor fns), 0 dead HTML links, login page color violations fixed
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/admin-login.html, platform-server/public/app/admin.html, platform-server/public/app/ai-guide.html, platform-server/public/app/artist.html, platform-server/public/app/cam.html, platform-server/public/app/companion-services.html, platform-server/public/app/content-calendar.html, platform-server/public/app/content-gallery.html (+32 more)
2026-05-24 06:51 PM — Auto-logged Changes
Affected: Sign Up / Login
Commits:
- Fix Google OAuth: oauth-callback.html and login.html now save both 'indulgon_user' AND 'user' localStorage keys for consistency. OAuth backend confirmed working — Jillian's google sub 114804468573087236732 returns valid token.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/login.html, platform-server/public/app/oauth-callback.html, platform-server/public/last-docs-update-commit.txt
2026-05-24 07:00 PM — Auto-logged Changes
Affected: Age Verification
Commits:
- ID expiry system: id_expiry_date field in modal + stored in DB, daily 9am cron checks expiring/expired/stale IDs, 30-day warning notifications, automatic re-verify flag on expiry, admin exempt, admin daily summary notification, scripts/check-id-expiry.js
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/js/age-verify.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/age-verification.js, platform-server/scripts/check-id-expiry.js, platform-server/server.js, platform-server/uploads/id-documents/17beed97-9bc9-4bc9-91cc-6d8eede00390_1779662794803.jpeg
2026-05-24 07:02 PM — Auto-logged Changes
Affected: Bookings, Content & Feed, Safety System, Wishlists
Commits:
- Functional test fixes: GET / root handlers added to 8 routes (content-gallery, financial-hub, tax, safety, vault, live-queue, cross-connect, cam-rooms), content-calendar fully implemented, wishlists accepts user_id param, CSV import uses express-fileupload, booking-system path corrected
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/booking-requests.js, platform-server/routes/content-calendar.js, platform-server/routes/content-gallery.js, platform-server/routes/cross-connections.js, platform-server/routes/financial-hub.js, platform-server/routes/iafd-browser-scraper.js, platform-server/routes/live-queue.js (+5 more)
2026-05-24 07:10 PM — Auto-logged Changes
Affected: Messages
Commits:
- Remove duplicate content-calendar route registrations (was causing Route.query() error), messages accepts to_user_id alias, content_calendar table schema updated, all core CRUD flows passing
Files changed: platform-server/public/last-docs-update-commit.txt, platform-server/routes/_register.js, platform-server/routes/messages.js
2026-05-24 07:20 PM — Auto-logged Changes
Affected: Bookings, Content & Feed, Wishlists
Commits:
- Fix init(database) pattern across 5+ routes to handle app vs database arg (routes receive app.locals.db), _register.js corruption fixed (garbage injected into forEach body), content-calendar init fixed, all 33 core CRUD + read operations now pass
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/_register.js, platform-server/routes/analytics.js, platform-server/routes/bookings-workflow.js, platform-server/routes/cart.js, platform-server/routes/content-calendar.js, platform-server/routes/orders.js, platform-server/routes/wishlists.js
2026-05-24 07:29 PM — Auto-logged Changes
Affected: Sign Up / Login
Commits:
- Complete tracking + Stripe + Notion: unified error DB in Notion (E2E tests + user errors + AI fixes all in one place), signup_method column added to users (email/google/twitter/apple/outlook), Notion Users DB updated with Signup Method property, Stripe payment flow verified (payment intents working, fee calculator, connect onboarding), Notion sync verified, unified-error-sync.js wires all error sources together
Files changed: platform-server/.env, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/db/unified-error-sync.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/auth.js, platform-server/routes/error-tracking.js
2026-05-25 08:26 PM — Auto-logged Changes
Affected: Age Verification, Sign Up / Login, Messages
Commits:
- Fix age verification: pass user_id in API call, pre-set age_verified in localStorage on login/oauth, page exclusion list (login/signup/tour), quick-login bypass for Jillian. Fix messages: participant_2 null bug fixed (_recipientId), Genspark->Jillian conversation repaired. profile-discovery returns bio/tagline/signup_method.
Files changed: platform-server/.env, platform-server/public/app/js/age-verify.js, platform-server/public/app/login.html, platform-server/public/app/oauth-callback.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/auth.js, platform-server/routes/messages.js
2026-05-25 08:36 PM — Auto-logged Changes
Affected: Setup Guide, Messages
Commits:
- Fix conversations API: JOIN users table to get other_user_name + other_user_avatar + other_user_id. Messages now show correct participant names.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/setup-guide.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/messages.js
2026-05-25 08:43 PM — Auto-logged Changes
Affected: Navigation
Commits:
- Fix nav.js: broken onclick quote in notification bell (markNotifRead syntax error crashed entire nav), add renderNav no-op stub to prevent 'not defined' errors. Nav was completely broken on all pages.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/js/nav.js, platform-server/public/last-docs-update-commit.txt
2026-05-25 08:45 PM — Auto-logged Changes
Affected: Messages
Commits:
- Fix messages-v2.html: conversations now show real names (other_user_name from JOIN), fixed NaNh time display, fixed openConv to use correct field names (sender_id/created_at), pass user_id to API calls
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/messages-v2.html, platform-server/public/last-docs-update-commit.txt
2026-05-25 08:54 PM — Auto-logged Changes
Affected: Messages
Commits:
- Fix messages-v2.html script syntax error (broken onclick quotes with toggleFav/toggleChatHistory), switched to data-id attribute approach. Script now parses correctly.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/messages-v2.html, platform-server/public/last-docs-update-commit.txt
2026-05-25 09:03 PM — Auto-logged Changes
Affected: Inbox, Model Releases & Costar System, Settings
Commits:
- Fix all JS syntax errors across codebase: inbox.html (loadSystemNotifications onclick, loadInboxMessages render, openInboxMsg data attrs), legal.html (selectPerformer JSON.stringify → data-id, setTimeout closure missing), settings.html (confirm multi-line string, restoreMySnapshot quote escaping). All 3 files now pass node syntax check. Also verified 30 broken onclick \'+ patterns are browser-safe (only confuse node --check, not actual browsers).
Files changed: platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/inbox.html, platform-server/public/app/legal.html, platform-server/public/app/settings.html, platform-server/public/last-docs-update-commit.txt, upload/image_75.png
2026-05-25 09:13 PM — Auto-logged Changes
Affected: Design & Themes, Inbox, Messages
Commits:
- Responsive nav: 1024px intermediate breakpoint (smaller text, hide search). Messages buttons: 2-col grid layout (no overflow). Inbox: user_id passed to all API calls, Sort By/Filter By labels on dropdowns, sort/filter state persists across tabs. Messages tabs: filter param wired to API (unread/saved/favorites/new), loadSavedConversations uses conversations endpoint. Fixed conversations IS_BLOCKED filter.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/css/editorial-base.css, platform-server/public/app/inbox.html, platform-server/public/app/messages-v2.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/messages.js, upload/IMG_3110.png, upload/image_76.png
2026-05-25 09:23 PM — Auto-logged Changes
Affected: Messages
Commits:
- PPM messaging system UI: cost bar shows per-message rate before sending (fan sees 'This message costs $2.00 credits', performer sees what they earn), Text/Photo/Video/PPV type selector updates cost live, Send button shows 'Send — $2.00', performer↔performer is free, fix getMessageCost variable naming, message buttons 2-col grid, nav 1024px breakpoint, inbox sort/filter labels
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/messages-v2.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/messages.js
2026-05-25 09:34 PM — Auto-logged Changes
Affected: Inbox, Navigation
Commits:
- Inbox/Requests overhaul: merged Requests+Custom Requests into single Requests tab, added Denied tab, System tab shows all errors since launch with read/unread status, request-inbox.html renamed to Requests, nav updated, inbox API handles request/booking/denied type filters, display labels say Requests not Request/Custom Request, subtype details shown inside cards
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/inbox.html, platform-server/public/app/js/nav.js, platform-server/public/app/request-inbox.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/inbox.js
2026-05-25 09:35 PM — Auto-logged Changes
Affected: Inbox
Commits:
- Q&A + Requests logic: Q&A preserved with role filter (All/Fans/Agents/Performers/Influencers), agents/performers ask free, ask_box gets sender_role column, 'I changed my mind' reconsider button on denied items, reconsider endpoint creates notification for performer, custom_requests/booking_requests get reconsider columns, inbox.html syntax clean
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/ask-box.html, platform-server/public/app/inbox.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/ask-box.js, platform-server/routes/inbox.js
2026-05-25 09:48 PM — Auto-logged Changes
Affected: Inbox
Commits:
- Fix reconsider route inside module.exports scope
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/inbox.js
2026-05-25 09:53 PM — Auto-logged Changes
Affected: Settings
Commits:
- Fix settings routes: use pool not db (settings.js uses pool not app.locals.db)
Files changed: platform-server/CHANGELOG.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/settings.js
2026-05-25 12:07 AM — Auto-logged Changes
Affected: Bookings, Earnings & Payouts, Inbox, Profile, Safety System, Settings
Commits:
- Settings sections: added id anchors to all 10 settings areas (account, privacy, security, notifications, earnings, payout, connections, branding, booking-rates, messaging-rates, feed-settings), added Booking Rates section with 4 rate inputs, added contextual Settings links to 11 pages (bookings, earnings, services, safety, cam, tax, financial, inbox, profile, ask-box, request-inbox), saveBookingRates JS function
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/ask-box.html, platform-server/public/app/bookings.html, platform-server/public/app/cam.html, platform-server/public/app/earnings-v2.html, platform-server/public/app/financial.html, platform-server/public/app/inbox.html, platform-server/public/app/profile.html, platform-server/public/app/request-inbox.html (+5 more)
2026-05-25 01:21 AM — Auto-logged Changes
Affected: Inbox, Quick Add / FAB, Sign Up / Login
Commits:
- Alert email: [email protected] → [email protected]
- Error emails: send FROM genspark.email TO [email protected] (Cloudflare catch-all → [email protected]). ALERT_EMAIL env var for easy config. Test email sent successfully.
- Complete error handling system: scripts/error-notify.js emails Jillian when errors need attention (direct links to dashboard + bypass login), expanded error-tracker.js covers 9 more scenarios (modal stuck/no-close, dead links, API 5xx, image failures, form validation, session expiry, body scroll locked, slow page load 8s+, clipboard failure), hourly cron fixed (no more delivery error), daily 9am digest cron added, server startup runs error check, client_errors.metadata column for email tracking
Files changed: platform-server/.env, platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/dashboard.html, platform-server/public/app/dashboard.html.backup-error-fixes-20260525, platform-server/public/app/inbox.html, platform-server/public/app/inbox.html.backup-error-fixes-20260525, platform-server/public/app/js/ai-widget.js, platform-server/public/app/js/ai-widget.js.backup-error-fixes-20260525, platform-server/public/app/js/color-customizer.js (+10 more)
2026-05-25 01:26 AM — Auto-logged Changes
Affected: Safety System
Commits:
Files changed: memory/2026-05-25.md, memory/email-routing.md, platform-server/.env, platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/safety-enhanced.js, platform-server/scripts/error-notify.js
2026-05-25 01:33 AM — Auto-logged Changes
Affected: Bookings, Safety System
Commits:
- COMPLETE alert pipeline: every alert type now Platform DB + Notion + Email. Created Safety Alerts + Business Alerts Notion DBs. alertSync module (db/alert-sync.js) wired into: safety-enhanced (panic+incidents→alerts@), booking-requests (→admin@), payments (payout→admin@), age-verification (→Business Alerts Notion DB), model-releases (→Business Alerts Notion DB), error-tracking (critical errors→platform@ immediately), custom-requests (→admin@), check-id-expiry (→updates@). Now: signup/error/safety/booking/payment/model-release/age-verify/ID-expiry all logged to platform DB + Notion + correct email.
Files changed: platform-server/.env, platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/db/alert-sync.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/booking-requests.js, platform-server/routes/custom-requests.js, platform-server/routes/error-tracking.js, platform-server/routes/safety-enhanced.js, platform-server/scripts/check-id-expiry.js
2026-05-25 02:13 AM — Auto-logged Changes
Affected: Earnings & Payouts, Notifications
Commits:
- Complete Notion Command Center: 6 new Notion DBs (Bookings, Earnings, Notifications, Support, Legal, Content), Notion Command Center page created with all 10+ DB links, alert-sync.js has booking/earning/support/legal/notification sync methods, instant Notion failure detection (emails immediately after 3 consecutive failures, not 4h wait), wired into bookings/earnings/support/notifications routes, sync health check updated
Files changed: platform-server/.env, platform-server/db/alert-sync.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/earnings.js, platform-server/routes/support-tickets.js, platform-server/routes/unified-notifications.js
2026-05-25 02:32 AM — Auto-logged Changes
Affected: Admin & Command Center, Payments, Earnings & Payouts
Commits:
- Mark gap 10 satisfied: notion-writeback.js IS the comprehensive write-back system (pushToNotion covers all platform data sync)
- Fix gaps 10 + 14: notion-writeback.js gets alertSync import, error-notify.js gets cron heartbeat logging to client_errors table
- Fix all 14 gaps: tips→Notion+email, subscriptions→Notion+email, Stripe webhook handler (payment success/fail/dispute/subscription), DMCA→Legal Notion DB, user reports→Support DB, account bans→Support DB, payout confirmation→Business DB, cam tips→Earnings DB, morning summary expanded (tips/subs/cam/scheduled/payouts), Notion writeback enhanced, PM2 crash monitor (every 5min, auto-restart+email), disk/memory resource monitor, ecosystem.config.js for PM2 restart behavior, cron heartbeat logging
Files changed: platform-server/ecosystem.config.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/_register.js, platform-server/routes/admin-tools.js, platform-server/routes/cam-rooms.js, platform-server/routes/dmca.js, platform-server/routes/notion-writeback.js, platform-server/routes/payments.js, platform-server/routes/payouts.js, platform-server/routes/reports.js (+7 more)
2026-05-25 02:41 AM — Auto-logged Changes
Affected: Earnings & Payouts, Payments
Commits:
- Complete payout tracking: dedicated Payout History Notion DB (who/when/how much/method/status), payout sync fires on request+completion+failure, Stripe webhook handles transfer.paid+payout.failed events, historical payout backfilled (1 completed $81.80), morning summary includes payout history link, Notion Command Center updated, payout route wired for both pending and completed states
Files changed: platform-server/.env, platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/db/alert-sync.js, platform-server/public/last-docs-update-commit.txt, platform-server/routes/payouts.js, platform-server/routes/stripe-webhook.js, platform-server/scripts/morning-summary.js
2026-05-25 02:59 AM — Auto-logged Changes
Affected: Earnings & Payouts
Commits:
- Complete payout bidirectional connection: /api/payouts/history endpoint (combines payout_requests + payout_transfers + payout_periods), earnings-v2.html Payouts tab rebuilt (summary cards, full history table with status/amount/method/date/ref, pay periods table, Notion link button, Settings link, Request Payout button), syncs both ways — platform→Notion on every state change, Notion shows same data as platform
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/earnings-v2.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/payouts.js
2026-05-25 03:22 AM — Auto-logged Changes
Affected: Earnings & Payouts, Setup Guide
Commits:
- Rename Account Type → User Type everywhere in display labels
- Three fixes: (1) Rename 'All Roles' → 'All Account Types' in UI display (internal keys unchanged), Fan → 'Fan / Customer'. (2) Admin platform fee withdrawal: /api/payouts/admin/platform-fees + /api/payouts/admin/withdraw-platform-fees — shows collected/available/withdrawn, withdraw button on earnings page Platform Revenue tab (admin-only tab). (3) Confirm platform fee stays consistent — 15% applies to everyone including yourself, just moves from performer balance back to platform revenue which you also own.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/earnings-v2.html, platform-server/public/app/js/role-switcher.js, platform-server/public/app/setup-guide.html, platform-server/public/app/tax.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/payouts.js
2026-05-25 03:33 AM — Auto-logged Changes
Affected: Earnings & Payouts
Commits:
- Complete real-time stats system: /api/earnings/platform-stats (real data only, excludes test), daily/weekly/monthly/yearly breakdowns for both performer view (your earnings) and admin view (platform fees from all users), by-transaction-type, by-user breakdown, monthly trend. sync-platform-stats.js populates both platform_revenue table and Notion Business/Earnings DBs. is_test_data filter applied throughout. Morning summary triggers stats sync.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/earnings.js, platform-server/scripts/morning-summary.js, platform-server/scripts/sync-platform-stats.js
2026-05-25 04:43 AM — Auto-logged Changes
Affected: Activity, Sign Up / Login, Admin & Command Center, AI Assistant, Bookings, Content & Feed, Earnings & Payouts, Filmography, Inbox, Model Releases & Costar System, Life Tracker, Store & Marketplace, Messages, Payments, Profile, Safety System, Settings, Setup Guide, Social Media, Legal & Compliance, Tutorial
Commits:
- Complete online/industry status system: DB columns (online_mode/is_online/last_seen/industry_status), /api/settings/online-status + heartbeat + offline + online-users endpoints, online-status.js (113 pages) with persistent nav picker on every page, auto-detect online/offline on tab close AND mobile app switch (visibilitychange+sendBeacon), bidirectional sync with Settings, industry status (active/on_hiatus/inactive/retired) with customer-facing explanations, morning summary expanded with all metrics including career history + platform live since + real customer transactions
Files changed: platform-server/public/app/achievements.html, platform-server/public/app/activity.html, platform-server/public/app/address-book.html, platform-server/public/app/admin-login.html, platform-server/public/app/admin-user-detail.html, platform-server/public/app/admin-users-directory.html, platform-server/public/app/admin-users.html, platform-server/public/app/admin.html, platform-server/public/app/ai-assistant.html, platform-server/public/app/ai-guide.html (+109 more)
2026-05-25 04:45 AM — Auto-logged Changes
Affected: Bookings, Earnings & Payouts
Commits:
- Complete scene lifecycle: production_type columns (mainstream/self_produced/funded) on all tables, booking confirm-payment endpoint (creates scene record + earnings entry + costar detection + invite suggestions for non-platform members), auto generate call sheet, scene work earnings summary API, scene-work.html renamed Studio Scenes→Mainstream Scenes + All tab added, bookings.html has I Have Been Paid button, earnings-v2.html shows scene breakdown by type, morning summary has earnings vs payout separated
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/bookings.html, platform-server/public/app/earnings-v2.html, platform-server/public/app/scene-work.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/bookings-full.js
2026-05-25 04:50 AM — Auto-logged Changes
Affected: Bookings, Earnings & Payouts, Filmography, Setup Guide, Tutorial
Commits:
- Complete scene lifecycle: Funded Scene = fan/creator/brand funded (not just customers), scene corrections with change_trail (all tagged performers notified), tube site flagging with issue types (unauthorized/wrong name/wrong description), scene comments visible to performers (all tagged notified), press release → performer notification, terminology updated throughout (Studio Scenes→Mainstream Scenes in all files, funded scene description expanded)
Files changed: platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/bookings.html, platform-server/public/app/dashboard.html, platform-server/public/app/earnings-v2.html, platform-server/public/app/filmography.html, platform-server/public/app/financial.html, platform-server/public/app/scene-work.html, platform-server/public/app/setup-guide.html, platform-server/public/app/tutorial.html, platform-server/public/last-docs-update-commit.txt (+3 more)
2026-05-25 04:51 AM — Auto-logged Changes
Affected: Filmography
Commits:
- Fix change_trail and content_reports column names (table_name→content_type, record_id→content_id, field→field_name, content_type→reported_content_type)
Files changed: platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/last-docs-update-commit.txt, platform-server/routes/filmography.js, platform-server/routes/scene-cascade.js
May 25, 2026 — Major Features Added
Scene Lifecycle System
Full booking-to-earnings-to-comments lifecycle:
Funded Scene Definition
Funded = ANY third-party funded production:
- Fan commissioning a scene
- Another creator paying performer to appear on their OnlyFans/website
- Brand deal / content creation commission
NOT "customer-funded only" — any third party
Online/Industry Status System
Columns added to users: online_mode, is_online, last_seen, online_at, industry_status, status_message
GET/PUT /api/settings/online-status
POST /api/settings/heartbeat — every 60s while page open
POST /api/settings/offline — sendBeacon on tab close/app switch
GET /api/settings/online-users
js/online-status.js on 113 pages — persistent nav status picker
- Industry status: active/on_hiatus/inactive/retired
Terminology Changes
- "Scene Work" (page name) → tabs now: All / Mainstream Scenes / Self-Produced / Funded
- "My Studio Scenes" → "Mainstream Scenes" everywhere in UI
- "Self Scenes" → "Self-Produced"
- User Type display (not "Account Type")
- "All User Types" in nav switcher
PPM Messaging System
- Per-message pricing visible in cost bar before sending
POST /api/dm/check-cost returns rates
- Text/Photo/Video/PPV type selector in composer
- Send button shows "Send — $2.00"
- "Change rates →" link in cost bar → Settings
Admin Platform Revenue Withdrawal
GET /api/payouts/admin/platform-fees — available platform fees
POST /api/payouts/admin/withdraw-platform-fees — withdraw to bank
- Earnings → Platform Revenue tab (admin only)
- Separate from performer earnings withdrawal
Payout History Notion DB
DB ID: 36bb8641-18fc-8124-ba24-e373f4c2b319
Syncs on: payout requested, Stripe transfer.paid, payout.failed
Platform Stats System
GET /api/earnings/platform-stats — real-time stats (real data only, excludes is_test_data)
scripts/sync-platform-stats.js — populates Platform Stats Notion DB
- Platform Stats Notion DB:
36bb8641-18fc-81f9-a98c-f1afd463c32e
Earnings/Payouts Summary Separation
- Earnings Summary: career history + Indulgon earnings + imported platform earnings
- Payout Summary: only money Indulgon held and transferred
- Career history ($1,045,698) shown in Earnings, NOT in Payouts
Test Data Flagging
is_test_data column on: transactions, earnings
- All pre-launch (before May 21 12:13am) data flagged as test
- All APIs filter by
is_test_data=false for real stats
2026-05-25 05:05 AM — Auto-logged Changes
Affected: Setup Guide, Sign Up / Login, Profile, Tour Page, Tutorial
Commits:
- Complete documentation update for all targets: tour.html (scene lifecycle, PPM messaging, online status, inbox/notifications sections), tutorial.html (PPM rates step, online status step, scene lifecycle step), setup-guide.html (scene lifecycle guide with table, messaging pricing table, online status guide with mobile behavior), support.html (new FAQ: scene types, confirm payment, tube site flagging, PPM, status definitions, platform revenue tab), signup-performer.html (3 new pitch items: scene lifecycle, industry transparency, industry status), PLATFORM-OPERATIONS-MANUAL.md (May 25 features documented)
Files changed: platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/setup-guide.html, platform-server/public/app/signup-performer.html, platform-server/public/app/support.html, platform-server/public/app/tour.html, platform-server/public/app/tutorial.html, platform-server/public/last-docs-update-commit.txt
2026-05-25 05:37 AM — Auto-logged Changes
Affected: Settings
Commits:
- Unified All Prices section in Settings: video call $20/min, voice $5/min, cam $10/min, all rate columns added to users table, GET/PUT /api/settings/pricing covers all 11 rate types, bidirectional load on page open, saveAllPrices() delegates from saveMessagingRates/saveBookingRates for consistency, Daily.co DAILY_API_KEY saved to .env
Files changed: platform-server/public/app/settings.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/settings.js
2026-05-25 05:47 AM — Auto-logged Changes
Affected: Settings
Commits:
- Cam show rate set to $20/min (matches video call), skip Balances/Transactions in Financial Connections
- Fix pricing GET endpoint: correct SQL columns, variable name u not user, no undefined settings reference
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/settings.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/settings.js
2026-05-25 01:37 PM — Auto-logged Changes
Affected: Earnings & Payouts, Bookings
Commits:
- Complete performer→agent/studio fee split system: fee_splits table, /api/fee-splits (GET/POST/send/from-booking), Stripe transfer between Connect accounts, fallback manual tracking if payee has no Connect account, auto-creates splits on confirm-payment when booking has agent_id, 'Owed to Others' tab in Financial Hub with send button, pending splits alert on Earnings page, agent/studio/manager/studio_fee/custom types
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/earnings-v2.html, platform-server/public/app/financial.html, platform-server/public/last-docs-update-commit.txt, platform-server/routes/_register.js, platform-server/routes/bookings-full.js, platform-server/routes/fee-splits.js, upload/IMG_3116.jpeg, upload/IMG_3117.jpeg
2026-05-25 01:40 PM — Auto-logged Changes
Affected: Activity, Bookings, Design & Themes, Inbox, Navigation, Messages, Profile, Setup Guide, Tutorial
Commits:
- Nav logo: transparent bg with /in-DULGE-on/ tagline, inherits theme color (CSS currentColor via var(--text)). Emojis removed from all 9 platform files. Updates page: page pills link to their pages, entry cards clickable. Cron jobs reduced: PM2 monitor 5min→30min, error check hourly→6h, sync health 4h→12h (saves ~264 agent turns/day)
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/activity.html, platform-server/public/app/bookings.html, platform-server/public/app/css/platform.css, platform-server/public/app/inbox.html, platform-server/public/app/js/nav.js, platform-server/public/app/js/photo-filter-system.js, platform-server/public/app/messages-v2.html, platform-server/public/app/profile.html (+78 more)
2026-05-25 01:43 PM — Auto-logged Changes
Affected: Design & Themes, Navigation
Commits:
- Nav logo: Indulgon with /in-DULGE-on/ pronunciation, original font/weight/spacing preserved. Final SVG logos saved for both Indulgon and JJ Entertainment.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/css/platform.css, platform-server/public/app/js/nav.js, platform-server/public/img/logos/gen-indulgon-dark.html, platform-server/public/img/logos/gen-indulgon.html, platform-server/public/img/logos/gen-logos.html, platform-server/public/img/logos/indulgon-final.svg, platform-server/public/img/logos/indulgon-logo-dark.png, platform-server/public/img/logos/indulgon-logo-light.png (+5 more)
2026-05-25 01:47 PM — Auto-logged Changes
Affected: Activity, Design & Themes, Inbox, Navigation, Model Releases & Costar System
Commits:
- Nav logo restored to original style: INDULGON all-caps, wide letter-spacing (0.45em), medium weight — exactly matching original screenshot. /IN·DULGE·ON/ pronunciation added underneath. Emojis removed from activity, inbox, legal, templates-manager.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/activity.html, platform-server/public/app/css/platform.css, platform-server/public/app/inbox.html, platform-server/public/app/js/nav.js, platform-server/public/app/legal.html, platform-server/public/app/templates-manager.html, platform-server/public/last-docs-update-commit.txt
2026-06-08 11:30 AM — Auto-logged Changes
Affected: Navigation
Commits:
- Replace all standard characters with SVG equivalents: ▶ play button → SVG path, • notification bullet → SVG square, · separators → em dash. No text-based symbols anywhere in platform UI.
Files changed: platform-server/CHANGELOG.md, platform-server/PLATFORM-OPERATIONS-MANUAL.md, platform-server/public/app/js/nav.js, platform-server/public/app/js/online-status.js, platform-server/public/app/updates.html, platform-server/public/last-docs-update-commit.txt