|
All checks were successful
deploy / deploy (push) Successful in 3m36s
Image variants were written to the ephemeral release directory and wiped on every deploy, causing 500 errors with 50s timeouts as browsers waited for images that could never be served. - Point image_cache_dir at /data/image_cache in prod - Add Plug.Static to serve from the persistent volume - Exclude /image_cache/ from broken URL tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .gitea/workflows | ||
| assets | ||
| config | ||
| docs | ||
| lib | ||
| priv | ||
| rel | ||
| test | ||
| .credo.exs | ||
| .dialyzer_ignore.exs | ||
| .dockerignore | ||
| .formatter.exs | ||
| .gitignore | ||
| .mcp.json | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Dockerfile | ||
| fly.toml | ||
| LICENSE | ||
| mise.toml | ||
| mix.exs | ||
| mix.lock | ||
| PROGRESS.md | ||
| README.md | ||
| ROADMAP.md | ||
Berrypod
A customisable e-commerce storefront for print-on-demand sellers, built with Phoenix LiveView. Professional shops without design expertise, privacy-respecting by default, fully self-hostable.
Features
Shop
Complete storefront with all the pages you need:
- Home — hero banner, category navigation, featured products, newsletter
- Products — grid layout with hover effects, sorting, filtering by collection
- Product detail — image gallery with per-colour filtering, variant selector, related products
- Cart — drawer + full page, quantity controls, shipping estimate, cross-tab sync
- Checkout — Stripe-hosted checkout with shipping costs, order confirmation
- Custom pages — CMS pages at any URL with 26 block types
- Legal pages — auto-generated privacy, delivery, and terms from actual shop settings
- Search — FTS5 full-text search with live modal, keyboard nav, ARIA
- Contact — contact form with order status lookup
Admin
- Theme editor — 8 presets, real-time preview, comprehensive customisation
- Page builder — drag-free block editor with undo/redo, live editing on shop pages
- Analytics — privacy-first, cookie-free, comparison mode, CSV export
- Orders — status tracking, fulfilment timeline, provider submission
- Media library — image management with alt text, usage tracking, orphan detection
- Activity log — global event feed, "needs attention" tab, contextual retry
- URL redirects — auto-redirect on slug change, 404 monitoring, dead link scanning
- Email settings — 10 adapter options, test email, env var precedence
- Print providers — Printify + Printful with sync, orders, shipping, webhooks
Technical highlights
- Hand-written CSS with three-layer architecture (9.8 KB gzipped shop, 17.8 KB admin)
- SQLite with BLOB storage, IMMEDIATE transactions, WAL, mmap
- Image optimisation pipeline (AVIF/WebP/JPEG responsive variants via Oban)
- ETS caching for CSS, pages, redirects, favicons
- 99-100 PageSpeed mobile, no-JS support across all key flows
- 1679+ tests, CI with credo + dialyzer
Getting started
Prerequisites
- Elixir 1.19+
- Erlang/OTP 28+
- Node.js 20+ (for esbuild asset bundling)
Setup
git clone <repo-url>
cd berrypod
mix setup # install deps, create DB, run migrations, build assets
mix phx.server # start dev server at localhost:4000
Visit http://localhost:4000/setup to create your admin account and connect a print provider.
Running tests
mix test # all tests
mix test path/to.exs # specific file
mix precommit # compile warnings + format + test (run before committing)
Project structure
lib/berrypod/ # core business logic
├── accounts.ex # user accounts + auth
├── analytics.ex # privacy-first pageview tracking
├── activity_log.ex # system event logging
├── cart.ex # session-based cart
├── media.ex # image uploads, optimisation, media library
├── newsletter.ex # email list + campaigns
├── orders.ex # order lifecycle + fulfilment
├── pages.ex # page builder (blocks, cache, defaults)
├── products.ex # products, variants, categories
├── providers.ex # POD provider abstraction (Printify, Printful)
├── redirects.ex # URL redirects + dead link monitoring
├── search.ex # FTS5 full-text search
├── settings.ex # theme + shop settings
├── shipping.ex # shipping rates + country detection
├── theme/ # CSS generation, presets, ETS cache
└── workers/ # Oban background jobs
lib/berrypod_web/ # web layer
├── components/
│ ├── layouts/ # app, admin, and shop layouts
│ ├── shop_components/ # shop UI (product cards, cart, gallery, etc.)
│ └── block_editor_components.ex
├── live/
│ ├── admin/ # admin LiveViews (orders, pages, media, etc.)
│ ├── shop/ # shop LiveViews (home, collection, product, etc.)
│ └── auth/ # authentication
├── page_renderer.ex # generic block-to-component dispatch
└── controllers/ # Stripe webhooks, favicons, images, cart API
assets/css/
├── shop/ # shop component styles
├── admin/ # admin component styles
├── theme-layer1-primitives.css # design tokens
├── theme-layer2-attributes.css # theme-specific values
└── theme-layer3-semantic.css # component styles
Stripe setup
- Create a Stripe account
- Navigate to Admin > Settings in your shop
- Paste your secret key and click "Connect Stripe"
For local webhook testing:
stripe listen --forward-to localhost:4000/webhooks/stripe
Test cards: 4242 4242 4242 4242 (success), 4000 0000 0000 0002 (declined).
Documentation
- PROGRESS.md — current status and next tasks
- ROADMAP.md — future vision and planned features
- CLAUDE.md — coding guidelines and conventions
- docs/plans/ — feature implementation plans
License
AGPL-3.0