All checks were successful
deploy / deploy (push) Successful in 4m59s
- Per-page SEO controls: meta robots directives, focus keyword, OG image - Site-wide default OG image in admin settings - FAQ block type with FAQPage JSON-LD schema - Enhanced Organization JSON-LD with business info, contact, address - Image sitemap with product images - SEO preview panel with Google/social card mockups - SEO checklist with real-time scoring - Business info section in site editor - GSC integration scaffolding (OAuth, client, cache) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
386 lines
13 KiB
Markdown
386 lines
13 KiB
Markdown
# Berrypod: Project Overview
|
|
|
|
> Generated April 2026. For current status, see [PROGRESS.md](../PROGRESS.md).
|
|
|
|
## Technology Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|------------|
|
|
| Framework | Phoenix 1.8, LiveView 1.1 |
|
|
| Language | Elixir 1.19, OTP 28 |
|
|
| Database | SQLite (via Ecto + ecto_sqlite3) |
|
|
| HTTP Server | Bandit |
|
|
| Background Jobs | Oban 2.19 |
|
|
| Payments | Stripe |
|
|
| Image Processing | Image (VIPS-based) |
|
|
| Asset Build | esbuild |
|
|
| Testing | ExUnit, Mox, LazyHTML |
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
lib/
|
|
├── berrypod/ # Core business contexts
|
|
│ ├── accounts/ # User auth, TOTP
|
|
│ ├── products/ # Products, variants, provider connections
|
|
│ ├── orders/ # Orders, line items, abandoned carts
|
|
│ ├── media/ # Image upload, optimization
|
|
│ ├── pages/ # CMS pages, block editor
|
|
│ ├── theme/ # CSS generation, presets
|
|
│ ├── settings/ # Site configuration
|
|
│ ├── analytics/ # Privacy-first tracking
|
|
│ ├── providers/ # Printify/Printful abstraction
|
|
│ ├── shipping/ # Rates, country detection
|
|
│ ├── newsletter/ # Subscribers, campaigns
|
|
│ ├── reviews/ # Product reviews
|
|
│ ├── activity_log/ # Event logging
|
|
│ └── redirects/ # URL redirects, 404 tracking
|
|
└── berrypod_web/ # Web layer
|
|
├── live/admin/ # Admin LiveViews
|
|
├── live/shop/ # Shop LiveViews
|
|
├── components/ # UI components
|
|
├── controllers/ # HTTP controllers
|
|
└── plugs/ # Request middleware
|
|
```
|
|
|
|
---
|
|
|
|
## Core Business Contexts
|
|
|
|
### Products (`lib/berrypod/products/`)
|
|
- Products synced from POD providers (Printify/Printful)
|
|
- Variants with pricing, cost, availability tracking
|
|
- Image optimization pipeline (WebP conversion, AVIF/JPEG variants at 400/800/1200px)
|
|
- Denormalized fields: `cheapest_price`, `in_stock`, `on_sale`
|
|
- Status flow: draft → active → archived → discontinued
|
|
|
|
### Orders (`lib/berrypod/orders/`)
|
|
- Order numbers: `SS-YYMMDD-XXXX` format
|
|
- Payment tracking: pending → paid → failed → refunded
|
|
- Fulfilment: unfulfilled → submitted → processing → shipped → delivered
|
|
- Abandoned cart recovery (24hr inactivity triggers)
|
|
- Stripe session/payment intent tracking
|
|
|
|
### Media & Images (`lib/berrypod/media/`, `lib/berrypod/images/`)
|
|
- BLOB storage in SQLite
|
|
- Lossless WebP conversion on upload (26-41% smaller)
|
|
- Dominant color extraction for header images
|
|
- Async variant generation via Oban workers
|
|
- Usage tracking across products, pages, themes
|
|
|
|
### Pages (`lib/berrypod/pages/`)
|
|
- 14 system pages + unlimited custom CMS pages
|
|
- Block-based editor with **26 block types** (hero, text, gallery, grid, testimonials, etc.)
|
|
- ETS caching with DB fallback
|
|
- Auto-redirect creation when URLs change
|
|
- Navigation menu integration
|
|
|
|
### Theme (`lib/berrypod/theme/`)
|
|
- **3-layer CSS architecture:**
|
|
1. Primitives (CSS custom properties)
|
|
2. Attributes (theme-specific rules)
|
|
3. Semantic (component styles)
|
|
- 8 presets: Gallery, Studio, Boutique, etc.
|
|
- Instant switching via CSS variable injection (no reload)
|
|
- WCAG contrast checking
|
|
|
|
### Analytics (`lib/berrypod/analytics/`)
|
|
- Privacy-first: no cookies, no personal data, GDPR-friendly
|
|
- Visitor hashing with daily-rotating salt
|
|
- Event types: pageview, product_view, add_to_cart, checkout_start, purchase
|
|
- Metrics: unique visitors, bounce rate, top pages, sources, countries, devices
|
|
- E-commerce funnel tracking with revenue
|
|
|
|
### Providers (`lib/berrypod/providers/`)
|
|
- Behaviour-based abstraction layer
|
|
- **Printify**: 800+ products from 90+ print providers
|
|
- **Printful**: In-house production with warehousing
|
|
- Operations: test connection, fetch products, submit orders, track status, fetch shipping rates
|
|
|
|
### Reviews (`lib/berrypod/reviews/`)
|
|
- 1-5 star ratings with text + images (up to 3)
|
|
- Verified purchase badge
|
|
- Moderation workflow: pending → approved/rejected
|
|
- Rating denormalization to products
|
|
|
|
### Newsletter (`lib/berrypod/newsletter/`)
|
|
- Double opt-in with confirmation emails
|
|
- Plain text only (no tracking pixels)
|
|
- Campaign scheduling and bulk sending
|
|
- Global suppression list
|
|
|
|
---
|
|
|
|
## Database Schema (26 Schemas)
|
|
|
|
**Core entities:**
|
|
- `User`, `UserToken` - Authentication
|
|
- `Product`, `ProductImage`, `ProductVariant` - Catalog
|
|
- `ProviderConnection` - POD credentials (encrypted)
|
|
- `Order`, `OrderItem`, `AbandonedCart` - Commerce
|
|
- `Page`, `NavItem`, `SocialLink` - Content
|
|
- `Image`, `FaviconVariant` - Media
|
|
- `ShippingRate` - Rates by country/provider
|
|
- `Review` - Product reviews
|
|
- `Newsletter.Subscriber`, `Newsletter.Campaign` - Email
|
|
- `Analytics.Event` - Tracking
|
|
- `ActivityLog.Entry` - System events
|
|
- `Redirects.Redirect`, `BrokenUrl`, `DeadLink` - URLs
|
|
- `Setting` - Configuration (JSON, encrypted)
|
|
|
|
---
|
|
|
|
## Background Jobs (Oban)
|
|
|
|
### Scheduled (cron)
|
|
|
|
| Schedule | Worker | Purpose |
|
|
|----------|--------|---------|
|
|
| Every 30min | `FulfilmentStatusWorker` | Poll provider for order updates |
|
|
| Every 6hr | `ScheduledSyncWorker` | Product sync |
|
|
| Daily 3am | `RetentionWorker` | Delete old analytics |
|
|
| Daily 3:30am | `DeadLinkCheckerWorker` | Scan for broken links |
|
|
| Every 5min | `ScheduledCampaignWorker` | Send scheduled campaigns |
|
|
|
|
### On-demand
|
|
|
|
- `ProductSyncWorker` - Sync products from provider
|
|
- `ImageDownloadWorker` - Download product images
|
|
- `OptimizeWorker` - Generate image variants
|
|
- `OrderSubmissionWorker` - Submit to fulfilment
|
|
- `ReviewRequestWorker` - Send review request after delivery
|
|
- `CampaignSendWorker` - Newsletter campaigns
|
|
|
|
---
|
|
|
|
## Web Layer
|
|
|
|
### Admin LiveViews (`/admin/*`)
|
|
- Dashboard, Analytics, Orders, Products, Providers
|
|
- Settings, Media, Pages, Newsletter, Reviews
|
|
- Activity log, Backup, Redirects
|
|
|
|
### Shop LiveViews (public)
|
|
- Home, Collections, Products, Cart, Checkout
|
|
- Contact (with order lookup), Search, Review forms
|
|
- Custom CMS pages via catch-all route `/:slug`
|
|
|
|
### Key Routes
|
|
|
|
| Path | Purpose |
|
|
|------|---------|
|
|
| `/` | Shop home |
|
|
| `/collections/:slug` | Category browsing |
|
|
| `/products/:id` | Product detail |
|
|
| `/cart` | Shopping cart |
|
|
| `/admin` | Admin dashboard |
|
|
| `/admin/orders` | Order management |
|
|
| `/admin/pages` | Page editor |
|
|
| `/admin/media` | Media library |
|
|
| `/admin/analytics` | Analytics dashboard |
|
|
| `/admin/theme` | Theme editor |
|
|
| `/:slug` | Custom pages (catch-all) |
|
|
|
|
---
|
|
|
|
## Asset Pipeline
|
|
|
|
**No Tailwind** - Hand-written CSS with:
|
|
- `@layer` for cascade organization
|
|
- Native CSS nesting
|
|
- `oklch()` color function
|
|
- CSS custom properties for theming
|
|
|
|
**Bundles:**
|
|
- `berrypod` - Main JS
|
|
- `berrypod_shop_css` - Storefront styles
|
|
- `berrypod_admin_css` - Admin styles
|
|
- `berrypod_theme_css` - Dynamic theme CSS
|
|
|
|
---
|
|
|
|
## Key Features
|
|
|
|
### For Shop Owners
|
|
- Product sync from Printify/Printful with image optimization
|
|
- Block-based CMS page builder (26+ block types)
|
|
- Live theme editor with 8 presets
|
|
- Privacy-first analytics (no cookies, GDPR-friendly)
|
|
- Order management with fulfilment tracking
|
|
- Abandoned cart recovery emails
|
|
- Newsletter with double opt-in
|
|
- Product review system with moderation
|
|
- Activity log for system events
|
|
|
|
### For Customers
|
|
- Product browsing with collections/filters
|
|
- Session-based shopping cart
|
|
- Stripe checkout
|
|
- Order lookup via email
|
|
- Review submissions
|
|
|
|
---
|
|
|
|
## Security & Performance
|
|
|
|
### Security
|
|
- Vault encryption for secrets
|
|
- CSRF protection, secure headers
|
|
- TOTP two-factor auth for admin
|
|
- Webhook signature verification (Stripe, Printify, Printful)
|
|
|
|
### Performance
|
|
- ETS caching (settings, theme CSS, pages, redirects)
|
|
- Streams for LiveView collections
|
|
- Batch analytics flushing
|
|
- Image variants with lazy generation
|
|
- Pagination throughout
|
|
|
|
---
|
|
|
|
## Outstanding Work
|
|
|
|
### Active Plans (Ready to Implement)
|
|
|
|
#### 1. Profit-Aware Pricing & Sales ([plan](plans/profit-aware-pricing.md)) ~16h
|
|
|
|
| Task | Est | Status |
|
|
|------|-----|--------|
|
|
| Fix Printful cost sync (catalog API cross-reference) | 45m | planned |
|
|
| Cost snapshot on orders (`unit_cost`, `gross_profit`) | 1.5h | planned |
|
|
| Exact Stripe fees from Balance Transaction API | 45m | planned |
|
|
| Tax toggle + Stripe Tax integration | 1.5h | planned |
|
|
| Admin profit dashboard (margins, P&L) | 3h | planned |
|
|
| Profit-aware price editor (live margin display) | 2h | planned |
|
|
| Sales & promotions (%, fixed, scoped, scheduled) | 3h | planned |
|
|
| Margin guard (prevent profit-killing discounts) | 1h | planned |
|
|
| Announcement bar for active sales | 1.5h | planned |
|
|
|
|
#### 2. Competitive Gaps - Phase 1: Core Commerce ([plan](plans/competitive-gaps.md)) ~17h
|
|
|
|
| Task | Est | Status |
|
|
|------|-----|--------|
|
|
| Customer authentication schema | 2h | planned |
|
|
| Customer auth flows (login, register, reset) | 3h | planned |
|
|
| Link orders to customers | 1.5h | planned |
|
|
| Customer account dashboard | 2h | planned |
|
|
| Saved addresses | 1.5h | planned |
|
|
| Guest checkout linking | 1h | planned |
|
|
| PayPal SDK integration | 2h | planned |
|
|
| PayPal checkout flow | 3h | planned |
|
|
| PayPal webhooks | 1.5h | planned |
|
|
|
|
#### 3. Competitive Gaps - Phase 2: Retention & Growth ~14h
|
|
|
|
| Task | Est | Status |
|
|
|------|-----|--------|
|
|
| Returns schema | 1.5h | planned |
|
|
| Return request flow | 2h | planned |
|
|
| Return admin | 2h | planned |
|
|
| Return policy settings | 1h | planned |
|
|
| Email sequence schema | 2h | planned |
|
|
| Sequence triggers & sending | 3h | planned |
|
|
| Sequence admin | 2h | planned |
|
|
| Customer data export (GDPR) | 1.5h | planned |
|
|
| Customer data deletion (GDPR) | 2h | planned |
|
|
|
|
#### 4. Competitive Gaps - Phase 3: Scale ~7h
|
|
|
|
| Task | Est | Status |
|
|
|------|-----|--------|
|
|
| Blog post type | 3h | planned |
|
|
| Staff accounts & RBAC | 4h | planned |
|
|
|
|
#### 5. SEO Enhancements ([plan](plans/seo-enhancements.md)) ~21h
|
|
|
|
| Task | Est | Status |
|
|
|------|-----|--------|
|
|
| Per-page noindex/nofollow + meta descriptions | 2h | planned |
|
|
| Enhanced Organization schema | 2h | planned |
|
|
| Image sitemap entries | 1h | planned |
|
|
| SEO preview panel (Google + social cards) | 4h | planned |
|
|
| Focus keyword & SEO score/checklist | 4h | planned |
|
|
| FAQ block with FAQPage schema | 2h | planned |
|
|
| Google Search Console OAuth integration | 6h | planned |
|
|
|
|
#### 6. Draft-then-Publish Workflow ([plan](plans/draft-publish-workflow.md)) ~31h
|
|
|
|
| Phase | Description | Est |
|
|
|-------|-------------|-----|
|
|
| 0 | Site-level publishing (coming soon → live) | 1.5h |
|
|
| 1 | Page versions and drafts (auto-save, publish/discard) | 7h |
|
|
| 2 | Theme drafts | 4h |
|
|
| 3 | Settings drafts | 4h |
|
|
| 4 | Version history and rollback (diff view, history panel) | 5.5h |
|
|
| 5 | Image soft delete and trash (usage check, restore, auto-purge) | 4.5h |
|
|
| 6 | Polish and pruning (conflict handling, retention worker) | 4.25h |
|
|
|
|
Key features: auto-save drafts, explicit publish, version history with rollback, image trash/recycle bin, tiered version retention.
|
|
|
|
---
|
|
|
|
### Platform/Business Items
|
|
|
|
| Task | Status |
|
|
|------|--------|
|
|
| Platform/marketing site (brochure, pricing, sign-up) | planned |
|
|
| Separation of platform site vs AGPL open source core | planned |
|
|
|
|
---
|
|
|
|
### Production Hardening
|
|
|
|
| Item | Description |
|
|
|------|-------------|
|
|
| Litestream / SQLite replication | Continuous backup to S3, point-in-time recovery |
|
|
| End-to-end & accessibility tests | Wallaby browser tests, WCAG 2.1 AA |
|
|
| Security monitoring | Paraxial.io for runtime security, bot detection, rate limiting |
|
|
| AGPL licensing | LICENSE file, contribution guidelines, release process |
|
|
|
|
---
|
|
|
|
### Future Enhancements
|
|
|
|
| Feature | Description |
|
|
|---------|-------------|
|
|
| Multiple print providers | Route products to different providers based on cost/type |
|
|
| Product page improvements | Pre-checkout validation, cost monitoring, better gallery |
|
|
| Editable email templates | Admin UI for customizing transactional emails |
|
|
| Hosted platform infrastructure | Multi-tenancy, OAuth connect for providers/payments |
|
|
| Migration & export | Shopify/WooCommerce import, data export |
|
|
| Internationalisation | Multi-language (Gettext), currency formatting, RTL |
|
|
|
|
---
|
|
|
|
### Summary by Priority
|
|
|
|
**High priority (core commerce):**
|
|
1. Customer accounts + PayPal (~17h)
|
|
2. Profit-aware pricing + sales (~16h)
|
|
|
|
**Medium priority (polish):**
|
|
3. SEO enhancements (~21h)
|
|
4. Draft-then-publish workflow (~31h)
|
|
5. Returns system (~6.5h)
|
|
6. Email sequences (~7h)
|
|
|
|
**Lower priority (scale):**
|
|
7. Blog post type (3h)
|
|
8. Staff accounts & RBAC (4h)
|
|
9. Platform site (TBD)
|
|
|
|
**Total estimated remaining:** ~100-120h of planned work, plus the larger platform vision items.
|
|
|
|
---
|
|
|
|
## Design Philosophy
|
|
|
|
1. **"One theme, infinite variations"** — one solid foundation with curated customisation
|
|
2. **Constrained creativity** — limit choices to prevent poor design outcomes
|
|
3. **No professional photography required** — works with product mockups
|
|
4. **Mobile-first** — all features work on touch devices
|
|
5. **Ethical design** — no dark patterns or fake urgency
|
|
6. **Privacy-first** — cookie-free analytics, GDPR-compliant cart recovery, no tracking pixels
|