MPS-14: Add environment column (production/staging/development) to shops.
Non-production shops excluded from feeds, search, and discovery.
Environment banner in base template. Settings UI and creation selector.
MPS-15: Add 21-day free trial with trial_started_timestamp on shop
creation. Properties: is_trial_active, is_trial_expired, trial_days_remaining,
is_active. Grandfathered pre-trial shops (NULL timestamp = paid).
Trial banner in base template.
MPS-16: BYOB (Bring Your Own Bucket) - per-shop S3 storage with
primary_s3_* columns. Shop-aware request methods (shop_uploads_client,
shop_bucket_name, shop_cdn_endpoint) that fall back to MPS default.
All templates and views updated from global to shop-aware S3 references.
Bucket settings UI in shop settings.
Migration: 9884324a48e3 (idempotent, 11 new columns on mps_shop).
Tests: 14 unit tests + 8 functional tests (712 total, all pass).
Variable-amount gift cards purchasable with any payment method.
Code-based redemption at checkout (applied to cart like coupons).
Partial use across multiple purchases, never expire. Shop owners
control min/max amounts and can disable individual cards.
Models: GiftCard, GiftCardTransaction, CartGiftCard + migration.
Views: purchase page, cart apply/remove, shop admin manage/detail/toggle.
Templates: gift_card.j2, gift_card_manage.j2, gift_card_detail.j2.
Cart integration: gift cards deduct after coupons in all checkout paths.
Tests: 10 new unit tests covering model logic (677 total pass).
Adjust login card spacing for smaller screens and add overflow hidden to main content sections. Refine logo sizing across viewport sizes to prevent it from dominating on mobile devices.
- Add white-space: nowrap to section.log-in links, .user-display-name,
.cart-and-count, .mps-button, .mps-footer-links a, .mps-footer-group-title
- Prevents sloppy word breaks on "My Account", "Cart $0.00", etc.
- Remove .well from login-card to prevent padding/bg override
- Add border-radius and border directly to .login-card
- Bump specificity on .landing-feature-card.well and .landing-cta-card.well
- Constrain hero CTA button min-width to 180px
- Add display:block to .login-form-input for reliable full-width
Move :root and [data-theme="dark"] variable blocks from common.css into
tokens.css so the entire theme system lives in one file. Replace ~38
hardcoded #2d3748 dark button backgrounds with var(--dark-button-bg).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ~150 hardcoded color, spacing, radius, font, and border values
with CSS custom property references from tokens.css. Every replacement
uses var() with the original value as fallback, ensuring zero visual
change while establishing the token-based foundation.
Categories migrated:
- Colors: button backgrounds, link color, status text, alert bg/text/border
- Surfaces: wells, content bg, table stripes, card bg, input bg
- Borders: input borders, thumbnails, comment replies, crypto cards
- Border radius: buttons, inputs, wells, serp items, alerts, cards
- Typography: font-family, font-size, font-weight on buttons/labels
- Spacing: padding, margins on buttons, inputs, coupons, notices
- Motion: theme toggle transition uses duration/easing tokens
Dark mode [data-theme="dark"] blocks left untouched — they override
via the existing variable system and will be consolidated in a future pass.
Tests were using /s/{shop.id} which returns 302 redirect instead of
/s/{shop.id}/{shop.slug} which returns 200 directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add _daily_referrer_counts() for 28-day external referrer line chart
bucketing in shop and product analytics views
- Add SVG line chart sections for referrer trends in both analytics
templates (analytics.j2 and analytics_product.j2)
- Add functional tests for sandbox mode enable/disable, toolbar
conditional rendering, and form isolation
- Add functional tests for user S3 storage settings (save, clear,
validation) and presigned upload endpoint
- Add test for data-has-bucket attribute on sandbox toolbar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New styleguide page at /styleguide showing all design system
components: colors (light/dark), typography, buttons (core +
semantic + small/cancel), form elements, wells, alerts, SERP
product cards, layout patterns, task bar, theme system docs,
comment actions, ribbon, and footer structure.
Includes theme toggle button for previewing both modes.
Extends base.j2, wired through routes.py and views/misc.py.
watch.js: presigned URL refresh now skips src swap when media is paused.
Tracks lastUrlRefreshTs so that when the user resumes playback after a
long pause, the play listener detects the stale URL and refreshes before
continuing. No more re-buffering or disruption for idle media.
shop.py: detect X-Requested-With header on settings POST and return JSON
with flash messages instead of redirect, enabling SPA behavior.
shop-settings.js: new progressive enhancement script intercepts settings
form submits via fetch, renders flash messages inline into #alerts div.
Falls back to normal POST + redirect when JS is disabled or on error.
watch.py now returns human_created_timestamp, human_updated_timestamp,
and show_dates in the JSON response. watch.js updatePageContent() rebuilds
the .product-meta-dates element on each navigation so Created/Updated
dates reflect the current product instead of staying stale from initial load.
Extract _AuthenticatedBase class from AuthenticatedFunctionalTests so
TestBeacon and TestAnalytics inherit only setUp/helpers without
duplicating all parent test methods (112 + 92 → 25 + 6 tests).
Add check_same_thread=False for SQLite engines so background reforge
threads can safely use the shared connection pool.
Return thread from reforge_discovery_ring_async and replace sleep-based
waits with thread.join() for deterministic, CI-resilient assertions.
Shop owners can configure their own S3-compatible bucket (DigitalOcean
Spaces, AWS S3, MinIO, Backblaze B2, etc.) to automatically mirror all
uploaded files. The MPS main bucket remains the origin/CDN — the shop
bucket is a fire-and-forget backup.
Sync runs in daemon threads after each copy_object, capturing credentials
as plain strings for thread safety with fresh boto3 clients per thread.
Backfill button copies all existing files via double-fork process.
Users can configure their own S3-compatible bucket credentials in User
Settings > Artifact Storage. When configured, sandbox mode shows an
"Upload to Bucket" button that pushes exported artifacts (filtered images,
video captures) directly to the user's bucket via presigned POST.
Supports DigitalOcean Spaces, AWS S3, MinIO, Backblaze B2, and any
S3-compatible service. Files never touch the MPS server — two-step
presign pattern matches existing product upload architecture.
CDN already serves Access-Control-Allow-Origin: * but browsers only
send the Origin header when img.crossOrigin is set. sandbox.js now
sets crossOrigin="anonymous" on all images at init and after SPA
navigation so canvas.toBlob() can read pixels for export.
Architecture diagrams, export pipeline, face detection pipeline,
filter preset reference table, CORS requirements, localStorage keys,
mobile behavior, and stacking with shop color filter.
Client-side creative filter system for MPS shops. When enabled, visitors
see a floating toolbar with 32 filter presets (basic, warm, cool, dramatic,
color shifts, Instagram-style, SVG), 7 adjustment sliders, image/video
canvas export, and on-demand MediaPipe face detection (eye glow, face mask).
All processing is browser-side. Server only stores the sandbox_mode toggle.
Filters apply to individual media elements (stacks with shop color_filter).
localStorage persists filter state. Watch mode SPA re-applies on navigation.
Set PRAGMA busy_timeout=30000 on SQLite connections to prevent
"database is locked" errors under concurrent access. Fix invalid
escape sequence in email regex by using raw string.
- Add SVG line charts for session duration, engagement, and bounce rate trends (28 days)
- Track referrer_domain and referrer_query on PageSession (new migration)
- Refactor classify_referrer() to extract domain and search engine query params
- Surface internal search keywords (ShopSearchRequest) on shop analytics
- Show top referrer domains and search engine queries on both analytics pages
- Add wide bar row CSS modifier for longer domain labels