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>
Event call sites (product_view, add_to_cart, checkout_start, purchase)
were only passing visitor_hash and pathname, leaving browser, OS, screen
size and country nil. Add AnalyticsHook.attrs/1 helper to extract common
analytics fields from socket assigns, and use it in all LiveView event
call sites. Checkout controller reads the same fields from the session.
Also fix plug analytics test to clear stale events before assertions.
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>
Stripe.Checkout.Session is a struct that doesn't implement Access,
so get_in with atom keys fails. Use direct struct field access instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
login_user_by_magic_link raises for unconfirmed users with a password,
which is exactly what recovery creates. Use get_user_by_magic_link_token
directly and log in without the magic link guard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When email isn't configured, the login page now hides the magic link
form and shows a recovery link. The /recover page logs the setup secret
to server logs and lets the admin reset their password with it.
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>
Show a lightweight error page using admin.css when the shop isn't
live yet, avoiding broken theme dependencies. Also tidied up copy
to sentence case and shorter descriptions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
error pages render shop-themed layout but were loading admin.css,
which has no shop component styles. switch to shop.css.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
add system font stack to admin reset CSS so setup/admin pages render
sans-serif on all devices instead of falling through to browser default.
pass path_resolver to CSSGenerator.generate on cache miss paths so
font URLs resolve to digested paths in production.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>