docs: reorganize documentation and add ROADMAP
- Rewrite README.md with proper project overview, setup, and structure - Create ROADMAP.md capturing future improvements and known gaps - Move reference docs to docs/ directory: - docs/spec.md (theme system specification) - docs/plans/sample-content.md (POD content refresh plan) - docs/plans/page-builder.md (existing) - docs/research/typography.md - docs/research/ux-patterns.md - Delete obsolete planning files: - PLAN.md (work complete) - PHASE_9_PLAN.md (work complete) - PHASE_9_PROGRESS.md (stale tracker) - RECENT_CHANGES.md (stale) - Keep AGENTS.md (Phoenix codegen guidelines) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
335
docs/plans/sample-content.md
Normal file
335
docs/plans/sample-content.md
Normal file
@@ -0,0 +1,335 @@
|
||||
# Plan: POD Sample Content Refresh - "Curated Mix" Approach
|
||||
|
||||
## Goal
|
||||
Replace the current mixed sample data with a POD-focused "curated mix" that:
|
||||
1. Covers all types of POD sellers (art prints, apparel, homewares, accessories)
|
||||
2. Uses nature/natural as the primary vibe but includes variety
|
||||
3. Shows different "artist styles" to demonstrate theme versatility
|
||||
4. Uses realistic product mockups generated via Printify
|
||||
|
||||
## Design Concept
|
||||
|
||||
**Shop Identity:** "Wildprint Studio"
|
||||
- Primary vibe: Nature/organic/botanical
|
||||
- Secondary styles: Bold/graphic, minimalist geometric (to show versatility)
|
||||
- UK-focused (prices in £, UK shipping references)
|
||||
|
||||
### Categories (5 POD-relevant)
|
||||
1. **Art Prints** - Wall art, posters, framed prints
|
||||
2. **Apparel** - T-shirts, hoodies, tote bags
|
||||
3. **Homewares** - Mugs, cushions, blankets
|
||||
4. **Stationery** - Notebooks, cards, calendars
|
||||
5. **Accessories** - Phone cases, laptop sleeves
|
||||
|
||||
### Products (16 total, varied styles)
|
||||
|
||||
**Nature Style (10 products):**
|
||||
- Mountain Sunrise Art Print
|
||||
- Wildflower Meadow Tote Bag
|
||||
- Fern Leaf Mug
|
||||
- Ocean Waves Cushion
|
||||
- Autumn Leaves Notebook
|
||||
- Forest Silhouette T-Shirt
|
||||
- Night Sky Throw Blanket
|
||||
- Monstera Leaf Phone Case
|
||||
- Botanical Illustration Art Print (NEW)
|
||||
- Forest Light Hoodie (NEW)
|
||||
|
||||
**Minimalist/Geometric Style (3 products):**
|
||||
- Geometric Abstract Art Print
|
||||
- Abstract Shapes Notebook
|
||||
- Blue Waves Laptop Sleeve (NEW)
|
||||
|
||||
**Bold/Graphic Style (3 products):**
|
||||
- Tropical Leaves Poster
|
||||
- Mountain Peaks Print
|
||||
- Sunset Gradient Tote Bag (NEW)
|
||||
|
||||
---
|
||||
|
||||
## Artwork for Printify Mockups (VERIFIED URLs)
|
||||
|
||||
### Art Prints (to render on: Premium Matte Poster)
|
||||
|
||||
| Design Name | Unsplash URL | Description |
|
||||
|-------------|--------------|-------------|
|
||||
| Mountain Sunrise | https://unsplash.com/photos/mountain-range-under-golden-hour-UweNcthlmDc | Mountain range at golden hour by Alice Donovan Rouse |
|
||||
| Ocean Waves | https://unsplash.com/photos/the-sun-is-setting-over-the-ocean-with-waves-XRhUTUVuXAE | Sunset over ocean waves |
|
||||
| Wildflower Meadow | https://unsplash.com/photos/a-field-of-flowers-with-a-mountain-in-the-background-6hPfsDGtBgI | Field of flowers with mountain backdrop |
|
||||
| Geometric Abstract | https://unsplash.com/photos/abstract-geometric-shapes-form-a-minimalist-pattern--6GvTDpkkPU | Abstract geometric shapes by Pawel Czerwinski |
|
||||
|
||||
### Apparel (to render on: Unisex T-Shirt, Tote Bag)
|
||||
|
||||
| Design Name | Unsplash URL | Product Type | Description |
|
||||
|-------------|--------------|--------------|-------------|
|
||||
| Forest Silhouette | https://unsplash.com/photos/silhouette-photography-of-trees-EhvMzMRO4_o | T-Shirt | Trees silhouette at dawn |
|
||||
| Wildflower Meadow | (same as above) | Tote Bag | Field of flowers |
|
||||
|
||||
### Homewares (to render on: Mug, Cushion, Blanket)
|
||||
|
||||
| Design Name | Unsplash URL | Product Type | Description |
|
||||
|-------------|--------------|--------------|-------------|
|
||||
| Fern Leaf | https://unsplash.com/photos/close-up-of-vibrant-green-fern-leaves-in-soft-light-bYiJojtkHnc | Mug | Vibrant green fern by Aaron Burden |
|
||||
| Ocean Waves | (same as above) | Cushion | Ocean sunset |
|
||||
| Night Sky | https://unsplash.com/photos/milky-way-and-stars-in-a-dark-night-sky-oQR1B87HsNs | Blanket | Milky way stars by Tobias Rademacher |
|
||||
|
||||
### Stationery (to render on: Hardcover Journal/Notebook)
|
||||
|
||||
| Design Name | Unsplash URL | Description |
|
||||
|-------------|--------------|-------------|
|
||||
| Autumn Leaves | https://unsplash.com/photos/selective-focus-photography-of-orange-leaves-Aa3ALtIxEGY | Orange autumn leaves by Aaron Burden |
|
||||
| Monstera Leaf | https://unsplash.com/photos/green-monstera-leaves-with-water-droplets-hETU8_b2IM0 | Monstera with water droplets |
|
||||
|
||||
### Accessories (to render on: Phone Case, Laptop Sleeve)
|
||||
|
||||
| Design Name | Unsplash URL | Description |
|
||||
|-------------|--------------|-------------|
|
||||
| Monstera Leaf | (same as above) | Tropical monstera |
|
||||
| Blue Waves | https://unsplash.com/photos/blue-waves-form-a-soft-abstract-gradient-dYksH3vHorc | Blue abstract gradient waves |
|
||||
|
||||
### Additional Artwork for 16 Products
|
||||
|
||||
| Design Name | Unsplash URL | Description |
|
||||
|-------------|--------------|-------------|
|
||||
| Botanical Illustration | https://unsplash.com/photos/a-drawing-of-a-plant-with-roots-and-flowers-FNtNIDQWUZY | Vintage botanical drawing |
|
||||
| Forest Light | https://unsplash.com/photos/sunlight-filters-through-a-peaceful-forest-clearing-FwVkxITt8Bg | Sunlight through forest clearing |
|
||||
| Sunset Gradient | https://unsplash.com/photos/the-sun-is-setting-over-the-ocean-with-waves-XRhUTUVuXAE | (reuse Ocean Waves for gradient effect) |
|
||||
|
||||
### About Page Image (NOT a product - just for about page)
|
||||
|
||||
| Design Name | Unsplash URL | Description |
|
||||
|-------------|--------------|-------------|
|
||||
| Forest Clearing | https://unsplash.com/photos/sunlight-filters-through-a-peaceful-forest-clearing-FwVkxITt8Bg | Peaceful forest with sunlight (no road) |
|
||||
| OR White Flowers Golden Hour | https://unsplash.com/photos/auXdimpx7K8 | White flowers in field at golden hour |
|
||||
|
||||
---
|
||||
|
||||
## Printify Product Mapping (for mockup generation) - 16 PRODUCTS
|
||||
|
||||
| Product Name | Printify Product | Artwork to Use |
|
||||
|--------------|------------------|----------------|
|
||||
| Mountain Sunrise Art Print | Premium Matte Poster (A3/A4) | Mountain Sunrise |
|
||||
| Ocean Waves Art Print | Premium Matte Poster | Ocean Waves |
|
||||
| Wildflower Meadow Art Print | Premium Matte Poster | Wildflower Meadow |
|
||||
| Geometric Abstract Art Print | Premium Matte Poster | Geometric Abstract |
|
||||
| Botanical Illustration Print | Premium Matte Poster | Botanical Illustration |
|
||||
| Forest Silhouette T-Shirt | Bella+Canvas 3001 Unisex Tee | Forest Silhouette |
|
||||
| Forest Light Hoodie | Gildan 18500 Heavy Blend Hoodie | Forest Light |
|
||||
| Wildflower Meadow Tote Bag | Cotton Canvas Tote | Wildflower Meadow |
|
||||
| Sunset Gradient Tote Bag | Cotton Canvas Tote | Ocean Waves (cropped) |
|
||||
| Fern Leaf Mug | White Glossy Mug 11oz | Fern Leaf |
|
||||
| Ocean Waves Cushion | Spun Polyester Pillow | Ocean Waves |
|
||||
| Night Sky Blanket | Sherpa Fleece Blanket | Night Sky |
|
||||
| Autumn Leaves Notebook | Hardcover Journal | Autumn Leaves |
|
||||
| Monstera Leaf Notebook | Hardcover Journal | Monstera Leaf |
|
||||
| Monstera Leaf Phone Case | iPhone Tough Case | Monstera Leaf |
|
||||
| Blue Waves Laptop Sleeve | Laptop Sleeve | Blue Waves |
|
||||
|
||||
---
|
||||
|
||||
## Files to Update
|
||||
|
||||
### 1. Core Data Source
|
||||
**File:** `lib/simpleshop_theme/theme/preview_data.ex`
|
||||
|
||||
Changes:
|
||||
- Replace `mock_products/0` with 12 new POD products
|
||||
- Update `mock_categories/0` with 5 POD categories
|
||||
- Update `mock_cart_items/0` to reference new products
|
||||
- Update `cart_drawer_items/0` with new product names
|
||||
- Update `mock_testimonials/0` with POD-relevant reviews
|
||||
|
||||
### 2. Preview Page Templates
|
||||
|
||||
**File:** `lib/simpleshop_theme_web/live/theme_live/preview_pages/home.html.heex`
|
||||
- Update hero title/subtitle to be inclusive of all POD types
|
||||
- Update about section text (make it generic to all creators, not botanical-specific)
|
||||
|
||||
**File:** `lib/simpleshop_theme_web/live/theme_live/preview_pages/about.html.heex`
|
||||
- Rewrite entire narrative for generic POD creator
|
||||
- Keep UK focus but remove Yorkshire/botanical specifics
|
||||
- Update sustainability/process sections
|
||||
|
||||
**File:** `lib/simpleshop_theme_web/live/theme_live/preview_pages/pdp.html.heex`
|
||||
- Update review examples (make them product-agnostic)
|
||||
- Keep structure, just refresh content
|
||||
|
||||
**File:** `lib/simpleshop_theme_web/live/theme_live/preview_pages/contact.html.heex`
|
||||
- Minor updates to timings if needed
|
||||
- Keep generic email placeholder
|
||||
|
||||
### 3. Shared Components
|
||||
**File:** `lib/simpleshop_theme_web/live/theme_live/preview_pages.ex`
|
||||
- Update newsletter CTA: "Join the studio" -> more generic
|
||||
- Update search hints from "fern, roses, botanical" to relevant terms
|
||||
|
||||
### 4. Static Demo File
|
||||
**File:** `priv/static/demo.html`
|
||||
- **SKIP** - Leave as-is (legacy reference file)
|
||||
|
||||
---
|
||||
|
||||
## Image Strategy
|
||||
|
||||
Use Unsplash for realistic POD product photography:
|
||||
- Art prints: framed prints on walls, print mockups
|
||||
- Apparel: t-shirts, tote bags worn/styled
|
||||
- Homewares: mugs, cushions in lifestyle settings
|
||||
- Nature-themed but showing actual products
|
||||
|
||||
Example Unsplash search terms:
|
||||
- "framed art print wall"
|
||||
- "t-shirt flat lay"
|
||||
- "ceramic mug coffee"
|
||||
- "cushion sofa"
|
||||
- "tote bag canvas"
|
||||
|
||||
---
|
||||
|
||||
## Content Examples
|
||||
|
||||
### Hero Section (home page)
|
||||
**Before:** "Nature-inspired art prints"
|
||||
**After:** "Original designs, printed on demand"
|
||||
Subtitle: "From art prints to apparel - unique products created by independent artists and delivered straight to your door."
|
||||
|
||||
### About Section (home page preview)
|
||||
**Before:** "Made with care in Yorkshire"
|
||||
**After:** "Made with passion, printed with care"
|
||||
Text: "Every design starts with an idea. We work with quality print partners to bring those ideas to life on premium products - from gallery-quality art prints to everyday essentials."
|
||||
|
||||
### About Page (full)
|
||||
Generic creative studio narrative:
|
||||
- Passion for design
|
||||
- Quality print partners
|
||||
- Sustainable practices
|
||||
- UK-based small business
|
||||
|
||||
### Testimonials
|
||||
POD-relevant reviews:
|
||||
- "The print quality is amazing - colours are exactly as shown"
|
||||
- "My new favourite mug! Great packaging too"
|
||||
- "The tote bag is so sturdy, I use it every day"
|
||||
- etc.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. **preview_data.ex** - Core data (products, categories, cart, testimonials)
|
||||
2. **home.html.heex** - Hero and about preview section
|
||||
3. **about.html.heex** - Full about page narrative
|
||||
4. **pdp.html.heex** - Product page reviews
|
||||
5. **preview_pages.ex** - Shared components (newsletter, search hints)
|
||||
6. **contact.html.heex** - Minor updates if needed
|
||||
7. **demo.html** - Align static demo with new content
|
||||
|
||||
---
|
||||
|
||||
## Workflow
|
||||
|
||||
### Phase 1: Automated Mockup Generation (via Printify API)
|
||||
|
||||
We'll create an Elixir module + Mix task to automate mockup generation.
|
||||
|
||||
#### Implementation Plan
|
||||
|
||||
**New files to create:**
|
||||
1. `lib/simpleshop_theme/printify/client.ex` - HTTP client wrapper for Printify API
|
||||
2. `lib/simpleshop_theme/printify/mockup_generator.ex` - Core logic module
|
||||
3. `lib/mix/tasks/generate_mockups.ex` - Mix task entry point
|
||||
|
||||
**API Workflow:**
|
||||
1. Fetch shop ID via `GET /v1/shops.json`
|
||||
2. For each product type, look up blueprint_id via `GET /v1/catalog/blueprints.json`
|
||||
3. Get print provider and placeholder dimensions via `GET /v1/catalog/blueprints/{id}/print_providers/{id}/variants.json`
|
||||
4. Download Unsplash image at highest resolution
|
||||
5. Upload image to Printify via `POST /v1/uploads/images.json` (using URL)
|
||||
6. Create product via `POST /v1/shops/{shop_id}/products.json` with centered artwork
|
||||
7. Extract mockup URLs from response `images` array
|
||||
8. Download mockups to `priv/static/mockups/` directory
|
||||
|
||||
**Image Handling:**
|
||||
- Printify API returns placeholder dimensions (width x height in pixels) for each product
|
||||
- We'll calculate scale factor to fit artwork within print area while maintaining aspect ratio
|
||||
- Center position: x=0.5, y=0.5 with appropriate scale
|
||||
- Unsplash provides high-res downloads (typically 4000+ pixels) - should exceed 300 DPI requirements
|
||||
- Printify auto-enhances low-res images, but we'll use highest quality available
|
||||
|
||||
**Configuration:**
|
||||
- API token stored in environment variable `PRINTIFY_API_TOKEN`
|
||||
- Product definitions in the module (blueprint IDs, provider IDs)
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Generate mockups (keeps products in Printify)
|
||||
mix generate_mockups
|
||||
|
||||
# Generate mockups and delete products from Printify afterwards
|
||||
mix generate_mockups --cleanup
|
||||
```
|
||||
|
||||
**Blueprint IDs to look up:**
|
||||
- Premium Matte Poster
|
||||
- Bella+Canvas 3001 Unisex Tee
|
||||
- Gildan 18500 Heavy Blend Hoodie
|
||||
- Cotton Canvas Tote Bag
|
||||
- White Glossy Mug 11oz
|
||||
- Spun Polyester Pillow
|
||||
- Sherpa Fleece Blanket
|
||||
- Hardcover Journal
|
||||
- iPhone Tough Case
|
||||
- Laptop Sleeve
|
||||
|
||||
### Phase 2: Code Updates
|
||||
Once mockup images are generated:
|
||||
1. Update `preview_data.ex` with new products pointing to local mockup images
|
||||
2. Update preview page templates (home, about, pdp, etc.)
|
||||
3. Update shared components (footer, announcement bar, search hints)
|
||||
4. Test all preview pages work correctly
|
||||
|
||||
### Phase 3: About Page Image
|
||||
Download directly from Unsplash (no Printify needed):
|
||||
- Forest Clearing: https://unsplash.com/photos/sunlight-filters-through-a-peaceful-forest-clearing-FwVkxITt8Bg
|
||||
- Save to `priv/static/images/about-hero.jpg`
|
||||
|
||||
---
|
||||
|
||||
## Final Decisions
|
||||
|
||||
1. **Shop name** - "Wildprint Studio"
|
||||
2. **Product count** - 16 products
|
||||
3. **About page image** - Forest Clearing: https://unsplash.com/photos/sunlight-filters-through-a-peaceful-forest-clearing-FwVkxITt8Bg
|
||||
4. **About page narrative** - Humble, British, personal tone. Single person who takes lovely nature photos and prints them on products.
|
||||
|
||||
## About Page Content Direction
|
||||
|
||||
**Tone:** Personal, humble, British, warm
|
||||
|
||||
**Example narrative:**
|
||||
> I'm [Name], a nature photographer based in the UK. What started as weekend walks with my camera has grown into something I never expected – a little shop where I can share my favourite captures with others.
|
||||
>
|
||||
> Every design in this shop comes from my own photography. Whether it's early morning mist over the hills, autumn leaves in the local woods, or the quiet beauty of wildflower meadows, I'm drawn to the peaceful moments that nature offers.
|
||||
>
|
||||
> I work with quality print partners to bring these images to life on products you can actually use and enjoy – from art prints for your walls to mugs for your morning tea.
|
||||
>
|
||||
> Thank you for visiting. It means a lot that you're here.
|
||||
|
||||
**Key themes:**
|
||||
- Personal photography journey
|
||||
- UK-based
|
||||
- Nature and peaceful moments
|
||||
- Quality print partners (POD)
|
||||
- Gratitude for customers
|
||||
|
||||
---
|
||||
|
||||
## Validation
|
||||
|
||||
After implementation:
|
||||
- Browse all preview pages in theme editor
|
||||
- Verify images load correctly
|
||||
- Check content makes sense for "any POD seller"
|
||||
- Ensure prices/currency consistent (£)
|
||||
- Test that theme presets still work with new content
|
||||
- Verify mockup images display at correct sizes
|
||||
375
docs/research/typography.md
Normal file
375
docs/research/typography.md
Normal file
@@ -0,0 +1,375 @@
|
||||
# Professional typography systems for Tailwind e-commerce themes
|
||||
|
||||
A well-designed typography system using modular scales, vertical rhythm, and constrained customization can transform an e-commerce shop from generic to polished. The key insight: **typography accounts for 95% of web design**, yet most theme builders expose the wrong controls—offering granular font size pickers when users actually need curated presets with automatic scaling. The most successful approach combines a **Major Third (1.25) type scale**, **8px baseline grid**, and **2-3 carefully paired Google Fonts** with preset-based theme customization that prevents design chaos while enabling brand expression.
|
||||
|
||||
This report covers the complete technical foundation: mathematical type scales with CSS implementations, curated Google Font pairings across seven style categories, production-ready Tailwind configurations, DaisyUI integration patterns, and research-backed guidelines for building theme editors that balance freedom with quality outcomes.
|
||||
|
||||
---
|
||||
|
||||
## Type scales create mathematical harmony across all text sizes
|
||||
|
||||
Modular type scales use consistent mathematical ratios to generate font sizes, ensuring visual harmony without arbitrary decisions. Starting with a **16px base** (browser default), each size step multiplies by the chosen ratio.
|
||||
|
||||
| Ratio | Name | Best use case |
|
||||
|-------|------|--------------|
|
||||
| 1.125 | Major Second | Dense UIs, dashboards, documentation |
|
||||
| **1.25** | **Major Third** | **Recommended default for e-commerce** |
|
||||
| 1.333 | Perfect Fourth | Editorial, content-heavy sites |
|
||||
| 1.414 | Augmented Fourth | Landing pages, marketing |
|
||||
| 1.5 | Perfect Fifth | High-contrast headlines |
|
||||
| 1.618 | Golden Ratio | Luxury brands, creative projects |
|
||||
|
||||
The **Major Third (1.25)** strikes the ideal balance for e-commerce: sufficient hierarchy without oversized mobile headings. A full scale at this ratio: 12.8px → 16px → 20px → 25px → 31.25px → 39px → 48.8px.
|
||||
|
||||
**Implementation principle**: Use larger ratios (1.333–1.5) on desktop and smaller ratios (1.125–1.25) on mobile. Fluid typography with `clamp()` handles this automatically:
|
||||
|
||||
```css
|
||||
--fs-heading: clamp(1.5rem, 1rem + 2vw, 2.5rem);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Vertical rhythm and baseline grids enforce consistent spacing
|
||||
|
||||
The **8-point grid system** (used by Material Design, iOS, and most design systems) creates visual consistency by constraining all spacing to multiples of 8px. Typography integrates with this grid through line-height alignment.
|
||||
|
||||
**Why 8px works**: Most screen sizes divide evenly by 8, scaling cleanly to @1x, @2x, and @3x resolutions. It reduces decision-making to a finite set of options: 8, 16, 24, 32, 40, 48px.
|
||||
|
||||
**Typography integration**: Base font of 16px with line-height 1.5 yields **24px line-height** (3 × 8), keeping text on the baseline grid. All margins and padding use 8px increments.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--rhythm: 0.5rem; /* 8px */
|
||||
--line-height-body: 1.5rem; /* 24px = 3 × rhythm */
|
||||
}
|
||||
|
||||
body { font-size: 1rem; line-height: 1.5; }
|
||||
p { margin-bottom: 1rem; } /* 16px = 2 × rhythm */
|
||||
h2 { margin-bottom: 1.5rem; } /* 24px = 3 × rhythm */
|
||||
```
|
||||
|
||||
**Practical approach**: Accept line-height-based rhythm rather than true baseline alignment—CSS centers text vertically within line-height, making pixel-perfect baseline grids impractical without complex padding offsets.
|
||||
|
||||
---
|
||||
|
||||
## Line-height, measure, and letter-spacing have precise optimal values
|
||||
|
||||
These three parameters have research-backed optimal ranges that should rarely need customization in a theme editor.
|
||||
|
||||
**Line-height follows an inverse relationship with font size**—larger text needs tighter leading:
|
||||
|
||||
| Context | Line-height | Example at 16px base |
|
||||
|---------|-------------|---------------------|
|
||||
| Large headings (32px+) | 1.1–1.2 | 35–38px |
|
||||
| Subheadings (20–28px) | 1.2–1.3 | 24–36px |
|
||||
| **Body text** | **1.5–1.6** | **24–26px** |
|
||||
| Small text (<14px) | 1.4–1.5 | 20–21px |
|
||||
|
||||
WCAG accessibility requires **minimum 1.5 line-height** for body text. Always use unitless values (`line-height: 1.5`) so they scale proportionally.
|
||||
|
||||
**Measure (line length)** should stay within **45–75 characters** for optimal readability, with 66 being ideal. Implementation:
|
||||
|
||||
```css
|
||||
.prose { max-width: 65ch; }
|
||||
/* Or responsive: */
|
||||
.content { width: clamp(45ch, 90%, 75ch); }
|
||||
```
|
||||
|
||||
**Letter-spacing guidelines**:
|
||||
- **Body text**: Leave default (font is optimized)
|
||||
- **ALL CAPS**: Add 5–12% spacing (`letter-spacing: 0.08em`)
|
||||
- **Large headings (32px+)**: Tighten slightly (`letter-spacing: -0.02em`)
|
||||
- **Small text (<14px)**: Widen slightly (`letter-spacing: 0.02em`)
|
||||
|
||||
---
|
||||
|
||||
## Curated Google Font pairings for seven e-commerce styles
|
||||
|
||||
Each pairing includes heading and body fonts with specific weights to load. These combinations feel distinctive while maintaining professional readability.
|
||||
|
||||
### Minimal and modern (tech, sustainable goods, contemporary homeware)
|
||||
|
||||
**Manrope (500, 600) + Inter (400, 500)** — Geometric precision meets exceptional screen readability. Both feature clean lines without quirks.
|
||||
|
||||
**Plus Jakarta Sans (500, 600) + Literata (400, 400i)** — Newer, distinctive sans-serif with variable font support paired with a screen-optimized serif. Fresh but professional.
|
||||
|
||||
**DM Sans (500, 700) + Source Serif Pro (400, 400i)** — Low-contrast geometric sans contrasts elegantly with refined serif. Ideal for design tools, premium stationery.
|
||||
|
||||
### Warm and artisan (handmade goods, craft products, specialty food)
|
||||
|
||||
**Cormorant Garamond (500, 600) + Proza Libre (400, 400i)** — Lavish Garamond revival with strong calligraphic feel pairs with humanist sans optimized for screens. Perfect for artisan ceramics, specialty coffee.
|
||||
|
||||
**Calistoga (400) + IBM Plex Sans (400, 500)** — Rounded serifs with friendly sophistication. Excellent for bakeries, organic goods, candle shops.
|
||||
|
||||
**Josefin Sans Light (300, 400) + Crimson Text (400, 400i, 600)** — Thin letterforms create an airy feel; classic serif adds professional warmth. Suits makeup, jewelry, wellness.
|
||||
|
||||
### Bold and editorial (fashion, lifestyle brands)
|
||||
|
||||
**Playfair Display (500, 700) + Raleway Light (300, 400)** — High-contrast delicate hairlines of Playfair with thin Raleway strokes. Classic fashion magazine aesthetic.
|
||||
|
||||
**Instrument Serif + Instrument Sans (400, 500)** — Same-designer family creates cohesive editorial look with perfect built-in contrast. Art-forward brands, creative agencies.
|
||||
|
||||
**DM Serif Display (400) + Poppins (300, 400)** — Beautiful calligraphic strokes with thin modern geometric sans. Fashion accessories, beauty products.
|
||||
|
||||
### Playful and quirky (creative products, novelty gifts)
|
||||
|
||||
**Fraunces (variable, 400–900) + Work Sans (400, 500)** — Four axes including "wonk" create vintage-inspired whimsy while maintaining professionalism. Variable font with softness, weight, and optical size controls.
|
||||
|
||||
**Syne Bold (700) + Syne Regular (400)** — Footprint expands as weight increases for quirky but readable stand-out headlines. Music merchandise, creative agencies.
|
||||
|
||||
**Dynapuff (variable) + Nunito (400, 600)** — Bold, playful, round font with soft rounded sans. Children's products, candy shops.
|
||||
|
||||
### Luxury and elegant (high-end goods, premium products)
|
||||
|
||||
**Cinzel (400, 500) + Fauna One (400)** — High-contrast Roman inscription inspiration conveys timeless authority. Fine jewelry, luxury watches.
|
||||
|
||||
**Cormorant Garamond (400, 500) + Montserrat Light (300, 400)** — Elegant Garamond with clean urban sans creates sophisticated contrast. High-end cosmetics, luxury home decor.
|
||||
|
||||
**Prata (400) + Manrope Light (300, 400)** — Contrasting thick/thin strokes convey elegance; light Manrope maintains delicacy. Premium skincare, designer accessories.
|
||||
|
||||
### Vintage and retro (heritage brands, nostalgic products)
|
||||
|
||||
**Libre Franklin (500, 600) + Libre Baskerville (400, 400i)** — American Gothic + Transitional pairing used for 100+ years. Evokes established, traditional authenticity.
|
||||
|
||||
**Oswald (500, 600) + EB Garamond (400, 400i)** — Bold condensed sans (Franklin Gothic–inspired) with elegant Garamond. Vintage clothing, retro posters.
|
||||
|
||||
**Rokkitt (400, 700) + Raleway (400, 500)** — Geometric slab serif (Egyptian style) with elegant sans. Heritage stationery, letterpress products.
|
||||
|
||||
### Tech and futuristic (sci-fi prints, gadget accessories)
|
||||
|
||||
**Space Grotesk (500, 700) + IBM Plex Mono (400, 500)** — Distinctive geometric sans with monospace body creates coding/tech aesthetic.
|
||||
|
||||
---
|
||||
|
||||
## Variable fonts offer performance and flexibility advantages
|
||||
|
||||
Variable fonts contain multiple styles in a single file, reducing HTTP requests and enabling precise weight control (e.g., font-weight: 450).
|
||||
|
||||
| Font | Weight range | Other axes | Best for |
|
||||
|------|-------------|-----------|----------|
|
||||
| **Inter** | 100–900 | Optical size 14–32 | All-purpose workhorse |
|
||||
| **Roboto Flex** | 100–1000 | Width, grade, optical size | Maximum flexibility |
|
||||
| **Fraunces** | 100–900 | Soft, wonk, optical size | Playful brands |
|
||||
| **Outfit** | 100–900 | — | Modern headlines |
|
||||
| **DM Sans** | 100–1000 | Optical size 9–40 | Clean interfaces |
|
||||
|
||||
**Request syntax** for Google Fonts variable fonts:
|
||||
```html
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@200..900&display=swap">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Font loading strategies that protect performance
|
||||
|
||||
**Recommended approach**: Use `font-display: swap` for headings (fastest text visibility) and `font-display: optional` for body text (prevents layout shifts if font fails to load).
|
||||
|
||||
**Self-hosting now outperforms Google Fonts CDN** due to Chrome and Safari's cache partitioning (since 2020)—cross-site caching no longer works. Self-hosting reported PageSpeed improvements of 66 → 94 on mobile scores.
|
||||
|
||||
**Performance checklist**:
|
||||
- Load only weights actually used (e.g., 400, 600 instead of full range)
|
||||
- Preconnect to font origins: `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>`
|
||||
- Use WOFF2 format only (30% smaller than WOFF)
|
||||
- Limit to 2–3 font families maximum
|
||||
- Preload critical above-fold fonts:
|
||||
```html
|
||||
<link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tailwind configuration for production typography systems
|
||||
|
||||
Tailwind's fontSize config supports a tuple syntax for complete typographic definitions:
|
||||
|
||||
```javascript
|
||||
// tailwind.config.js
|
||||
module.exports = {
|
||||
theme: {
|
||||
fontSize: {
|
||||
'xs': ['0.75rem', { lineHeight: '1rem', letterSpacing: '0.025em' }],
|
||||
'sm': ['0.875rem', { lineHeight: '1.25rem' }],
|
||||
'base': ['1rem', { lineHeight: '1.5rem' }],
|
||||
'lg': ['1.125rem', { lineHeight: '1.75rem' }],
|
||||
'xl': ['1.25rem', { lineHeight: '1.75rem' }],
|
||||
'2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '-0.01em' }],
|
||||
'3xl': ['1.875rem', { lineHeight: '2.25rem', letterSpacing: '-0.02em' }],
|
||||
'4xl': ['2.25rem', { lineHeight: '2.5rem', letterSpacing: '-0.02em' }],
|
||||
},
|
||||
spacing: {
|
||||
// 8px baseline grid
|
||||
'1': '0.5rem', // 8px
|
||||
'2': '1rem', // 16px
|
||||
'3': '1.5rem', // 24px
|
||||
'4': '2rem', // 32px
|
||||
'6': '3rem', // 48px
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'ui-sans-serif', 'system-ui'],
|
||||
display: ['Playfair Display', 'ui-serif', 'Georgia'],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**Fluid typography in Tailwind** uses arbitrary values or custom config:
|
||||
|
||||
```html
|
||||
<h1 class="text-[clamp(1.75rem,3vw,3rem)]">Fluid headline</h1>
|
||||
```
|
||||
|
||||
Or extend the config:
|
||||
```javascript
|
||||
fontSize: {
|
||||
'fluid-xl': 'clamp(1.5rem, 1rem + 2vw, 2.5rem)',
|
||||
'fluid-display': 'clamp(2.5rem, 1.5rem + 4vw, 5rem)',
|
||||
}
|
||||
```
|
||||
|
||||
**@tailwindcss/typography plugin** handles prose content with sensible defaults:
|
||||
|
||||
```html
|
||||
<article class="prose prose-lg dark:prose-invert prose-headings:font-display">
|
||||
{{ markdown }}
|
||||
</article>
|
||||
```
|
||||
|
||||
Override defaults in config:
|
||||
```javascript
|
||||
typography: {
|
||||
DEFAULT: {
|
||||
css: {
|
||||
maxWidth: '65ch',
|
||||
'h1, h2, h3': { fontFamily: 'var(--font-display)' },
|
||||
a: { color: '#3182ce', '&:hover': { color: '#2c5282' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DaisyUI themes control colors while typography stays at Tailwind level
|
||||
|
||||
**Critical distinction**: DaisyUI themes only control colors, border-radius, and effects—not typography. Font families, sizes, and spacing are configured in Tailwind, applying consistently across all DaisyUI themes.
|
||||
|
||||
```css
|
||||
/* DaisyUI plugin configuration */
|
||||
@import "tailwindcss";
|
||||
@plugin "daisyui" {
|
||||
themes: light --default, dark --prefersdark;
|
||||
}
|
||||
|
||||
/* Typography at Tailwind level (applies to all themes) */
|
||||
@theme {
|
||||
--font-display: "Playfair Display", serif;
|
||||
--font-body: "Inter", sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
**Semantic color usage for text**: DaisyUI provides `base-content` for default text, `primary-content` for text on primary backgrounds, etc. Components auto-apply correct text colors (`btn-primary` uses `primary-content`).
|
||||
|
||||
**Overriding component typography**:
|
||||
```css
|
||||
@layer components {
|
||||
.btn {
|
||||
text-transform: none; /* Remove default uppercase */
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Theme editors should offer presets, not granular controls
|
||||
|
||||
Research across Shopify, Squarespace, and Webflow reveals a clear pattern: the most successful theme systems use **constrained customization** that prevents design chaos.
|
||||
|
||||
### Parameters to make user-configurable
|
||||
|
||||
| Setting | Implementation | Why expose |
|
||||
|---------|---------------|-----------|
|
||||
| **Font pairing preset** | 5–10 curated combinations | Enables brand expression without typography expertise |
|
||||
| **Heading font family** | Dropdown of paired fonts | Primary brand identity signal |
|
||||
| **Body font family** | Dropdown of paired fonts | Readability preference |
|
||||
| **Font size scale** | Slider 90%–120% | Accessibility accommodation |
|
||||
| **Accent colors** | Color picker with presets | Brand customization |
|
||||
|
||||
### Parameters to lock down (prevent user adjustment)
|
||||
|
||||
| Setting | Locked value | Why restrict |
|
||||
|---------|-------------|-------------|
|
||||
| **Line-height ratios** | 1.5 body, 1.2 headings | Users break readability |
|
||||
| **Letter-spacing** | Preset per size | Technical, easy to ruin |
|
||||
| **Measure/line length** | 45–75ch | Readability science |
|
||||
| **Type scale ratio** | 1.25 | Mathematical harmony |
|
||||
| **Mobile scaling** | Automatic | Complex responsive logic |
|
||||
|
||||
### The Shopify model (maximum constraints)
|
||||
|
||||
Shopify exposes only **two font categories** (headings and body), a **single size slider** (100–150%), and no line-height or letter-spacing controls. Users select from a curated library of ~1,000 fonts. Result: hard to break, accessible to non-designers.
|
||||
|
||||
### The Squarespace model (balanced approach)
|
||||
|
||||
Squarespace offers **60+ Font Packs**—professionally curated heading/body pairs that guarantee aesthetic coherence. Users can also access individual controls (family, weight, size, line-height, letter-spacing) but the preset system handles most needs.
|
||||
|
||||
### Recommended implementation for e-commerce themes
|
||||
|
||||
1. **Offer 5–10 curated font pairing presets** covering different brand aesthetics
|
||||
2. **Allow 2 font category overrides** (heading + body) from a filtered quality list
|
||||
3. **Use range sliders with sensible limits** (size 90–120%, never expose line-height)
|
||||
4. **Provide real-time preview** before saving changes
|
||||
5. **Include accessibility validation** (contrast ratio warnings)
|
||||
6. **Group elements semantically** (all headings share one setting)
|
||||
|
||||
---
|
||||
|
||||
## E-commerce typography patterns that increase conversions
|
||||
|
||||
Research from Baymard Institute (200,000+ hours of UX testing) reveals specific typography patterns that improve shopping experiences.
|
||||
|
||||
### Product page hierarchy
|
||||
|
||||
- **Product title**: Largest text (20–28px), semi-bold to bold (600–700), first in visual hierarchy
|
||||
- **Price**: High prominence near Add to Cart, **4.5:1 minimum contrast**, consider showing price-per-unit (**74% of sites miss this**)
|
||||
- **CTA buttons**: Clean sans-serif, 14–16px, action verbs ("Add to Cart" outperforms "Submit")
|
||||
- **Body descriptions**: 16–18px, 1.5 line-height, structured with subheadings (**78% of sites don't use highlights format**)
|
||||
|
||||
### Trust signals through typography
|
||||
|
||||
Monotype/Neurons research found serif fonts increase **perceived quality by 13%** and **reliability by 9%**. For premium positioning:
|
||||
- Use serif fonts for headlines (Playfair Display, Cormorant Garamond)
|
||||
- Generous white space around text elements
|
||||
- Restrained design—avoid decorative excess
|
||||
- Limit to 2–3 fonts maximum (**4+ creates "cheap" perception**)
|
||||
|
||||
### Mobile e-commerce requirements
|
||||
|
||||
- **Touch targets**: 44×44px minimum for text links (WCAG AAA), 8px minimum spacing between targets
|
||||
- **Body text**: 16px minimum (prevents iOS input zoom)
|
||||
- **Avoid horizontal tabs on mobile**—27% of users overlook them entirely
|
||||
- Position price and CTA in natural thumb zone (bottom 2/3 of screen)
|
||||
|
||||
### Scanning patterns inform layout
|
||||
|
||||
**F-pattern** (product pages with descriptions): Users scan horizontally across top, then shorter horizontal line below, then vertically down left side. Place critical information (product name, price, CTAs) along these paths.
|
||||
|
||||
**Z-pattern** (landing pages, minimal text): Top left → top right → diagonal to bottom left → bottom right. Position logo top-left, navigation top-right, primary CTA bottom-right.
|
||||
|
||||
---
|
||||
|
||||
## Conclusion: A complete typography system for Tailwind e-commerce themes
|
||||
|
||||
The optimal system combines:
|
||||
|
||||
1. **Major Third (1.25) type scale** as the default, with automatic mobile scaling using `clamp()`
|
||||
2. **8px baseline grid** for all spacing, with line-heights aligned to 24px (1.5rem) for body text
|
||||
3. **2–3 Google Fonts** loaded as variable fonts with `font-display: swap`, self-hosted for performance
|
||||
4. **Tailwind configuration** with fontSize tuples including line-height and letter-spacing
|
||||
5. **DaisyUI for color theming** while typography remains at Tailwind level
|
||||
6. **Preset-based theme customization** offering curated font pairings rather than granular controls
|
||||
|
||||
The research consensus is clear: typography parameters like line-height (1.5 body, 1.2 headings), measure (65ch), and letter-spacing should be **locked to optimal values**. User customization should focus on font pairing presets and size scaling within safe ranges—enabling brand expression without the risk of breaking readability or professional appearance.
|
||||
|
||||
For print-on-demand shops specifically, the **Minimal/Modern** (Manrope + Inter) and **Playful/Quirky** (Fraunces + Work Sans) pairings offer the most versatility across product categories, while **Warm/Artisan** (Cormorant Garamond + Proza Libre) suits handmade goods and **Bold/Editorial** (Playfair Display + Raleway) elevates fashion-forward brands.
|
||||
276
docs/research/ux-patterns.md
Normal file
276
docs/research/ux-patterns.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# SimpleShop UX-Optimised Component Patterns
|
||||
|
||||
A research-backed guide to component design that avoids common anti-patterns and creates professional, ethical, high-converting e-commerce experiences.
|
||||
|
||||
---
|
||||
|
||||
## Spacing & Layout System
|
||||
|
||||
Building on the 8px grid from the typography guide:
|
||||
|
||||
**Spacing Tokens**:
|
||||
```css
|
||||
--space-1: 0.25rem; /* 4px - tight */
|
||||
--space-2: 0.5rem; /* 8px - compact */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-4: 1rem; /* 16px - default */
|
||||
--space-5: 1.5rem; /* 24px */
|
||||
--space-6: 2rem; /* 32px */
|
||||
--space-8: 3rem; /* 48px - section gaps */
|
||||
--space-10: 4rem; /* 64px */
|
||||
--space-12: 6rem; /* 96px - major sections */
|
||||
--space-16: 8rem; /* 128px - hero spacing */
|
||||
```
|
||||
|
||||
**Tailwind Config**:
|
||||
```javascript
|
||||
module.exports = {
|
||||
theme: {
|
||||
spacing: {
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.5rem',
|
||||
'6': '2rem',
|
||||
'8': '3rem',
|
||||
'10': '4rem',
|
||||
'12': '6rem',
|
||||
'16': '8rem',
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Section Spacing**:
|
||||
```html
|
||||
<!-- Page sections use consistent vertical spacing -->
|
||||
<section class="py-12 md:py-16">
|
||||
<div class="container mx-auto px-4">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
```
|
||||
|
||||
**Container Widths**:
|
||||
```css
|
||||
--container-prose: 65ch; /* Text content */
|
||||
--container-content: 80rem; /* 1280px - main content */
|
||||
--container-wide: 90rem; /* 1440px - full layouts */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component States
|
||||
|
||||
Every interactive component needs these states defined:
|
||||
|
||||
**Button States**:
|
||||
```
|
||||
Default → Base styling
|
||||
Hover → Subtle lift/colour shift (200ms ease)
|
||||
Active → Pressed state
|
||||
Focus → Visible ring (accessibility)
|
||||
Disabled → Greyed, no pointer
|
||||
Loading → Spinner, disabled
|
||||
```
|
||||
|
||||
**Form Input States**:
|
||||
```
|
||||
Default → Border, background
|
||||
Focus → Ring, border colour change
|
||||
Error → Red border, error message below
|
||||
Success → Green check (optional, for validation)
|
||||
Disabled → Greyed background
|
||||
```
|
||||
|
||||
**Card States**:
|
||||
```
|
||||
Default → Base styling
|
||||
Hover → Subtle lift (box-shadow increase)
|
||||
Focus → Visible ring (if interactive)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Baseline
|
||||
|
||||
Every SimpleShop theme must meet WCAG 2.1 AA:
|
||||
|
||||
**Colour Contrast**:
|
||||
- Normal text: 4.5:1 minimum
|
||||
- Large text (18px+ or 14px bold): 3:1 minimum
|
||||
- UI components and graphics: 3:1 minimum
|
||||
|
||||
**Focus Indicators**:
|
||||
- Visible focus ring on all interactive elements
|
||||
- Never remove outline without replacement
|
||||
- Ring should have 3:1 contrast with adjacent colours
|
||||
|
||||
**Touch Targets**:
|
||||
- Minimum 44×44px for touch targets
|
||||
- 8px minimum spacing between targets
|
||||
|
||||
**Screen Reader**:
|
||||
- Semantic HTML (button for buttons, not div)
|
||||
- Alt text on all images
|
||||
- ARIA labels where needed
|
||||
- Skip links for keyboard navigation
|
||||
- Logical heading hierarchy (h1 → h2 → h3)
|
||||
|
||||
---
|
||||
|
||||
## Performance Patterns
|
||||
|
||||
**Image Loading**:
|
||||
```html
|
||||
<!-- Lazy load below-fold images -->
|
||||
<img
|
||||
src="product.jpg"
|
||||
alt="Product"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
width="400"
|
||||
height="533"
|
||||
/>
|
||||
|
||||
<!-- Eager load above-fold images -->
|
||||
<img
|
||||
src="hero.jpg"
|
||||
alt="Hero"
|
||||
loading="eager"
|
||||
fetchpriority="high"
|
||||
/>
|
||||
```
|
||||
|
||||
**Font Loading**:
|
||||
```html
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
||||
rel="stylesheet"
|
||||
>
|
||||
```
|
||||
|
||||
**Critical CSS**:
|
||||
- Inline above-fold styles
|
||||
- Defer non-critical CSS
|
||||
- Remove unused styles
|
||||
|
||||
---
|
||||
|
||||
## Theme Presets
|
||||
|
||||
Combining typography pairings with component styling:
|
||||
|
||||
### Minimal Modern
|
||||
- **Fonts**: Manrope + Inter
|
||||
- **Cards**: No shadows, subtle borders
|
||||
- **Buttons**: Solid fills, sharp corners (border-radius: 0 or 2px)
|
||||
- **Spacing**: Generous, airy
|
||||
- **Colours**: Monochrome with single accent
|
||||
|
||||
### Warm Artisan
|
||||
- **Fonts**: Cormorant Garamond + Proza Libre
|
||||
- **Cards**: Subtle shadows, rounded corners
|
||||
- **Buttons**: Rounded, warm fills
|
||||
- **Spacing**: Comfortable, not sparse
|
||||
- **Colours**: Warm neutrals, earthy accents
|
||||
|
||||
### Bold Editorial
|
||||
- **Fonts**: Playfair Display + Raleway
|
||||
- **Cards**: Strong contrast, dramatic shadows
|
||||
- **Buttons**: High contrast, possibly outlined
|
||||
- **Spacing**: Dramatic, asymmetric
|
||||
- **Colours**: Black/white with bold accent
|
||||
|
||||
### Playful Quirky
|
||||
- **Fonts**: Fraunces + Work Sans
|
||||
- **Cards**: Rounded, possibly with borders
|
||||
- **Buttons**: Rounded/pill, playful hover states
|
||||
- **Spacing**: Varied, dynamic
|
||||
- **Colours**: Bright, fun palette
|
||||
|
||||
### Luxury Elegant
|
||||
- **Fonts**: Cinzel + Fauna One
|
||||
- **Cards**: Minimal, refined
|
||||
- **Buttons**: Thin borders, subtle
|
||||
- **Spacing**: Generous, refined
|
||||
- **Colours**: Muted, sophisticated
|
||||
|
||||
---
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
Before shipping any SimpleShop theme, verify:
|
||||
|
||||
**Layout**:
|
||||
- [ ] Mobile-first responsive design
|
||||
- [ ] No horizontal scroll on any viewport
|
||||
- [ ] Content readable at 320px minimum
|
||||
- [ ] Touch targets 44×44px minimum
|
||||
|
||||
**Navigation**:
|
||||
- [ ] Logo links to homepage
|
||||
- [ ] Cart always accessible
|
||||
- [ ] Current page indicated
|
||||
- [ ] Mobile menu works smoothly
|
||||
|
||||
**Product Cards**:
|
||||
- [ ] Consistent aspect ratios
|
||||
- [ ] Price clearly visible
|
||||
- [ ] Hover state provides value
|
||||
- [ ] Links are obvious
|
||||
|
||||
**Product Page**:
|
||||
- [ ] Accordion sections, not horizontal tabs
|
||||
- [ ] Images zoomable
|
||||
- [ ] Price prominent
|
||||
- [ ] Add to Cart sticky on mobile
|
||||
- [ ] Trust signals visible
|
||||
|
||||
**Checkout**:
|
||||
- [ ] Guest checkout prominent
|
||||
- [ ] Progress indicator clear
|
||||
- [ ] All costs shown upfront
|
||||
- [ ] Form fields properly labeled
|
||||
- [ ] Error messages inline
|
||||
- [ ] Trust signals present
|
||||
|
||||
**Ethical**:
|
||||
- [ ] No fake urgency/scarcity
|
||||
- [ ] No confirmshaming
|
||||
- [ ] No hidden costs
|
||||
- [ ] No exit-intent popups
|
||||
- [ ] Clear, neutral options
|
||||
- [ ] Honest product information
|
||||
|
||||
**Accessibility**:
|
||||
- [ ] Colour contrast passes WCAG AA
|
||||
- [ ] Focus rings visible
|
||||
- [ ] Semantic HTML
|
||||
- [ ] Alt text on images
|
||||
- [ ] Keyboard navigable
|
||||
|
||||
**Performance**:
|
||||
- [ ] Images lazy loaded (except hero)
|
||||
- [ ] Fonts preloaded
|
||||
- [ ] LCP under 2.5s
|
||||
- [ ] No layout shift (CLS < 0.1)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
SimpleShop's component system prioritises:
|
||||
|
||||
1. **Honesty over manipulation** — No dark patterns, ever
|
||||
2. **Clarity over cleverness** — Obvious UI beats novel UI
|
||||
3. **Research over assumptions** — Patterns backed by testing
|
||||
4. **Consistency over creativity** — Systems over one-offs
|
||||
5. **Accessibility over aesthetics** — Everyone can use it
|
||||
|
||||
These patterns, combined with the typography and spacing systems, create a foundation for themes that are not just beautiful but genuinely effective—converting browsers into buyers through trust and clarity rather than tricks and pressure.
|
||||
|
||||
The result: shops that sellers are proud of and customers enjoy using.
|
||||
423
docs/spec.md
Normal file
423
docs/spec.md
Normal file
@@ -0,0 +1,423 @@
|
||||
# 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"
|
||||
Reference in New Issue
Block a user