- New admin root + child layouts with daisyUI drawer sidebar
- AdminLayoutHook tracks current path for active nav highlighting
- Split router into :admin, :admin_theme, :user_settings live_sessions
- Theme editor stays full-screen with back link to admin
- Admin bar on shop pages for logged-in users (mount_current_scope)
- Strip Layouts.app wrapper from admin LiveViews
- Remove nav from root.html.heex (now only serves auth pages)
- 9 new layout tests covering sidebar, active state, theme editor, admin bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidates admin_live/, theme_live/, provider_live/ into admin/
(with theme/ and providers/ subdirs). Renames shop_live/ to shop/
and user_live/ to auth/. Updates all module names, router refs,
test files, CSS source paths, and dialyzer ignore.
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>
Move increment/decrement handlers from Cart LiveView into CartHook so
they work from any page's drawer. Enable show_quantity_controls on the
drawer's cart_item_row. Scope cart tests to #main-content to avoid
duplicate button matches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire up +/− buttons with phx-click events and handle_event handlers,
clamp to 1–99, reset to 1 after add-to-cart. Trust badges now use a
single hero-check-circle icon and sentence case text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mobile: swipeable carousel with dot indicators, no lightbox trigger.
Desktop: carousel with thumbnail grid, prev/next arrows, click to
open existing lightbox. Keeps all lightbox appearance and behaviour.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 16 mock products now have at least one variant so add-to-cart works
in demo mode. CSSCache.invalidate/0 rescues ArgumentError when the ETS
table doesn't exist yet (seed_defaults runs before CSSCache starts).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
37 new LiveView integration tests covering the three previously
untested shop pages. Product detail tests cover variant selection,
price updates and add-to-cart. Cart tests use DB fixtures with
session seeding for hydration. Home tests cover hero, categories,
featured products and navigation links. 612 total tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace one-off ShopLive.About with generic ShopLive.Content that
handles all static content pages via live_action. Add delivery &
returns, privacy policy, and terms of service pages with sample
content. Update footer help links and theme editor preview.
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>
Create separate CSS bundles to reduce shop page load times:
- app-shop.css (45KB/7.8KB gzip): Shop pages only, no daisyUI
- app.css (139KB): Admin pages with daisyUI and theme editor
Key changes:
- Add app-shop.css with targeted @source paths for shop files only
- Move .preview-frame rules from theme-layer2-attributes.css to app.css
- Delete fonts.css (fonts now generated inline by CSSGenerator)
- Add inline all-fonts generation in theme editor for typography switching
- Configure separate Tailwind profiles and watchers for both bundles
Shop pages now load 54% less CSS by excluding:
- daisyUI components (admin only)
- .preview-frame theme switching rules (editor only)
- Admin-specific Tailwind utilities
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>
Self-hosted fonts:
- Download all 10 typefaces (35 font files, 728KB) from Google Fonts
- Create @font-face declarations in assets/css/fonts.css
- Remove Google Fonts external dependency from layouts
- Privacy improvement (no Google tracking)
- Performance improvement (no DNS lookup to fonts.googleapis.com)
- GDPR compliant (no third-party requests)
Admin access:
- Add /admin route that redirects to /admin/theme (requires auth)
- Remove Admin link from footer (too visible for visitors)
- Shop owners can bookmark or type /admin directly
Layout improvements:
- Create shop_root.html.heex as minimal root for shop pages
- Shop pages no longer show admin nav bar
Other:
- Update .gitignore to exclude digested static files
- Add PageSpeed 100% task to ROADMAP.md
- Fix test to check /users/settings instead of shop homepage
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>
- Add ShopLive.Cart at /cart using shared PageTemplates
- Update ErrorHTML to render fully themed 404/500 pages
- Add dev-only error preview routes at /dev/errors/404 and /dev/errors/500
- Update error page tests for themed output
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>
Add tests to verify that:
- Both .shop-root and .preview-frame have theme data attributes
- Theme settings changes are reflected on shop pages
- CSS file has correct selectors for both contexts
- Generated CSS cache includes all theme variables
These tests catch regressions like the selector issue where
.preview-frame[data-mood="warm"] was incorrectly transformed to
.preview-frame, .shop-root[data-mood="warm"] instead of
.preview-frame[data-mood="warm"], .shop-root[data-mood="warm"]
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create LoadTheme plug for loading theme settings
- Add shop layout with inline CSS injection (~400 bytes vs 17KB full)
- Create ShopLive.Home at / using shared ShopComponents
- Wire up CSS cache invalidation when theme settings change
- Replace Phoenix welcome page with themed shop home page
The shop layout injects only the active theme CSS variables inline,
achieving a 97% reduction compared to the full variants file used
by the theme editor.
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 Google Fonts link to root layout for typography presets
- Add data-mood, data-typography, data-shape, data-density attributes to preview-frame
- Create theme-layer2-attributes.css with attribute-based CSS from demo
- Move theme CSS files from priv/static/css to assets/css for proper compilation
- Update CSS import order (primitives → layer2 → semantic)
- Add 'css' to static_paths to serve theme CSS files
This fixes the issue where theme controls updated the database but didn't
visually affect the preview. The demo's attribute-based CSS system is now
properly integrated with the Phoenix LiveView implementation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement all 7 preview pages showcasing theme customization:
- Home page: hero, featured products, testimonials, categories
- Collection page: product grid with filters and sorting
- Product detail page (PDP): gallery, variants, add to cart
- Cart page: cart items with quantity controls and order summary
- About page: company story and values
- Contact page: contact form and business information
- 404 error page: error message with product suggestions
Features:
- All pages use CSS custom properties for theming
- Preview data from PreviewData module (mock products, testimonials, categories)
- Responsive layouts with Tailwind utilities
- Grid columns respect theme settings
- Colors, typography, shapes, and spacing all theme-aware
- Components created as embed_templates for clean separation
Technical implementation:
- Created PreviewPages component module with embed_templates
- Wired up preview_data in LiveView mount
- Updated index.html.heex to render preview pages based on @preview_page
- All pages styled with inline styles using CSS variables
- Scrollable preview frame with max-height
All tests passing (197 total).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement basic theme editor interface with live preview:
- ThemeLive.Index LiveView with mount and event handlers
- Two-column layout: controls sidebar + preview area
- Display all 9 presets as clickable buttons
- Apply preset and regenerate CSS on click
- Show current theme settings (mood, typography, shape, density, color)
- Preview page switcher (7 pages: home, collection, product, cart, about, contact, 404)
- Inline <style> tag with generated CSS for instant preview
- Basic preview frame showing theme variables in action
- Authentication required via :require_authenticated_user pipeline
- Theme navigation link added to user menu
- 9 comprehensive LiveView tests
All tests passing (197 total).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>