Replace put_flash with inline feedback for form saves:
- Media library: metadata save shows "Saved" checkmark
- Product show: storefront controls save shows "Saved" checkmark
- Newsletter campaign form: draft save shows "Saved" checkmark
Page-level outcomes (uploads, deletes, async operations) remain as
flash/banner messages — these are the correct pattern for non-form
actions.
Completes Task 4 of notification overhaul.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Progressive enhancement: provider form now works without JavaScript.
Forms POST to ProvidersController (create/update), which handles
validation and redirects with flash messages.
With JS: LiveView phx-submit handles save, navigates with flash.
Without JS: Form POSTs to controller, redirects with flash.
Completes Task 3 of notification overhaul (admin forms migration).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace put_flash calls with inline feedback for form saves:
- Email settings: "Now send a test email" after saving
- Settings: from address and signing secret saves
- Page editor: save button shows "Saved" checkmark
Inline feedback appears next to save buttons and auto-clears after
3 seconds. Banners (put_flash) remain for page-level outcomes like
deletions, state changes, and async operations.
Task 3 of notification overhaul. Theme editor skipped as it auto-saves.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Render all adapter field sections in the form with CSS :has(:checked)
controlling visibility. Selecting a provider instantly shows its config
fields — no JS, no page reload, no server round-trip needed.
- Render all 6 adapter configs with data-adapter attribute
- CSS :has(:checked) show/hide rules per adapter in admin stylesheet
- Namespace field names per adapter (email[brevo][api_key] etc)
- Drop 4 transactional-only providers (Resend, Postmark, Mailgun, MailPace)
- Remove noscript "Switch provider" button and controller redirect workaround
- Remove configured_adapter hidden input tracking
- Hide JS-only test email button for no-JS users via noscript style
- LiveView progressively enhances with async save and test email
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Disable checkout when Stripe isn't connected (cart drawer, cart page,
and early guard in checkout controller to prevent orphaned orders).
Show amber warning on order detail when email isn't configured.
Fix pre-existing missing vertical spacing between page blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New external_link component in core_components handles target="_blank",
rel="noopener noreferrer", external-link icon, and sr-only "(opens in
new tab)" text. Migrated admin providers form, settings (Stripe),
order tracking, onboarding setup links to use it. Fixed rel="noopener"
to "noopener noreferrer" on remaining links (email settings, product
show, core_components card radio). Added sr-only text to shop social
link cards and aria-label to page renderer tracking link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New --t-border-input token per mood, all 3:1+ contrast against their
surface backgrounds (neutral #8c8c8c, warm #8a827a, cool #7a8591,
dark #707070). Used on admin inputs/selects/textareas and shop
themed-input/themed-select, with graceful fallback to --t-border-default.
Decorative borders on cards, dividers, panels are unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AnalyticsHook to the coming_soon live session — the shop layout
fires an analytics:screen JS event but the session had no handler,
crashing the page on connect.
Centre the logo image (display:block from CSS reset needs
margin-inline:auto). Add a subtle "Admin" link at the bottom using
flex flow rather than fixed/absolute positioning so it works in
iframes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap logo mode radios in fieldset/legend for screen reader grouping.
Hide native radio input properly (was using nonexistent .hidden class),
add aria-hidden on decorative dot spans, focus-visible ring on cards,
and IDs on each input.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Onboarding UX v2 supersedes the original plan — reworks setup into a
single guided journey with progress bar, forgiving validation, and
contextual prompts for skipped steps.
Notification overhaul replaces floating toasts with inline feedback
and persistent top banners (110+ flash messages audited).
Live site editor is a design exploration for on-site editing with
contenteditable text and live CSS variable injection.
Also adds SEO settings and multiple providers to the roadmap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix resolve_content_image returning base path (not full URL) so
responsive_image doesn't double-append width/extension
- Remove legacy image fields (image_src, image_alt, image_url) from
block settings schemas
- Remove demo/mockup fallbacks from renderer and defaults — blank
fields stay blank instead of showing preview content
- Replace demo text in defaults with instructional placeholders that
guide new shop owners
- Remove redundant X button from editor sidebar, add unsaved-changes
confirmation to Done button
- Fix block card name overflow on mobile (display: block, flex-wrap)
- Add onboarding UX improvement plan (10 tasks)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace BEM-style &--modifier nesting (unsupported in native CSS) with
&.class-modifier in shop/components.css and page_renderer.ex. Fix
Elixir 1.19 type warnings comparing lists with != [].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five missing line-height values caused pixel shifts when Tailwind
utilities (text-sm, text-lg, text-xs) were replaced with semantic
classes that only set font-size. Also remove phantom padding-bottom
on .admin-header (the old pb-4 utility was never defined).
Fixes: .admin-header, .admin-header-subtitle, .admin-error,
.admin-brand, .admin-text-secondary
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subscribers with double opt-in confirmation, campaign composer with
draft/scheduled/sent lifecycle, admin dashboard with overview stats,
CSV export, and shop signup form wired into page builder blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 tasks covering unsaved changes warning, block picker
descriptions, sidebar grouping, nav editor labels, inline
page settings, real data preview, and more.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Legal pages (privacy, delivery, terms) now auto-populate content from
shop settings on mount, show auto-generated vs customised badges, and
have a regenerate button. Theme editor gains alt text fields for logo,
header, and icon images. Image picker in page builder now has an upload
button and alt text warning badges. Clearing unused image references
shows an orphan info flash.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
History stacks (@history/@future) on both admin editor and live sidebar,
capped at 50 entries. All mutations routed through apply_mutation for
consistent history tracking. EditorKeyboard JS hook combines DirtyGuard
with Ctrl+Z/Ctrl+Shift+Z. Settings panel fade-in animation. 10 new tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New settings form for creating and editing custom page metadata
(title, slug, meta description, published, nav settings). Pages
index shows custom pages section with draft badges and delete.
Editor shows settings button for custom pages, hides reset to
defaults. 20 new tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Six-stage plan for user-created content pages at top-level URLs.
System pages keep dedicated LiveViews, custom pages use a single
generic LiveView with portable blocks. Includes navigation
management, SEO, and auto-redirects on slug change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 14 pages now render through PageRenderer. Theme editor preview
unified from 10 preview_page clauses to one function + page-context
helpers. PageTemplates module and 10 .heex template files deleted.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stage 4 of the page builder: all shop pages now render via
PageRenderer instead of inline templates or PageTemplates.
- Collection: full filter bar moved to renderer (category pills,
sort dropdown, CollectionFilters hook, empty state)
- PDP: related_products and reviews loaded via block data loaders
instead of manual queries
- Cart: page definition loaded in mount, subtotal computed in render
- Search: page definition loaded in mount, handle_params unchanged
- Added Phoenix.VerifiedRoutes to PageRenderer for ~p sigil
- Net -55 lines (128 added, 183 removed)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Home, Content (about/delivery/privacy/terms), Contact, and ErrorHTML
now render through the generic PageRenderer instead of hardcoded
templates. Block wrapper divs enable CSS grid targeting. Featured
products block supports layout/card_variant/columns settings for
different page contexts. Contact page uses CSS grid on data-block-type
attributes for two-column layout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Upload a source image (PNG, JPEG, or SVG) and get a complete favicon
setup: PNG variants at 32, 180, 192, 512px served from DB via
FaviconController with ETag caching, SVG favicon for vector sources,
dynamic site.webmanifest, and theme-color meta tag. Theme editor gains
a site icon section with "use logo as icon" toggle, dedicated icon
upload, short name, and background colour picker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces hardcoded PreviewData placeholders with generated content
derived from real shop state: connected providers (production lead
times), shipping countries (grouped by region), shop country
(jurisdiction language and governing law), and feature flags
(abandoned cart recovery section, newsletter, VAT clause).
Returns policy correctly cites Consumer Contracts Regulations Reg
28(1)(b) for POD exemption and Consumer Rights Act for defective goods.
Cart recovery section uses jurisdiction-specific wording: PECR Reg 22
for UK, GDPR Art 6(1)(f) for EU, generic otherwise.
About page unchanged — shop owner's story to tell.
26 new tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- add product_id to order_items (migration + schema + create_order)
- cart recovery email now includes a direct product link per item
- extend session cookie max_age to 7 days so carts survive browser restarts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Magic link flow on contact page: customer enters email, gets a
time-limited signed link, clicks through to /orders showing all their
paid orders and full detail pages with thumbnails and product links.
- OrderLookupController generates/verifies Phoenix.Token signed links
- Contact LiveView handles lookup_orders + reset_tracking events
- Orders and OrderDetail LiveViews gated by session email
- Order detail shows thumbnails, links to products still available
- .themed-button gets base padding/font-weight so all usages are consistent
- order-summary-card sticky scoped to .cart-grid (was leaking to orders list)
- 27 new tests (1095 total)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Product pages: Product schema (name, description, image, price/currency,
availability) + BreadcrumbList (Home > Category > Product). Home page:
Organization schema (name, url). Uses Jason with html_safe escaping so
the JSON is safe to embed in <script> tags.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Canonical: all shop pages now assign og_url (reusing the existing og:url
assign), which the layout renders as <link rel="canonical">. Collection
pages strip the sort param so ?sort=price_asc doesn't create a duplicate
canonical.
robots.txt: dynamic controller disallows /admin/, /api/, /users/,
/webhooks/, /checkout/. Removed robots.txt from static_paths so it
goes through the router instead of Plug.Static.
sitemap.xml: auto-generated from all visible products + categories +
static pages, served as application/xml. 8 tests.
Also updates PROGRESS.md: marks tasks 55, 58, 59, 61, 62 as done.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Click any row in pages, sources, countries, or devices tables to
filter the entire dashboard by that dimension. Active filters show
as dismissible chips. Filters thread through all queries including
previous-period deltas. 1050 tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three-layer pipeline: Plug for all HTTP requests (no JS needed), LiveView
hook for SPA navigations, JS hook for screen width. ETS-backed buffer
batches writes to SQLite every 10s. Daily-rotating salt for visitor hashing.
Includes admin dashboard with date ranges, visitor trends, top pages,
sources, devices, and e-commerce conversion funnel. Oban cron for 12-month
data retention.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both features were already fully implemented. Updated task list
and plan status to reflect reality.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Setup wizard no longer requires email delivery. Admin account is
auto-confirmed and auto-logged-in via token redirect. Adds setup
secret gate for prod (logged on boot), SMTP env var config in
runtime.exs, email_configured? helper, and admin warning banner
when email isn't set up. Includes plan files for this task and
the follow-up email settings UI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents the missing @font-face and font-family on admin/setup
pages, the cache miss path resolver bug, and options for fixing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- new /setup page with three-section onboarding (account, provider, payments)
- dashboard launch checklist with progress bar, go-live, dismiss
- provider registry on Provider module (single source of truth for metadata)
- payments registry for Stripe
- setup context made provider-agnostic (provider_connected, theme_customised, etc.)
- admin provider pages now fully registry-driven (no hardcoded provider names)
- auth flow: fresh installs redirect to /setup, signed_in_path respects setup state
- removed old /admin/setup wizard
- 840 tests, 0 failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace all Tailwind utilities in content.ex and collection.ex with
semantic CSS classes (content body, contact form, cards, reviews, etc.)
- Delete app-shop.css (Tailwind shop entry point)
- Remove shop Tailwind config from config.exs, dev.exs, mix.exs
- Remove shop Tailwind stylesheet link from shop_root.html.heex
- Add collection filter bar, empty state, and select dropdown styles
- Fix filter pill sizing (use theme font vars instead of hardcoded rem)
- Fix active pill contrast (tinted accent background + dark accent text)
- Fix --t-text-on-accent fallback for pill legibility
- Add padding/font-size to .themed-select
Shop pages now use zero Tailwind. Admin Tailwind remains for Phase 6.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Absorb ~100 Tailwind utility classes from layout.ex and all page
templates into semantic CSS rules in components.css. Uses theme font-size
vars (--t-text-small, --t-text-caption) instead of rem to respect the
theme's em-based scaling system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>