make_post_sell/docs/JAVASCRIPT.md
russell@unturf.com 32a19a339c docs: add MPS-6 through MPS-9 tickets, architecture diagram, update JS docs
- MPS-6: referrer analytics (domain, query, trend line charts)
- MPS-7: sandbox mode creative filter system
- MPS-8: user S3 bucket + artifact storage
- MPS-9: shop S3 mirror bucket
- architecture.md: system diagram, request flow, data pipeline, S3 layout
- JAVASCRIPT.md: add sandbox.js, signals.js, MediaPipe SDK entries
- sandbox-mode.md: mark S3 upload as implemented
- mps-2.md: document referrer_domain + referrer_query columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 06:19:56 -05:00

6.4 KiB

JavaScript Usage

This project minimizes JavaScript usage, preferring pure CSS solutions where possible (e.g., <details> elements for toggles). JavaScript is used only where necessary for payment integrations, real-time updates, and progressive enhancement.

Philosophy

  • Prefer pure HTML/CSS over JavaScript
  • Use <details> elements for toggles instead of JS
  • External SDKs loaded only when payment method is enabled
  • No build step - vanilla JS only
  • No jQuery - all vanilla JavaScript

Static JavaScript Files

Located in make_post_sell/static/js/:

qrcode.min.js

  • QRious library for QR code generation
  • Used by: Crypto checkout page
  • Generates payment QR codes for XMR/DOGE addresses

custom.js

  • Markdown preview functionality
  • Functions: previewAjax(), sendPreview()
  • Uses fetch API for AJAX calls to /markup-editor-preview

watch.js

  • Watch mode continuous playback engine
  • Used by: product.j2 when shop has watch_mode_enabled
  • Discovery ring with deterministic content traversal per shop
  • Crossfade transitions between media (3s, 60 steps)
  • Countdown overlay (7s) between items
  • Queue management: add, remove, reorder
  • Two-phase preload: JSON metadata fetch, then media buffering 30s before end
  • Recently-played filtering via localStorage (4-hour expiry)
  • Handles video, audio, and static content (PDFs, images)
  • Autoplay toggle persisted in localStorage
  • Ring state (position, direction, history) persisted in localStorage

sandbox.js

  • Client-side creative filter engine (IIFE, ~700 lines)
  • Used by: base.j2 when shop has sandbox_mode enabled
  • 32 CSS filter presets across 7 categories (basic, warm, cool, dramatic, color, Instagram-style, SVG)
  • 7 adjustment sliders (brightness, contrast, saturation, hue, blur, sepia, grayscale)
  • Image export via canvas toBlob() (PNG)
  • Video export via MediaRecorder + captureStream(30fps) (WebM)
  • On-demand face detection via MediaPipe Face Mesh (468 landmarks, eye glow, face mask overlays)
  • Upload-to-bucket: presigned POST to user's S3 bucket via /u/sandbox/upload
  • localStorage persistence: preset, slider values, panel state, filter mode
  • Exposes window.sandboxReapply() for watch.js SPA integration

signals.js

  • Anonymous page visit signal collector
  • Used by: all product/content pages
  • Collects presence (wall_clock, visible, active), scroll (depth, direction changes), and media playback signals
  • Sends single JSON beacon (~300 bytes) via navigator.sendBeacon() on page unload
  • No cookies, no IPs, no fingerprints — purely behavioral signals
  • Viewport width sent for device class derivation (server-side)

comments.js

  • AJAX comment submission (progressive enhancement)
  • Intercepts comment form POST, submits via fetch() with X-Requested-With: XMLHttpRequest
  • Server returns JSON (HTTP 201) for AJAX requests
  • Inserts new comment into DOM without page reload (preserves media playback)
  • Falls back to normal POST + redirect without JS or on error

player.js

  • Pop-out media player with draggable window
  • Prev/next navigation and keyboard shortcuts
  • Auto-advance for images/PDFs (60s timer)
  • Preloads adjacent media for instant switching
  • Used by: /random and /tv endpoints

Inline JavaScript by Template

base.j2

Purpose: Theme switching (dark/light mode)

  • Runs immediately in <head> to prevent flash of wrong theme
  • Priority: localStorage > user preference > shop default
  • Exposes window.setTheme() for programmatic use

shop_settings.j2

Purpose: Settings page interactions

  • Crypto wallets toggle (checkbox + localStorage)
  • Theme preview for shop default theme radio buttons
  • Note: Payment provider toggles use pure CSS <details> elements

user_settings.j2

Purpose: User theme preference sync

  • Syncs theme radio buttons with localStorage
  • Updates localStorage on form submit

cart_checkout.j2

Purpose: Payment processing

  1. PayPal SDK (paypal.Buttons())

    • Loads PayPal SDK from paypal.com
    • Creates orders via POST /paypal/create-order
    • Handles approval flow and form submission
    • Double-click protection flags
  2. Cancel Crypto Quote (cancelQuote())

    • Cancels pending crypto payment quotes
    • Uses fetch API with CSRF token

crypto_checkout.j2

Purpose: Crypto payment monitoring

  • QR code generation using QRious library
  • Countdown timer for quote expiry
  • Status polling via fetch API
  • Copy-to-clipboard for address/amount
  • Dynamic UI updates based on payment status
  • Functions: disableQuoteButtons(), removePaymentElements(), replaceButtonsWithInvoiceLink()

snippets/stripe.j2

Purpose: Stripe card form (macro new_card())

  • Loads Stripe.js SDK
  • Creates Payment Element for card input
  • Handles stripe.confirmSetup() flow
  • Uses vanilla JS with DOMContentLoaded

snippets/analytics.j2

Purpose: Analytics tracking (optional)

  • Plausible Analytics (privacy-focused)
  • Google Analytics (gtag.js)
  • Only loaded if shop has configured analytics

product.j2

Purpose: Inline video playback

  • playInline() replaces thumbnail container with <video> element on click
  • Used for preview playback on product pages without watch mode
  • Loads watch.js when shop has watch_mode_enabled

snippets/comments.j2

Purpose: Comment form

  • Loads comments.js async for AJAX submission
  • Uses js-only class pattern for elements requiring JS

snippets/optional-javascript.j2

Purpose: Optional JS loading

  • Loads custom.js async
  • Used for markdown preview functionality

External SDKs

SDK URL Used For
PayPal paypal.com/sdk/js PayPal button/checkout
Stripe js.stripe.com/v3/ Card payment form
Plausible Shop-configured domain Privacy analytics
Google Analytics googletagmanager.com Google analytics
MediaPipe cdn.jsdelivr.net Face detection (sandbox mode, on-demand)

CSRF Protection

All fetch/AJAX calls include CSRF tokens:

  • Header: X-CSRF-Token
  • Value from: {{ request.session.get_csrf_token() }} or hidden input

Progressive Enhancement

Pages work without JavaScript where possible:

  • Payment provider toggles use <details> (pure CSS)
  • Forms submit normally without JS
  • JS enhances UX (copy buttons, QR codes, live previews)
  • Comment forms POST normally without JS; AJAX submission preserves playback with JS
  • Watch mode elements use js-only class (hidden via <noscript> stylesheet)
  • Video thumbnails link directly to media without JS; inline playback with JS