# SimpleShop Theme - Phase 9 Implementation Plan ## Overview This plan covers **Phase 9: Storefront Integration** - applying the theme system to the actual public-facing shop. Based on my analysis, Phases 1-8 are complete, with a fully functional theme editor at `/admin/theme`. Phase 9 will create the public storefront that uses the saved theme settings. ## Current State Summary ✅ **Completed (Phases 1-8):** - Settings and Media contexts with SQLite storage - CSS three-layer architecture (primitives, attributes, semantic) - Theme editor LiveView with 8 presets - All 7 preview pages (home, collection, pdp, cart, about, contact, error) - Full customization controls (mood, typography, shape, density, colors, layout, toggles) - Logo and header image uploads with BLOB storage - SVG recoloring functionality - CSS generation system - Preview data system (mock products, testimonials, categories) ❌ **Not Started (Phase 9):** - Public storefront routes - Storefront LiveViews - Theme CSS injection for public pages - Plug to load theme settings - CSS cache warming - Real product integration ## Architecture Decisions ### 1. Routing Strategy - **Public routes**: Use root-level paths (`/`, `/products/:slug`, `/cart`, etc.) - **No shop slug**: Since this app IS the shop (not multi-tenant), no slug needed - **Future-proof**: Structure allows adding multi-shop support later if needed ### 2. LiveView Structure - **Reuse preview templates**: The preview pages are already production-ready - **Extract to shared components**: Move reusable pieces from preview_pages/ to components/ - **Storefront-specific LiveViews**: Create dedicated LiveViews that handle real data ### 3. CSS Application - **Same three-layer system**: Use identical CSS as theme editor - **Root element**: Use `.shop-root` class with data attributes - **Inline CSS injection**: Inject generated CSS into layout via assign - **ETS caching**: Use CSSCache for production performance - **Cache invalidation**: Invalidate on theme settings save ### 4. Data Handling - **Smart degradation**: Show empty states when no products exist - **Graceful fallback**: Use preview data patterns for missing content - **Real products**: When Products context exists, use real data ## Implementation Steps ### Step 1: Extract Shared Components **Goal**: Move reusable preview components to shared location for use in both admin and storefront **Files to create:** - `lib/simpleshop_theme_web/components/shop/announcement_bar.ex` - `lib/simpleshop_theme_web/components/shop/header.ex` - `lib/simpleshop_theme_web/components/shop/footer.ex` - `lib/simpleshop_theme_web/components/shop/search_modal.ex` - `lib/simpleshop_theme_web/components/shop/product_card.ex` **Files to modify:** - `lib/simpleshop_theme_web/live/theme_live/preview_pages.ex` - Import and use new components - All preview templates - Update to use new component modules **Actions:** 1. Create `lib/simpleshop_theme_web/components/shop/` directory 2. Extract `announcement_bar/1` from preview_pages.ex to `shop/announcement_bar.ex` 3. Extract `shop_header/1` to `shop/header.ex` 4. Extract `shop_footer/1` to `shop/footer.ex` 5. Extract `search_modal/1` to `shop/search_modal.ex` 6. Create new `product_card/1` component (used in multiple places) 7. Update preview_pages.ex to import and use new components 8. Update all 7 preview templates to use new component paths 9. Test theme editor still works correctly **Validation:** - Run `mix test test/simpleshop_theme_web/live/theme_live_test.exs` - Visit `/admin/theme` and verify all 7 preview pages still render correctly - No visual regressions --- ### Step 2: Create LoadTheme Plug **Goal**: Create a plug that loads theme settings and generated CSS for every public request **Files to create:** - `lib/simpleshop_theme_web/plugs/load_theme.ex` - `test/simpleshop_theme_web/plugs/load_theme_test.exs` **Plug functionality:** ```elixir defmodule SimpleshopThemeWeb.Plugs.LoadTheme do import Plug.Conn alias SimpleshopTheme.Settings alias SimpleshopTheme.Theme.{CSSGenerator, CSSCache} def init(opts), do: opts def call(conn, _opts) do # Try cache first {theme_settings, generated_css} = case CSSCache.get() do {:ok, css} -> {Settings.get_theme_settings(), css} :miss -> settings = Settings.get_theme_settings() css = CSSGenerator.generate(settings) CSSCache.put(css) {settings, css} end conn |> assign(:theme_settings, theme_settings) |> assign(:generated_css, generated_css) end end ``` **Files to modify:** - `lib/simpleshop_theme_web/router.ex` - Add plug to public pipeline **Actions:** 1. Create plug file with init/1 and call/2 functions 2. Implement cache-first CSS loading strategy 3. Assign both `:theme_settings` and `:generated_css` to conn 4. Add plug to `:browser` pipeline in router (before routes) 5. Write tests for plug behavior 6. Test cache hit and cache miss scenarios **Validation:** - Run `mix test test/simpleshop_theme_web/plugs/load_theme_test.exs` - Verify assigns are available in subsequent requests - Verify CSS is cached and reused --- ### Step 3: Create Storefront Layout **Goal**: Create a dedicated layout for the public storefront with theme CSS injection **Files to create:** - `lib/simpleshop_theme_web/components/layouts/shop.html.heex` **Layout structure:** ```heex
<.live_title><%= assigns[:page_title] || @theme_settings.site_name %>