# SimpleShop Theme Studio - Complete Implementation Summary ## Overview This document summarises the complete Theme Studio feature developed for SimpleShop - an open-source POD (print-on-demand) e-commerce platform built with Phoenix/Elixir/LiveView. The Theme Studio allows sellers to customise their shop's appearance through a constrained but flexible system of presets and options. ## Design Philosophy ### Core Principles 1. **"One theme, infinite variations"** - Rather than offering multiple themes, we provide one solid foundation with curated customisation options 2. **Constrained creativity** - Limit choices to prevent poor design outcomes while maintaining perceived variety 3. **No professional photography required** - Defaults work well with product mockups, not just lifestyle imagery 4. **Mobile-first** - All features work on touch devices (no hover-only interactions) 5. **Ethical design** - No dark patterns like countdown timers or fake urgency ### Target Audience - Solo POD creators (artists, illustrators, designers) - Small catalogs (typically <50 products) - Non-technical users who found WooCommerce too complex - Budget-conscious sellers (£5-10/month target price) ## Feature Architecture ### Preset System Nine curated presets that combine multiple settings into cohesive looks: ```elixir @presets %{ gallery: %{ mood: "warm", typography: "editorial", shape: "soft", density: "spacious", grid: "3", header: "centered", accent: "#e85d04" }, studio: %{ mood: "neutral", typography: "clean", shape: "soft", density: "balanced", grid: "4", header: "standard", accent: "#3b82f6" }, boutique: %{ mood: "warm", typography: "classic", shape: "soft", density: "balanced", grid: "3", header: "centered", accent: "#b45309" }, bold: %{ mood: "neutral", typography: "modern", shape: "sharp", density: "compact", grid: "4", header: "standard", accent: "#dc2626" }, playful: %{ mood: "neutral", typography: "friendly", shape: "pill", density: "balanced", grid: "4", header: "standard", accent: "#8b5cf6" }, minimal: %{ mood: "cool", typography: "minimal", shape: "sharp", density: "spacious", grid: "2", header: "minimal", accent: "#171717" }, night: %{ mood: "dark", typography: "modern", shape: "soft", density: "balanced", grid: "4", header: "standard", accent: "#f97316" }, classic: %{ mood: "warm", typography: "classic", shape: "soft", density: "spacious", grid: "3", header: "standard", accent: "#166534" }, impulse: %{ mood: "neutral", typography: "impulse", shape: "sharp", density: "spacious", grid: "3", header: "centered", accent: "#000000", font_size: "medium", heading_weight: "regular", layout_width: "full", button_style: "filled", card_shadow: "none", product_text: "center" } } ``` ### Customisation Options #### Typography Styles | Style | Heading Font | Body Font | Weight | Use Case | |-------|-------------|-----------|--------|----------| | clean | Inter | Inter | 600 | Default, versatile | | editorial | Fraunces (serif) | Source Sans | 600 | Art galleries, editorial | | modern | Space Grotesk | Space Grotesk | 500 | Tech, contemporary | | classic | Libre Baskerville | Source Sans | 400 | Traditional, luxury | | friendly | Nunito | Nunito | 700 | Playful, approachable | | minimal | Outfit | Outfit | 300 | Ultra-clean, light | | impulse | Nunito Sans | Nunito Sans | 300 | Fashion editorial | #### Colour Moods | Mood | Background | Text | Border | Use Case | |------|------------|------|--------|----------| | neutral | #ffffff | #171717 | #e5e5e5 | Default, works with any accent | | warm | #fdf8f3 | #1c1917 | #e7e0d8 | Cosy, artisan, handmade | | cool | #f4f7fb | #0f172a | #d4dce8 | Tech, modern, professional | | dark | #0a0a0a | #fafafa | #262626 | Premium, dramatic, night mode | #### Shape Options | Shape | Border Radius | Use Case | |-------|--------------|----------| | sharp | 0 | Modern, editorial, bold | | soft | 0.5rem | Default, approachable | | round | 0.75-1rem | Friendly, playful | | pill | 9999px (buttons) | Fun, casual, rounded | #### Density Options | Density | Multiplier | Use Case | |---------|------------|----------| | spacious | 1.25x | Editorial, luxury, few products | | balanced | 1x | Default, most stores | | compact | 0.75x | Large catalogs, utilitarian | #### Layout Options - **Grid columns**: 2, 3, or 4 products per row - **Header layout**: Standard (left logo), Centered, Minimal - **Layout width**: Contained (1200px), Wide (1400px), Full width - **Button style**: Filled, Outline, Soft - **Card shadow**: None, Subtle, Pronounced - **Product text alignment**: Left, Center - **Image aspect ratio**: Square, Portrait, Landscape ### Branding Options #### Logo Modes 1. **Text only** - Shop name as styled text 2. **Logo + text** - Logo image alongside shop name 3. **Logo only** - Just the logo image 4. **Header image** - Full-width header background 5. **Logo + header image** - Both logo and header background #### Logo Features - Upload support (PNG, JPG, WebP, SVG) - Size slider (24-120px) - SVG recolouring option (change logo colour to match theme) #### Header Image Features - Background image upload - Zoom control (100-200%) - Horizontal position (0-100%) - Vertical position (0-100%) ### Toggle Features - Announcement bar (on/off) - Sticky header (on/off) - Second image on hover (on/off) - Quick add button (on/off) - Show prices (on/off) - Trust badges on PDP (on/off) - Reviews section on PDP (on/off) - Related products on PDP (on/off) ## Data Model ### Theme Settings Schema ```elixir defmodule SimpleShop.Shops.ThemeSettings do use Ecto.Schema import Ecto.Changeset embedded_schema do # Core preset (optional - if set, provides defaults) field :preset, :string # Branding field :shop_name, :string field :logo_mode, :string, default: "text-only" field :logo_url, :string field :logo_size, :integer, default: 36 field :logo_recolor, :boolean, default: false field :logo_color, :string, default: "#171717" field :header_image_url, :string field :header_zoom, :integer, default: 100 field :header_position_x, :integer, default: 50 field :header_position_y, :integer, default: 50 # Theme tokens field :mood, :string, default: "neutral" field :typography, :string, default: "clean" field :shape, :string, default: "soft" field :density, :string, default: "balanced" field :accent_color, :string, default: "#f97316" field :hover_color, :string field :sale_color, :string, default: "#dc2626" # Layout field :grid_columns, :integer, default: 4 field :header_layout, :string, default: "standard" field :layout_width, :string, default: "wide" field :font_size, :string, default: "medium" field :heading_weight, :string, default: "bold" field :button_style, :string, default: "filled" field :card_shadow, :string, default: "none" field :product_text_align, :string, default: "left" field :image_aspect_ratio, :string, default: "square" field :gallery_position, :string, default: "left" # Feature toggles field :announcement_bar, :boolean, default: true field :sticky_header, :boolean, default: false field :hover_image, :boolean, default: true field :quick_add, :boolean, default: true field :show_prices, :boolean, default: true field :pdp_trust_badges, :boolean, default: true field :pdp_reviews, :boolean, default: true field :pdp_related_products, :boolean, default: true end end ``` ### CSS Custom Properties The theme system uses CSS custom properties for real-time updates. Key variables: ```css /* Primitives (fixed) */ --p-space-1 through --p-space-24 --p-radius-none through --p-radius-full --p-font-inter, --p-font-fraunces, etc. --p-text-xs through --p-text-4xl /* Theme tokens (dynamic) */ --t-surface-base, --t-surface-raised, --t-surface-sunken --t-text-primary, --t-text-secondary, --t-text-tertiary --t-border-default, --t-border-subtle --t-accent (HSL-based for easy manipulation) --t-font-heading, --t-font-body --t-heading-weight, --t-heading-tracking --t-radius-button, --t-radius-card, --t-radius-input --t-density (multiplier) /* Semantic aliases */ --color-page, --color-card, --color-heading, --color-body --font-heading, --font-body, --weight-heading --space-xs through --space-2xl --radius-button, --radius-card ``` ## LiveView Implementation Notes ### Real-time Preview The theme editor should provide instant visual feedback. In Phoenix LiveView: ```elixir defmodule SimpleShopWeb.ThemeEditorLive do use SimpleShopWeb, :live_view def mount(_params, _session, socket) do {:ok, assign(socket, settings: default_settings(), preview_page: "home" )} end def handle_event("update_setting", %{"key" => key, "value" => value}, socket) do settings = Map.put(socket.assigns.settings, String.to_atom(key), value) {:noreply, assign(socket, settings: settings)} end def handle_event("apply_preset", %{"preset" => preset_name}, socket) do preset = Map.get(@presets, String.to_atom(preset_name)) settings = Map.merge(socket.assigns.settings, preset) {:noreply, assign(socket, settings: settings)} end def handle_event("change_preview_page", %{"page" => page}, socket) do {:noreply, assign(socket, preview_page: page)} end end ``` ### CSS Generation Generate CSS custom properties from settings: ```elixir defmodule SimpleShop.Theme.CSSGenerator do def generate_css(settings) do """ :root { --t-accent-h: #{accent_hue(settings.accent_color)}; --t-accent-s: #{accent_saturation(settings.accent_color)}%; --t-accent-l: #{accent_lightness(settings.accent_color)}%; /* ... other properties */ } #{mood_css(settings.mood)} #{typography_css(settings.typography)} #{shape_css(settings.shape)} #{density_css(settings.density)} """ end end ``` ## File Uploads ### Logo Upload - Accepted formats: PNG, JPG, WebP, SVG - Max size: 2MB recommended - SVG special handling: Store raw content for recolouring feature - Storage: Local or S3-compatible (user's choice for data sovereignty) ### Header Image Upload - Accepted formats: PNG, JPG, WebP - Max size: 5MB recommended - Responsive serving: Generate multiple sizes ## Preview Pages The demo includes 7 preview pages to show theme in context: 1. **Home** - Hero, categories, featured products, testimonials 2. **Collection** - Product grid with filters 3. **Product (PDP)** - Gallery, details, add to cart, reviews 4. **Cart** - Line items, totals, checkout button 5. **About** - Brand story, values 6. **Contact** - Contact form, details 7. **Error (404)** - Error state styling ## Research Findings: POD Theme Best Practices ### What POD Sellers Actually Use - **Free themes dominate**: Dawn, Spotlight, Studio most popular - **Premium choice**: Streamline ($350) best for growing POD brands - **Impulse** is fashion-focused, not ideal POD default ### Key Requirements for POD 1. Large product imagery (mockups need to shine) 2. Clean/minimal design (products are the focus) 3. Quick setup (non-technical users) 4. Mobile-responsive (60%+ traffic) 5. Works with small catalogs 6. No reliance on lifestyle photography ### What to Avoid - Countdown timers (dark pattern) - Complex promotional systems - Hover-only interactions - Features requiring professional photography - Enterprise complexity ## Recommended Next Steps for Phoenix Implementation ### Phase 1: Core Theme System 1. Create ThemeSettings schema and migrations 2. Build CSS generator module 3. Implement preset system 4. Create basic LiveView editor with sidebar controls ### Phase 2: Branding 1. Logo upload with LiveView uploads 2. SVG parsing and recolouring 3. Header image with positioning controls ### Phase 3: Preview System 1. Live preview component 2. Page switching (home/collection/product/etc.) 3. Mock data for preview products ### Phase 4: Persistence 1. Save to shop record 2. Apply to storefront templates 3. CSS caching strategy ## Prototype File The complete working HTML prototype is available at: - `/home/claude/theme-demo-v28.html` - `/mnt/user-data/outputs/theme-demo-v28.html` This 6,277-line file contains all CSS, HTML structure, and JavaScript logic that can be referenced when building the Phoenix/LiveView implementation. ## Combination Count With current options, the system offers: - 4 moods × 7 typographies × 4 shapes × 3 densities × 3 grids × 3 headers = **3,024 base combinations** - Plus accent colours, layout width, button styles, shadows, etc. - Marketing claim: "100,000+ possible combinations"