Commit Graph

261 Commits

Author SHA1 Message Date
jamey
209ae7aee7 fix navigation links, footer categories, product card structure, and social icons
- add missing cta_href to hero section and error page CTAs
- replace hardcoded footer shop links with real product categories
- restructure product cards with stretched-link pattern so category
  badges link to their collection page
- unify social icons: footer and contact page share the same default
  links from a single source in content.ex
- add search implementation plan (docs/plans/search.md, deferred)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 08:17:19 +00:00
jamey
ac46c1504f remove redundant "view basket" link from cart drawer
The drawer now has full quantity controls, remove, subtotal, and
checkout — the link to the cart page added friction without value.
Cart page remains accessible via the basket icon in nav.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 00:32:15 +00:00
jamey
b3d1019cd4 add quantity controls to cart drawer via shared CartHook
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>
2026-02-11 00:15:04 +00:00
jamey
3c73b98d2b fix PDP quantity selector and trust badge consistency
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>
2026-02-10 23:15:09 +00:00
jamey
8775c2eeef drop redundant "Home" from PDP breadcrumbs
Logo already links home; breadcrumb now starts at category.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:59:34 +00:00
jamey
dc8bf28892 fix breadcrumb styling: semantic markup, chevron separators, mobile sizing
Rewrite breadcrumb as semantic ol/li with aria-current="page", CSS
chevron separators, 0.875em font size, and ellipsis truncation on
mobile for long product names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:58:26 +00:00
jamey
8445e9e8b1 replace PDP image gallery with scroll-snap carousel
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>
2026-02-10 15:33:41 +00:00
jamey
1a69736734 add mobile swipe for product card images and fix dev asset caching
Product cards now use CSS scroll-snap on touch devices (mobile) for
swiping between images, with dot indicators and a JS hook for active
state. Desktop keeps the existing hover crossfade via @media (hover:
hover). Dots use size differentiation (WCAG 2.2 AA compliant) with
outline rings for contrast on any background.

