simpleshop_theme/SIMPLESHOP_THEME_STUDIO_SPEC.md
Jamey Greenwood 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

424 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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"