- 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>
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.j2when shop haswatch_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.j2when shop hassandbox_modeenabled - 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()withX-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:
/randomand/tvendpoints
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
-
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
- Loads PayPal SDK from
-
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.jswhen shop haswatch_mode_enabled
snippets/comments.j2
Purpose: Comment form
- Loads
comments.jsasync for AJAX submission - Uses
js-onlyclass 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-onlyclass (hidden via<noscript>stylesheet) - Video thumbnails link directly to media without JS; inline playback with JS