Also fixes: no-image placeholder (SVG icon instead of broken img),
unnecessary wrapper div for single-image cards, and dev static asset
caching (was immutable for all envs, now only prod).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 12:24:52 +00:00
jamey
19b4a5bd59 add variants to all mock products and fix CSSCache race condition
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>
2026-02-09 18:12:57 +00:00
jamey
90b0242a06 fix cart hydration for demo mode with mock products
Cart.hydrate/1 now falls back to PreviewData mock products when variant
IDs aren't found in the database, so add-to-cart works on fresh deploys
without synced Printify data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 08:20:59 +00:00
jamey
c5e353eba1 improve lighthouse scores: image priority and long-poll removal
- Add priority attr to product_card, thread through to responsive_image
- First 2 featured products get fetchpriority="high" and eager loading
- Remove longPollFallbackMs to avoid unnecessary fallback attempt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 23:43:01 +00:00
jamey
865e3563b6 fix production deployment: CSS, images and theme seeding
- Add @source for shop_components/ directory in app-shop.css (Tailwind
  wasn't scanning sub-modules after the refactor, dropping ~73 utilities)
- Remove overly aggressive .dockerignore rules that excluded mockup
  image variants needed by the responsive_image component
- Seed default theme settings on first boot via Release.seed_defaults/0
  in the supervision tree (seeds.exs doesn't run in releases)
- Fix PDP gallery images for mock data by appending -1200.webp to
  bare mockup base paths
- Update fly.toml format from fly launch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 23:42:56 +00:00
jamey
1f4e938ed1 enable gzip on Plug.Static unconditionally
Plug.Static with gzip: true serves .gz files when they exist
(created by phx.digest) and falls back to uncompressed otherwise.
The previous code_reloading? guard was needlessly conservative —
in dev without digested assets, there are no .gz files so nothing
changes. With the lighthouse task building prod assets, this gives
realistic transfer sizes (42KB JS vs 135KB).

Mobile lighthouse scores jump from 95-97 to 99-100.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:23:53 +00:00
jamey
516d0d0070 add mix lighthouse task for PageSpeed auditing
Single-file Mix task that runs Google Lighthouse against the shop
and checks scores against configurable thresholds. Builds production
assets (minified + digested) before auditing for realistic scores.
Waits for image variant cache to finish processing. Supports mobile/
desktop modes, custom thresholds, multiple pages. All 4 key pages
score 95+ on mobile, 97+ on desktop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:18:01 +00:00
jamey
88291f276b add observability: LiveDashboard in prod, error tracking, JSON logging
- Move LiveDashboard to /admin/dashboard behind session auth (all envs)
- Add ErrorTracker at /admin/errors for auto-captured exceptions
- Add Oban job and LiveView metrics to telemetry module
- Add logger_json for structured JSON logs in production
- Enable os_mon for CPU/disk/memory in LiveDashboard OS Data tab
- Extend logger metadata with oban_worker and oban_queue fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 17:02:21 +00:00
jamey
1ee37c853d add Docker deployment with Alpine image, release config and health check
- Alpine multi-stage Dockerfile (131 MB image)
- Release overlays (bin/server, bin/migrate), env.sh, Release module
- Health check endpoint at GET /health
- Fly.io config with SQLite volume mount
- Fix hardcoded paths in optimizer.ex and variant_cache.ex to use
  Application.app_dir/2 (breaks in releases where Plug.Static serves
  from a different directory than CWD)
- strip_beams: true in release config
- Optimised .dockerignore and .gitignore for mockup variants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 16:21:05 +00:00
jamey
eaa4bbb3fa add CI pipeline with credo and dialyzer
mix ci alias: compile --warning-as-errors, format --check-formatted,
credo, dialyzer, test. Credo configured with sensible defaults.
Dialyzer ignore file for false positives (Stripe types, Mix tasks,
ExUnit internals). Credo fixes: map_join, filter consolidation,
nesting extraction, cond→if simplification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 15:19:42 +00:00
jamey
3b8d5faf3b refactor: consolidate settings lookups and secrets loading
- Extract fetch_setting/1 in Settings (4 callsites → 1 repo lookup)
- Replace hardcoded load_stripe_config with registry-driven load_all
- Adding new secrets is now a one-line @secret_registry entry
- Mark DRY refactor plan as complete (all 8 items done)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:42:13 +00:00
jamey
3eacd91fda refactor: split shop_components.ex into 5 focused sub-modules
4,487-line monolith → 23-line facade + 5 modules:
- Base (inputs, buttons, cards)
- Layout (header, footer, mobile nav, shop_layout)
- Cart (drawer, items, order summary)
- Product (cards, gallery, variant selector, hero)
- Content (rich text, images, contact, reviews)

`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules.
No single file over ~1,600 lines now.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:30:25 +00:00
jamey
cb4698bec8 refactor: extract Cart.build_state/1 as single source of truth for cart state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:24:39 +00:00
jamey
2825537136 refactor: extract common preview assigns helper in theme editor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:12:39 +00:00
jamey
8be1f90f2d refactor: extract shop_layout component to eliminate template boilerplate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:10:08 +00:00
jamey
e6d4fce656 refactor: extract ThemeHook to eliminate mount duplication
on_mount hook assigns theme_settings, generated_css, logo_image,
header_image, and mode for all public shop LiveViews. Removes
~70 lines of identical boilerplate and 18 unused aliases across
7 LiveViews.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 11:59:33 +00:00
jamey
db02c0b414 refactor: use assigns spread in page LiveView render functions
Replace verbose explicit attr passing with {assigns} spread for
home, contact, cart, product show and checkout success LiveViews.
Collection skipped (inline rendering, no template component).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 10:53:06 +00:00
jamey
5a43cfc761 feat: add default content pages for delivery, privacy and terms
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>
2026-02-08 10:47:54 +00:00
jamey
0af8997623 feat: add transactional emails for order confirmation and shipping
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>
2026-02-08 10:17:19 +00:00
jamey
3e19887499 feat: add Printify order submission and fulfilment tracking
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>
2026-02-08 09:51:51 +00:00
jamey
02cdc810f2 feat: add order management admin with list and detail views
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>
2026-02-07 21:59:14 +00:00
jamey
eede9bb517 feat: add encrypted settings, guided Stripe setup, and admin credentials page
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>
2026-02-07 17:12:53 +00:00
jamey
ff1bc483b9 feat: add Stripe checkout, order persistence, and webhook handling
Stripe-hosted Checkout integration with full order lifecycle:
- stripity_stripe ~> 3.2 with sandbox/prod config via env vars
- Order and OrderItem schemas with price snapshots at purchase time
- CheckoutController creates pending order then redirects to Stripe
- StripeWebhookController verifies signatures and confirms payment
- Success page with real-time PubSub updates from webhook
- Shop flash messages for checkout error feedback
- Cart cleared after successful payment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 08:30:17 +00:00
jamey
cff21703f1 fix: update demo content, fix broken links, and add cart item product links
- Replace all placeholder text with demo-aware copy that signals "replace me"
- Update USPs for POD accuracy (made to order, quality materials)
- Fix broken footer links (/delivery, /returns → /contact)
- Add real platform URLs to social icons with target="_blank"
- Make cart item images and names link to product pages
- Switch about page image to responsive_image component
- Add missing cart_status to collection page cart drawer
- Unify search hint text across all page templates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 23:33:22 +00:00
jamey
1bc08bfb23 feat: add cart page, cart drawer, and shared cart infrastructure
- 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>
2026-02-06 19:39:37 +00:00
jamey
880e7a2888 feat: add dynamic variant selector with color swatches
- Fix Printify options parsing (Color/Size were swapped)
- Add extract_option_types/1 for frontend display with hex colors
- Filter option types to only published variants (not full catalog)
- Track selected variant in LiveView with price updates
- Color swatches for color-type options, text buttons for size
- Disable unavailable combinations
- Add startup recovery for stale sync status

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 22:17:48 +00:00
jamey
1b49b470f2 feat: add product image download pipeline for PageSpeed 100%
Downloads Printify CDN images via ImageDownloadWorker, processes
through Media pipeline (WebP conversion, AVIF/WebP variant generation),
and links to ProductImage via new image_id FK.

- Add image_id to product_images table
- ImageDownloadWorker downloads and processes external images
- sync_product_images preserves image_id when URL unchanged
- PreviewData uses local images for responsive <picture> elements
- VariantCache enqueues pending downloads on startup
- mix simpleshop.download_images backfill task

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 00:26:19 +00:00
jamey
c818d0399c feat: wire shop LiveViews to real product data
PreviewData now queries the Products context when real products exist,
falling back to mock data otherwise. Shop pages automatically display
synced Printify products.

Fixes:
- Printify image position was string ("front"), now uses index
- Category extraction improved to match more Printify tags
- ProductShow finds products by slug for real data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 23:07:37 +00:00
jamey
a9c15ea6ae feat: add Printify webhook endpoint for real-time product updates
- Add /webhooks/printify endpoint with HMAC-SHA256 signature verification
- Add Webhooks context to handle product:updated, product:deleted events
- Add ProductDeleteWorker for async product deletion
- Add webhook API methods to Printify client (create, list, delete)
- Add register_webhooks/2 to Printify provider
- Add mix register_webhooks task for one-time webhook registration
- Cache raw request body in endpoint for signature verification

Usage:
1. Generate webhook secret: openssl rand -hex 20
2. Add to provider connection config as "webhook_secret"
3. Register with Printify: mix register_webhooks https://yourshop.com/webhooks/printify

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 22:41:15 +00:00
jamey
5b736b99fd feat: add admin provider setup UI with improved product sync
- 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>
2026-01-31 22:08:34 +00:00
jamey
336b2bb81d chore: apply mix format to codebase
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:24:58 +00:00
jamey
ee1da08941 fix: enable Tidewave remote access properly
Pass allow_remote_access option directly to the Tidewave plug
instead of using application config (which was not being read).
Remove the ineffective config line from dev.exs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:47:58 +00:00
c5c06d9979 feat: add Products context with provider integration (Phase 1)
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>
2026-01-29 20:32:20 +00:00
7d5896a1e3 refactor: add themed form components for consistent shop styling
Adds reusable Phoenix components (shop_input, shop_textarea, shop_select,
shop_button, shop_card) backed by semantic CSS classes (.themed-input,
.themed-button, etc.) to eliminate repeated inline styles across templates.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 19:09:49 +00:00
1b12dc3e7f perf: split CSS bundles for shop and admin pages
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>
2026-01-25 11:36:20 +00:00
9783199691 perf: use digested font paths in CSS and preloads
Add path_resolver parameter to font generation functions so both
font preloads and CSS @font-face declarations use the same digested
paths in production. This prevents duplicate font downloads when
preloads were using digested paths but CSS used non-digested paths.

- Add path_resolver parameter to Fonts.generate_font_faces/2,
  Fonts.preload_links/2, and Fonts.generate_all_font_faces/1
- Update CSSGenerator.generate/2 to accept path_resolver
- Update CSSCache.warm/0 to use Endpoint.static_path/1
- Move CSSCache to start after Endpoint in supervision tree
- Add 1-year cache headers for static assets

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 09:32:06 +00:00
03fb98afc4 chore: add UI styles and update documentation
- Add cart drawer and product gallery thumbnail CSS
- Remove redundant type="text/javascript" attribute
- Update image optimization plan to reflect completion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 00:34:04 +00:00
364ac8fa0e fix: improve accent color contrast for WCAG AA compliance
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>
2026-01-25 00:33:52 +00:00
2c3d8f5647 perf: use responsive images for theme preview mockups
Update theme preview to use optimized responsive images with modern
format support (AVIF/WebP with JPEG fallback).

- Change mockup URLs from .jpg to base paths for srcset generation
- Add source_width to preview products for proper variant selection
- Add responsive_image component with <picture> element
- Update image_text_section to use optimized 800px WebP variant

This ensures the theme preview loads optimal image formats and sizes,
matching the production responsive image behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 00:33:38 +00:00
0ade34d994 feat: add centralized fonts module for dynamic font loading
Create a DRY Fonts module that centralizes all font definitions and
generates @font-face declarations dynamically based on typography preset.

- Add Fonts module with typography font mappings
- Generate @font-face CSS in CSSGenerator based on active preset
- Add font preload links in shop_root layout for performance
- Remove hardcoded font-face declarations from CSS

This improves font loading performance by only loading fonts for the
active typography preset and preloading critical fonts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 00:33:24 +00:00
2bc05097b9 feat: enhance image optimization with on-demand JPEG fallbacks
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>
2026-01-25 00:33:09 +00:00
252ca2268a feat: optimize mockup images with WebP and auto-regeneration
Convert mockup source images from JPG to WebP format for 76% size
reduction (20MB → 4.7MB). Variants are now auto-generated on startup
via Oban, keeping the same DRY approach as database images.

Changes:
- Add OptimizeWorker.enqueue_mockup/1 for filesystem images
- Extend VariantCache to check mockup sources on startup
- Update MockupGenerator to save source as optimized WebP
- Update .gitignore to ignore generated variants
- Convert 55 source mockups from JPG to WebP

The mockup pipeline now uses the same code paths as database images:
- Optimizer.to_optimized_webp/1 for source conversion
- Optimizer.process_file/3 for variant generation
- OptimizeWorker for Oban background processing
- VariantCache for startup cache validation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 00:30:42 +00:00
2b5b749a69 feat: add image optimizer module
- 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>
2026-01-21 22:16:21 +00:00
cefec1aabd feat: add image metadata fields for optimization pipeline
- Add source_width, source_height, variants_status fields to images table
- Remove thumbnail_data (now derived to disk cache)
- Add Oban tables via Oban.Migration.up(version: 12)
- Update Image schema changeset to include new fields

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 22:08:19 +00:00
7fbde87c5b perf: improve SEO and accessibility for PageSpeed
- Add meta description tag with theme_settings.site_description fallback
- Add site_description field to ThemeSettings schema
- Fix color contrast on tertiary text (WCAG AA compliance)
  - Clean mood: #a3a3a3 → #737373
  - Warm mood: #a8a29e → #78716c
  - Cool mood: #94a3b8 → #64748b
- Add width/height attributes to product images to prevent CLS:
  - Product cards: 600x600
  - Cart items: 96x96
  - Gallery thumbnails: 150x150
  - Lightbox: 1200x1200

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:55:55 +00:00
f29772010e fix: resolve nested HTML documents causing LiveView binding errors
The shop.html.heex and shop_root.html.heex were both full HTML documents.
When nested (root layout + live layout), this created invalid HTML with
duplicate <!DOCTYPE>, <html>, <head>, and <body> tags.

This caused:
- "Cannot bind multiple views to the same DOM element" console errors
- Failed Lighthouse audits
- Potential rendering issues

Fix:
- shop_root.html.heex: Now contains the full HTML document with theme
  settings, CSS variables, and data attributes
- shop.html.heex: Now just passes through @inner_content

Results:
- Console errors: Gone
- Best Practices: 96 → 100
- Total Blocking Time: 140ms → 30ms
- HTML validation: Passes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 20:20:39 +00:00
5faa6c4c09 perf: self-host fonts and add /admin route
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>
2026-01-20 22:54:07 +00:00
4b22bb4a4b feat: add mobile bottom navigation bar
Replace cramped horizontal nav on mobile with a fixed bottom tab bar
for thumb-friendly navigation. The header nav is now hidden on mobile
(<768px) and the bottom nav provides Home, Shop, About, and Contact
links with icons.

- Add mobile_bottom_nav component with icon + label nav items
- Active page has accent-colored background highlight and larger icon
- Add shadow to lift nav visually off the page
- Update all page templates with bottom padding and bottom nav
- Remove CSS rule that was overriding Tailwind's hidden class
- Responsive header padding (tighter on mobile)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:03:42 +00:00
9c81f9511d chore: add "No spam" to newsletter description
Addresses the real concern people have about signing up.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:08:48 +00:00
c3f3bc237e chore: simplify newsletter description
Remove marketing fluff "Be the first" - everyone on the list gets
emails at the same time. Just describe what they'll receive.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:08:22 +00:00
a36d8f851c chore: change contact page copy from "us/we" to "me/I"
More personal and authentic for a solo POD seller:
- "Get in touch" instead of "Contact Us"
- "Drop me a message" instead of "Drop us"
- "I'll get back to you" instead of "we'll"
- "Send a message" instead of "Send us a message"
- "How can I help?" instead of "How can we help?"
- "I'll send you a link" instead of "we'll send"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:07:12 +00:00
6e52e03a03 chore: simplify newsletter card title to just "Newsletter"
Minimal and clear - the description does the selling, the button
says what to do.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:04:16 +00:00
8a616b0acd chore: change newsletter default title to "Join the newsletter"
Clear and explicit about what the user is signing up for.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:00:00 +00:00
7ae3af91ba chore: change newsletter default title to "Get updates"
More accurate than "Stay in touch" - newsletters are one-way communication.
Also updated description slightly: "news" instead of "updates" to avoid
repetition with the title.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 20:59:02 +00:00
4fa4a6a83e chore: change social links default title to "Find me online"
More neutral and personal than "Follow us":
- Works for all platform types (GitHub, Ko-fi, etc., not just social follows)
- "me" fits a solo POD seller better than corporate "us"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 20:56:52 +00:00
fc1b7dd708 chore: update demo social links for tech-savvy POD seller persona
Select platforms typical for a quirky, nerdy POD seller:
- Instagram: primary visual portfolio
- Bluesky: nerdy Twitter alternative
- Mastodon: federated/open web presence
- Ko-fi: indie tips and commissions
- GitHub: open source projects

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 19:31:29 +00:00
2ff24197e0 feat: add comprehensive social platform icons using Simple Icons
Add 24 social platform icons from Simple Icons (MIT licensed):
- Commercial/Creative: instagram, pinterest, tiktok, facebook, twitter,
  youtube, patreon, kofi, etsy, gumroad, bandcamp
- Open Web/Federated: mastodon, pixelfed, bluesky, peertube, lemmy, matrix
- Developer/Hacker: github, gitlab, codeberg, sourcehut
- Communication: discord, telegram, signal
- Other: substack, rss, website

Also:
- Redesign social_links_card to single card with compact flex-wrap layout
- Remove redundant response_time text (hero already says "get back to you")

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 19:29:45 +00:00
6b45846d6d feat: enhance contact page with newsletter and social cards
Add newsletter_card component with :card and :inline variants to share
between footer and contact page. Add social_links_card component with
full-width icon+text cards for better discoverability.

Improve contact_form with optional email link and response time display,
keeping important contact info above the fold. Reorganize contact page
layout with form on left, info cards on right.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 19:13:48 +00:00
50d7f135bc fix: improve header navigation accessibility
- Current page in nav is now a span instead of a link (no self-links)
- Logo links to home page, except when already on home
- Use aria-current="page" with accent underline for current page indicator
- Extract logo_content, logo_inner, and nav_item helper components
- Update CSS to target both a and span elements in .shop-nav

This follows WCAG accessibility guidelines - links that point to
the current page are confusing for screen reader users.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 23:43:54 +00:00
fe29c1ad36 feat: add product sorting to collection pages with tests
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>
2026-01-19 23:38:22 +00:00
9fb836ca0d feat: add /collections/:slug routes with category filtering
- Add ShopLive.Collection LiveView for collection pages
- Add products_by_category/1 and category_by_slug/1 to PreviewData
- Support /collections/all for all products view
- Remove /products route and ShopLive.Products (replaced by collections)
- Update all links to use /collections/all instead of /products
- Update category nav to link to /collections/:slug
- Update PDP breadcrumb to link to specific collection

URL structure now follows Shopify convention:
- /collections/all - All products
- /collections/art-prints - Art Prints collection
- /collections/apparel - Apparel collection
- etc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 23:26:41 +00:00
848c4ea146 feat: add navigation and collapsible sidebar to theme editor
- Add "← View Shop" link on admin/theme page for easy navigation
- Add collapsible sidebar with chevron toggle button
- Include proper ARIA attributes for accessibility (aria-label,
  aria-expanded, aria-controls)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 21:37:34 +00:00
a2d655d302 feat: add Cart page and themed error pages
- 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>
2026-01-17 22:29:45 +00:00
c25953780a refactor: consolidate shop and preview page templates
- Create shared PageTemplates module in components/page_templates/
- Shop LiveViews now use explicit render/1 calling shared templates
- Theme preview now uses preview_page/1 component calling shared templates
- Delete duplicate preview_pages directory and shop_live/*.html.heex
- Single source of truth: mode param controls shop vs preview behavior

Templates: home, about, contact, collection, pdp, cart, error

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 22:17:59 +00:00
e02d928815 feat: add Product Detail page to public storefront
Add PDP (Product Detail Page) at /products/:id with full e-commerce
functionality including product gallery, variant selector, quantity
controls, reviews section, and related products.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 21:57:43 +00:00
4f70c6649a feat: add Products listing page to public storefront
- Create ShopLive.Products module and template
- Add /products route to public shop live session
- Shows product grid with category filters and sort dropdown
- Displays all 16 preview products with categories

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 21:54:31 +00:00
5ceff20aaa feat: add Contact page to public storefront
- Create ShopLive.Contact module and template
- Add /contact route to public shop live session
- Includes contact form, order tracking, info cards, social links

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 21:52:11 +00:00
1f8dbd645d feat: add About page to public storefront
- Create ShopLive.About module and template
- Add /about route to public shop live session
- Reuse shop_components for header, footer, hero, rich text

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 21:49:16 +00:00
75206474a1 refactor: consolidate CSS to use .themed class with native nesting
- 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>
2026-01-17 21:43:26 +00:00
0157f20ae9 fix: update shop layout and CSS selectors for shop-root
- Fix asset paths in shop layout (css/app.css, js/app.js)
- Add Google Fonts preconnect and stylesheet link
- Update theme-layer2-attributes.css to target both .preview-frame
  and .shop-root so theme styles apply to real shop pages
- Properly duplicate attribute selectors (e.g., [data-mood="warm"])
  for both .preview-frame and .shop-root

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 16:25:52 +00:00
88636db9d2 feat: add shop storefront with optimized theme CSS
- 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>
2026-01-17 16:19:35 +00:00
97981a9884 refactor: extract remaining PDP components to ShopComponents
Add PDP-specific components:
- product_gallery with lightbox
- product_info (title, price, sale badge)
- variant_selector
- quantity_selector
- add_to_cart_button
- product_details accordion
- star_rating
- trust_badges
- reviews_section with review_card

Add page layout components:
- page_title for consistent h1 styling
- cart_layout for cart page structure
- rich_text for structured content blocks
- accordion_item for generic collapsible sections

Update preview pages to be fully component-based:
- PDP: 415 → 48 lines (88% reduction)
- Cart: 47 → 23 lines
- About: 65 → 27 lines

Add preview data functions:
- reviews() for product reviews
- about_content() for rich text blocks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 15:37:58 +00:00
0c15929c19 refactor: extract remaining page sections to ShopComponents
Add reusable components for all page sections:
- category_nav: Category circles for homepage navigation
- featured_products_section: Product grid with title and view-all CTA
- image_text_section: Two-column image + text layout
- collection_header: Page header with title and product count
- filter_bar: Category pills and sort dropdown
- content_body: Long-form content wrapper for about page
- contact_form: Contact form card
- order_tracking_card: Order tracking input card
- info_card: Bullet-point info card
- contact_info_card: Email contact card with icon
- social_links: Social media icon links
- cart_item: Cart item row with quantity controls
- order_summary: Order totals and checkout card
- breadcrumb: Navigation breadcrumb trail
- related_products_section: Related products grid

All preview pages now compose entirely of reusable components,
making them easier to maintain and enabling future section-based
theme customization.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 15:14:25 +00:00
1589ebaeca refactor: expand hero_section with page and error variants
Add variant support to hero_section component:
- :default - Standard hero with section wrapper (home, about)
- :page - Page header style with larger title, more spacing (contact)
- :error - Error page with pre-title (404), dual buttons (error)

Now used in: home, about, contact, error pages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:57:31 +00:00
f5b7693b96 refactor: extract hero_section to shared ShopComponents module
Create a centered hero section component with:
- Title (h1) and description (p)
- Optional CTA button with preview/live mode support
- Configurable background (:base or :sunken)

Used in: home page (with CTA), about page (without CTA)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:54:11 +00:00
b2869514cb refactor: extract product_grid to shared ShopComponents module
Create a reusable product grid component that handles responsive
column layouts. Supports two modes:

- Theme-based columns: Uses theme_settings.grid_columns for lg breakpoint
- Fixed columns: Use columns={:fixed_4} for 2/4 column layouts

Used in: home (featured), collection, pdp (related), error (suggestions)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:45:34 +00:00
9746bf183c refactor: extract product_card to shared ShopComponents module
Create a reusable product card component with four variants:
- :default (collection page) - full details with category
- :featured (home page) - hover animation, badges
- :compact (pdp related) - smaller, no badges/delivery
- :minimal (error 404) - smallest, not clickable

Accessibility improvements:
- Use <a> for all clickable cards (keyboard nav, screen readers)
- Use <div> only for non-clickable decorative cards

Unified badge logic with priority: Sold out > New > Sale

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:38:16 +00:00
50941d278f refactor: extract cart_drawer to shared ShopComponents module
Move the cart drawer component from ThemeLive.PreviewPages to the
shared ShopComponents module. The component now supports:
- mode attribute (:live for real stores, :preview for theme editor)
- subtotal attribute (default nil shows "£0.00")
- cart_items attribute (default empty list)

In preview mode, "View basket" navigates via LiveView JS commands.
In live mode, it links directly to /cart.

Preview pages now explicitly pass demo values:
  <.cart_drawer cart_items={...} subtotal="£72.00" mode={:preview} />

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:11:23 +00:00
5473337894 refactor: extract shop_header to shared ShopComponents module
Move the shop header component from ThemeLive.PreviewPages to the
shared ShopComponents module. The component now supports:
- mode attribute (:live for real stores, :preview for theme editor)
- cart_count attribute (default 0, preview pages pass 2)
- Navigation links render conditionally based on mode

Preview pages now call <.shop_header ... mode={:preview} cart_count={2} />

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:09:43 +00:00
c72f6446a4 refactor: extract shop_footer to shared ShopComponents module
Move the footer from ThemeLive.PreviewPages to the shared ShopComponents
module. Add mode attribute (:live vs :preview) for navigation behavior.
Preview mode uses phx-click handlers, live mode uses real URLs.
Also makes copyright year dynamic.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:06:28 +00:00
14b1af5314 refactor: extract search_modal to shared ShopComponents module
Move the search modal from ThemeLive.PreviewPages to the shared
ShopComponents module. Add optional hint_text attribute - preview
pages pass demo hint text while real stores can omit it.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:05:00 +00:00
0e998fdac9 refactor: extract skip_link to shared ShopComponents module
Move the accessibility skip link from ThemeLive.PreviewPages to the
shared ShopComponents module for reuse on public storefront pages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 13:51:15 +00:00
5f3efebdfc refactor: extract announcement_bar to shared ShopComponents module
Move announcement_bar from ThemeLive.PreviewPages to a new shared
SimpleshopThemeWeb.ShopComponents module. This establishes the pattern
for Phase 9 storefront integration where components need to work in
both the admin theme preview and public storefront pages.

Changes:
- Create lib/simpleshop_theme_web/components/shop_components.ex
- Add optional message attribute (defaults to "Free delivery over £40")
- Import ShopComponents in html_helpers for global availability
- Import ShopComponents in PreviewPages for embedded template access
- Update all 7 preview templates to use short-form <.announcement_bar>
- Remove original announcement_bar/1 from PreviewPages (now unused)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 13:15:46 +00:00
d4dbd8998f fix: resolve compilation warnings and update tests to match implementation
- 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
2026-01-15 22:36:15 +00:00
974d91ce33 feat: implement professional typography system with curated font pairings
Typography Presets (research-backed pairings):
- clean: Manrope + Inter (minimal, modern)
- editorial: Playfair Display + Raleway (fashion, lifestyle)
- modern: Space Grotesk + Inter (tech, futuristic)
- classic: Cormorant Garamond + Source Serif 4 (luxury, elegant)
- friendly: Fraunces + Work Sans (playful, quirky)
- minimal: DM Sans + Source Serif 4 (design-forward)
- impulse: Raleway + Inter (wellness, beauty)

Type Scale & Line Heights:
- Major Third (1.25) ratio for mathematical harmony
- H1: line-height 1.1, letter-spacing -0.025em
- H2: line-height 1.15, letter-spacing -0.02em
- H3: line-height 1.2, letter-spacing -0.015em
- Body: line-height 1.5 (WCAG compliant)
- Small text: letter-spacing +0.01em for readability

Fluid Typography:
- Headings use clamp() for smooth mobile→desktop scaling
- Display: 36px→48px, XL: 30px→40px, LG: 24px→32px

Performance:
- Variable font loading where available (Inter, Manrope, etc.)
- Removed unused fonts (Libre Baskerville, Nunito, Source Sans)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 01:16:21 +00:00
aa469ffb50 feat: implement UX pattern improvements for accessibility & performance
Accessibility:
- Add skip link component for keyboard navigation
- Add visible focus rings on all interactive elements
- Add aria-current="page" to navigation active states
- Ensure 44px minimum touch targets on header icons and filter pills

Product Page (PDP):
- Add accordion layout for Description, Size Guide, Shipping & Returns
- Convert Reviews section to accordion format (open by default)
- Make Add to Basket button sticky on mobile, normal on desktop

Product Cards (home & collection):
- Add "Free delivery over £40" shipping badge
- Add loading="lazy" and decoding="async" to images

Cart Drawer:
- Add "Delivery: Calculated at checkout" label
- Add Remove button to each cart item

All Preview Pages:
- Add skip link to all 7 preview pages
- Wrap main content in <main id="main-content">
- Pass active_page to shop_header for nav highlighting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 00:24:25 +00:00
0c43d65a04 feat: add automated Printify mockup generation & POD sample content
Printify Integration:
- Add Printify API client module with full HTTP wrapper
- Add mockup generator with dynamic "cover" scaling algorithm
- Create Mix task (mix generate_mockups) for automated mockup generation
- Support --cleanup flag to delete products after downloading mockups
- Calculate optimal scale factor based on artwork/placeholder aspect ratios
- Handle landscape artwork on portrait print areas without white space

Sample Content (16 products across 5 POD categories):
- Art Prints: Mountain Sunrise, Ocean Waves, Wildflower Meadow, Geometric Abstract, Botanical Illustration
- Apparel: Forest Silhouette T-Shirt, Forest Light Hoodie
- Tote Bags: Wildflower Meadow, Sunset Gradient
- Homewares: Fern Leaf Mug, Ocean Waves Cushion, Night Sky Blanket
- Stationery: Autumn Leaves Notebook, Monstera Leaf Notebook
- Accessories: Monstera Leaf Phone Case, Blue Waves Laptop Sleeve

Preview Data Updates:
- Replace generic e-commerce products with POD-focused items
- Update categories to POD-relevant: Art Prints, Apparel, Homewares, Stationery, Accessories
- Update cart drawer items to match new product range
- Refresh testimonials with POD-appropriate reviews

Theme Content Updates:
- Update hero section for "Wildprint Studio" brand identity
- Rewrite about page narrative with humble, British, personal tone
- Update search hints to nature/POD relevant terms
- Add mockups directory to static paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 23:35:18 +00:00
37653e5e7a feat: redesign contact page for POD sellers & add theme enhancements
Contact page redesign:
- Replace retail-style contact info (phone, address, hours) with POD-appropriate layout
- Add order tracking card with email input
- Add "Handy to know" section with printing/delivery/returns info
- Add email contact with response time promise
- Add social links (Instagram, Pinterest)
- Update intro text to be warmer and more personal

Collection page improvements:
- Replace sidebar filters with horizontal category pills
- Add filter pill CSS with theme token integration

PDP enhancements:
- Add image lightbox with keyboard navigation
- Add thumbnail gallery with active state
- Add reviews section (toggleable)
- Add related products section (toggleable)
- Add trust badges section (toggleable)

Theme system additions:
- Add button_style setting (filled/outline/soft)
- Add product_text_align setting (left/center)
- Add image_aspect_ratio setting (square/portrait/landscape)
- Add responsive form layouts with flex-wrap

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 13:48:03 +00:00
98a9e3b3d4 fix: adjust content and demo to be UK-centric 2026-01-01 16:52:43 +00:00
a8c0e150c8 feat: enhance theme customization with layout controls and real product images
Add comprehensive layout and styling controls including header layout options (standard, centered, left), content width settings (contained, wide, full), and card shadow levels. Update all theme presets with these new settings. Replace placeholder images with real Unsplash product and category images for more realistic previews. Add announcement bar and sticky header toggle options for enhanced header customization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 16:16:05 +00:00
1ca703e548 feat: add dark mode support, accordion UI, and current combination display
- 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>
2025-12-31 18:55:44 +00:00
0dada968aa feat: add ColorSync hook to sync color picker and text input
The color picker and text input for accent color weren't syncing properly when the user changed the color picker value. This was because LiveView doesn't update input values that might have user focus, to avoid interfering with user input.

Added a JavaScript LiveView hook (ColorSync) that:
- Listens to 'input' events on both the color picker and text input
- Syncs their values in real-time as the user interacts with either one
- Provides immediate visual feedback when changing colors via the picker

The hook is attached to the accent color form with phx-hook="ColorSync" and syncs the two inputs bidirectionally, ensuring they always display the same value.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 01:00:22 +00:00
53828c3a2a fix: remove hardcoded accent color values from theme-semantic.css
The accent color HSL components (--t-accent-h, --t-accent-s, --t-accent-l) were hardcoded in :root, which prevented the dynamically generated values from the CSS generator from taking effect properly.

Now the HSL components are only set by the CSS generator in .preview-frame, and theme-semantic.css only defines the derived colors that use those variables.

Also wrapped accent color inputs in a form element as required by Phoenix LiveView for phx-change events.

Verified that changing presets properly updates button colors (e.g., studio preset → blue buttons).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 00:55:25 +00:00
8aedb3466a feat: implement density-aware spacing system
- Move density-aware spacing variables from :root to .preview-frame in theme-layer2-attributes.css
  This ensures the variables can reference the correct --t-density value set by data attributes
- Remove density variables from theme-semantic.css to avoid CSS variable scoping issues
- Update home.html.heex to use var(--space-*) instead of Tailwind spacing classes
  Hero section, product grid, and cards now respond to density changes
- Verified all three density modes work correctly (compact: 0.85, balanced: 1, spacious: 1.25)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 00:51:28 +00:00
0871570b7e fix: support grid-cols-4, accent color, and header layout controls
- Fix grid columns 4 by using conditional logic instead of string interpolation
- Simplify CSS generator to only generate accent colors (mood/typography/shape/density now use data attributes)
- Add header component to all 7 preview pages with logo, nav, and cart
- Add header layout CSS for centered and minimal variants
- Move nav display property to CSS to enable minimal mode hiding

This resolves all high-priority theme control issues:
- Grid columns now supports 2, 3, and 4 columns
- Accent color picker now updates button colors
- Header layout control now works (standard, centered, minimal)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 00:45:14 +00:00
476ec9667a fix: add data attributes and Google Fonts to enable theme visual changes
- 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>
2025-12-31 00:24:53 +00:00
6a3069f854 feat: add preview page templates with theme styling
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>
2025-12-30 22:06:04 +00:00
da770f121f feat: add Theme LiveView with preset switching
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>
2025-12-30 21:53:52 +00:00
41f488c2b6 feat: add smart preview data system with mock fallback
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>
2025-12-30 21:46:54 +00:00
878d8f63ac feat: add CSS generation system with custom properties and ETS cache
- Create theme-primitives.css with spacing, fonts, radius scales
- Create theme-semantic.css with semantic CSS variable aliases
- Update app.css to import theme CSS files
- Add CSSGenerator module for dynamic CSS token generation
  - Generates mood variables (neutral, warm, cool, dark)
  - Generates typography variables (7 font combinations)
  - Generates shape variables (sharp, soft, round, pill)
  - Generates density variables (spacious, balanced, compact)
  - Converts hex colors to HSL for flexible manipulation
- Add CSSCache GenServer with ETS table for performance
  - Caches generated CSS to avoid regeneration
  - Warms cache on application startup
  - Provides invalidation for theme updates
- Add CSSCache to application supervision tree
- Add comprehensive tests for CSS generation (29 tests)
- Add comprehensive tests for preset validation (14 tests)
- All tests passing (58 total tests, 0 failures)
- Verified CSS generation and caching work correctly in IEx
2025-12-30 21:41:25 +00:00
a401365943 feat: add Settings and Media contexts with theme settings schema
- 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)
2025-12-30 21:35:52 +00:00
bb4633895c add Tidewave 2025-12-30 12:27:41 +00:00
9b73fcdf7a mix phx.gen.auth Accounts User users 2025-12-30 12:26:46 +00:00
4f2ed90044 mix phx.new simpleshop_theme --database sqlite3 --adapter bandit --binary-id 2025-12-30 12:26:26 +00:00