Printful HTTP client (v2 + v1 for sync products), Provider behaviour
implementation with all callbacks (test_connection, fetch_products,
submit_order, get_order_status, fetch_shipping_rates), and multi-provider
order routing that looks up the provider connection from the order's
product instead of hardcoding "printify".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shipping rates fetched from Printify during product sync, converted to
GBP at sync time using frankfurter.app ECB exchange rates with 5%
buffer. Cached in shipping_rates table per blueprint/provider/country.
Cart page shows shipping estimate with country selector (detected from
Accept-Language header, persisted in cookie). Stripe Checkout includes
shipping_options for UK domestic and international delivery. Order
shipping_cost extracted from Stripe on payment.
ScheduledSyncWorker runs every 6 hours via Oban cron to keep rates
and exchange rates fresh. REST_OF_THE_WORLD fallback covers unlisted
countries. 780 tests, 0 failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FTS5 prefix matching misses mid-word substrings (e.g. "ebook" in
"notebook"). When FTS5 returns zero results, fall back to LIKE
query on title and category with proper wildcard escaping. 4 new
tests, 757 total.
Also marks completed plan files (search, admin-redesign,
setup-wizard, products-context) with correct status.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace PreviewData indirection in all shop LiveViews with direct
Products context queries. Home, collection, product detail and error
pages now query the database. Categories loaded once in ThemeHook.
Cart hydration no longer falls back to mock data. PreviewData kept
only for the theme editor.
Search modal gains keyboard navigation (arrow keys, Enter, Escape),
Cmd+K/Ctrl+K shortcut, full ARIA combobox pattern, LiveView navigate
links, and 150ms debounce. SearchModal JS hook manages selection
state and highlight. search.ex gets transaction safety on reindex
and a public remove_product/1. 10 new integration tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds SQLite FTS5 search index with BM25 ranking across product title,
category, variant attributes, and description. Search modal now has
live results with thumbnails, prices, and click-to-navigate. Index
rebuilds automatically after each provider sync.
Also fixes Access syntax on Product/ProductImage structs (Map.get
instead of bracket notation) which was causing crashes when real
products were loaded from the database.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds cheapest_price, compare_at_price, in_stock, on_sale columns to
products table (recomputed from variants after each sync). Shop
components now work with Product structs directly instead of plain
maps from PreviewData. Renames .name to .title, adds Product display
helpers (primary_image, hover_image, option_types) and ProductImage
helpers (display_url, direct_url, source_width). Adds Products context
query functions for storefront use (list_visible_products,
get_visible_product, list_categories with DB-level sort/filter).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Settings.site_live?/0 and set_site_live/1 for shop visibility control
- Accounts.has_admin?/0 to detect single-tenant admin existence
- Registration lockdown: /users/register redirects when admin exists
- Setup.setup_status/0 aggregates provider, product, and stripe checks
- Coming soon page at /coming-soon with themed styling
- ThemeHook :require_site_live gate on all public shop routes
- Site live → everyone through
- Authenticated → admin preview through
- No admin → fresh install demo through
- Otherwise → redirect to coming soon
- Go live / take offline toggle on /admin/settings
- 648 tests, 0 failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plain text emails via Swoosh OrderNotifier module. Order confirmation
triggered from Stripe webhook after payment, shipping notification
from Printify shipment webhook with polling fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin UI at /admin/orders to view, filter, and inspect orders.
Adds list_orders/1 and count_orders_by_status/0 to the Orders
context, status filter tabs, clickable order table with streams,
and a detail page showing items, totals, and shipping address.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Store API keys and secrets encrypted in the SQLite database via the
existing Vault module (AES-256-GCM). The only external dependency is
SECRET_KEY_BASE — everything else lives in the portable DB file.
- Add encrypted_value column to settings table with new "encrypted" type
- Add put_secret/get_secret/delete_setting/secret_hint to Settings context
- Add Secrets module to load encrypted config into Application env at startup
- Add Stripe.Setup module with connect/disconnect/verify_api_key flow
- Auto-creates webhook endpoints via Stripe API in production
- Detects localhost and shows Stripe CLI instructions for dev
- Add admin credentials page at /admin/settings with guided setup:
- Not configured: single Secret key input with dashboard link
- Connected (production): status display, webhook info, disconnect
- Connected (dev): Stripe CLI instructions, manual signing secret input
- Remove Stripe env vars from dev.exs and runtime.exs
- Fix CSSCache test startup crash (handle_continue instead of init)
- Add nav link for Credentials page
507 tests, 0 failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cart context with pure functions for add/remove/update/hydrate
- Price formatting via ex_money (replaces all float division)
- CartHook on_mount with attach_hook for shared event handlers
(open/close drawer, remove item, PubSub sync)
- Accessible cart drawer with focus trap, scroll lock, aria-live
- Cart page with increment/decrement quantity controls
- Preview mode cart drawer support in theme editor
- Cart persistence to session via JS hook + API endpoint
- 19 tests covering all Cart pure functions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add /admin/providers LiveView for connecting and managing POD providers
- Implement pagination for Printify API (handles all products, not just first page)
- Add parallel processing (5 concurrent) for faster product sync
- Add slug-based fallback matching when provider_product_id changes
- Add error recovery with try/rescue to prevent stuck sync status
- Add checksum-based change detection to skip unchanged products
- Add upsert tests covering race conditions and slug matching
- Add Printify provider tests
- Document Printify integration research (product identity, order risks,
open source vs managed hosting implications)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement the schema foundation for syncing products from POD providers
like Printify. This includes encrypted credential storage, product/variant
schemas, and an Oban worker for background sync.
New modules:
- Vault: AES-256-GCM encryption for API keys
- Products context: CRUD and sync operations for products
- Provider behaviour: abstraction for POD provider implementations
- ProductSyncWorker: Oban job for async product sync
Schemas: ProviderConnection, Product, ProductImage, ProductVariant
Also reorganizes Printify client to lib/simpleshop_theme/clients/ and
mockup generator to lib/simpleshop_theme/mockups/ for better structure.
134 tests added covering all new functionality.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add WCAG AA compliant accent color variants and update default accent
to meet 4.5:1 contrast ratio requirements.
- Add --t-accent-text (darker for text on light backgrounds)
- Add --t-accent-button (darker for button backgrounds with white text)
- Change default accent from #3b82f6 to #2563eb (better contrast)
- Update presets and tests for new default
These changes ensure accent colors meet accessibility standards while
maintaining visual consistency with the brand palette.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Improve the image optimization pipeline with better compression and
smarter variant generation:
- Change to_lossless_webp → to_optimized_webp (lossy, quality 90)
- Auto-resize uploads larger than 2000px to save storage
- Skip pre-generating JPEG variants (~50% disk savings)
- Add on-demand JPEG generation for legacy browsers (<5% of users)
- Add /images/:id/variant/:width route for dynamic serving
- Add VariantCache to supervision tree for startup validation
- Add image_cache to static paths for disk-based serving
The pipeline now stores smaller WebP sources and generates AVIF/WebP
variants upfront, with JPEG generated only when legacy browsers request it.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Optimizer module with lossless WebP conversion
- Generate responsive variants at [400, 800, 1200] widths
- Only create sizes <= source dimensions (no upscaling)
- Support AVIF, WebP, and JPEG output formats
- Add disk cache at priv/static/image_cache/
- Add comprehensive test suite (12 tests)
- Add image fixtures helper for testing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add sort functionality to /collections/:slug pages with 6 sort options
(featured, newest, price ascending/descending, name A-Z/Z-A). Sort
selection persists across category navigation via URL query params.
Refactor handle_params to be DRY using load_collection/1 helper.
Add comprehensive unit tests for PreviewData category functions and
LiveView tests for the Collection page sorting and navigation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Verifies that updating theme settings regenerates the CSS cache
with the new values. Tests accent color changes from red to blue
and confirms the correct HSL hue values appear in cached CSS.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests cover:
- get/0, put/1, invalidate/0, warm/0 functions
- Performance benchmark comparing cache hit vs CSS generation
- 100 cache hit consistency test
Run with: mix test test/simpleshop_theme/theme/css_cache_test.exs --include benchmark
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add .themed class as shared selector for both shop and preview
- Move visual/behavioral styles from .preview-frame to .themed
- Keep .preview-frame only for CSS variable switching (editor live preview)
- Update CSSGenerator to target .themed instead of .shop-root
- Refactor CSS files to use native CSS nesting syntax
- Update tests to reflect new class structure
This improves maintainability by:
- Eliminating duplicate selectors (.shop-root + .preview-frame)
- Using modern CSS nesting (94%+ browser support)
- Clear separation: .preview-frame = vars, .themed = styles
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused generate_mood/1, generate_typography/1, generate_shape/1,
generate_density/1 functions from CSSGenerator (now handled via CSS
data attributes)
- Prefix unused _opts parameters in Printify.Client
- Remove unused created_products variable from MockupGenerator
- Update CSSGeneratorTest to test actual generated CSS (accent colors,
font size scale, layout width, etc.)
- Update PresetsTest to match 8 presets (not 9)
- Fix PreviewDataTest to accept local image paths
- Update ThemeLiveTest to use correct selectors and match actual UI
- Update Theme Studio sidebar to use DaisyUI theme-aware classes for dark mode
- Convert Customise accordion to native details/summary elements for proper interaction
- Add "Current combination" card showing active theme settings
- Add SVG recolorer for logo color customization
- Add image controller for serving uploaded images
- Implement header background image controls (zoom, position)
- Add toggle_customise event handler to preserve accordion state across re-renders
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add PreviewData module that provides mock data for theme preview:
- 12 diverse mock products with realistic details and placeholder images
- 3 cart items with variants and quantities
- 6 customer testimonials with ratings
- 5 product categories with counts
- Smart fallback: uses real data when available, mock otherwise
All data designed to showcase theme customization options.
Includes 19 comprehensive tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create settings table for site-wide key-value configuration
- Create images table for BLOB storage of logo/header images
- Add Setting schema with JSON/string/integer/boolean support
- Add ThemeSettings embedded schema with all theme options
- Add Settings context with get/put/update operations
- Add Media context for image uploads and retrieval
- Add Image schema with SVG detection and storage
- Add 9 curated theme presets (gallery, studio, boutique, etc.)
- Add comprehensive tests for Settings and Media contexts
- Add seeds with default Studio preset
- All tests passing (29 tests, 0 failures)