Files
cannamanage/docs/sprint-14/cannamanage-sprint14-analysis.md
Patrick Plate dad798a904
Deploy to TrueNAS / deploy (push) Failing after 33s
feat: Sprint 14 — Marketing & Monetization
- Landing page with hero, feature grid, trust signals
- Split-layout login redesign (admin + portal)
- Pricing page with storage tiers (5GB/50GB/unlimited)
- StorageQuotaService backend (V36 migration, 402 on exceeded)
- Frontend storage integration + 402 error handling
- StorageController uses TenantContext for tenant isolation
- onTierChange() hook for subscription tier updates
2026-06-18 20:28:35 +02:00

124 lines
7.2 KiB
Markdown

# Analysis: Sprint 14 — Marketing & Monetization
**Date:** 2026-06-18
**Author:** Patrick Plate / Lumen (Planner)
**Status:** v1
**Sprint Theme:** Marketing & Monetization
---
## 1. Problem Analysis
CannaManage is production-ready after Sprint 13's hardening. However, the public-facing marketing surfaces are minimal — there is no landing page (the root `/` currently serves the pricing page directly via the marketing layout), the login pages use a basic centered-card layout that doesn't communicate product value, and the pricing page lacks storage quota information which is a core monetization lever.
Additionally, the backend has no concept of storage quotas per tenant. Documents can be uploaded without limit, creating an unbounded cost liability on the file storage (TrueNAS/disk). Sprint 14 introduces a **StorageQuotaService** that enforces per-plan limits, making the pricing tiers meaningful at the infrastructure level.
### Sprint Goals
1. **Landing Page** — Create a professional homepage that converts visitors to signups
2. **Login Redesign** — Split-layout login pages that reinforce brand value during auth flow
3. **Pricing Rework** — Add storage tier information, update pricing model
4. **Storage Quota Backend** — Enforce plan-based storage limits on document uploads
---
## 2. Affected Components
| Component | Path | Role |
|-----------|------|------|
| Marketing layout | `cannamanage-frontend/src/app/(marketing)/layout.tsx` | Shared header/footer for marketing pages |
| Homepage (NEW) | `cannamanage-frontend/src/app/(marketing)/page.tsx` | Landing page — hero, features, trust signals |
| Pricing page | `cannamanage-frontend/src/app/(marketing)/pricing/page.tsx` | Pricing cards with storage tiers |
| Auth layout | `cannamanage-frontend/src/app/(auth)/layout.tsx` | Centered flex container for login |
| Admin login | `cannamanage-frontend/src/app/(auth)/login/page.tsx` | Admin/staff login form |
| Portal login | `cannamanage-frontend/src/app/(portal)/portal-login/page.tsx` | Member portal login form |
| PlanTier enum | `cannamanage-domain/src/main/java/de/cannamanage/domain/enums/PlanTier.java` | TRIAL, STARTER, PRO, ENTERPRISE |
| Club entity | `cannamanage-domain/src/main/java/de/cannamanage/domain/entity/Club.java` | Needs `storageUsedBytes` field |
| Document entity | `cannamanage-domain/src/main/java/de/cannamanage/domain/entity/Document.java` | Has `fileSize` field — source of truth for usage |
| DocumentService | `cannamanage-service/src/main/java/de/cannamanage/service/DocumentService.java` | Upload logic — needs quota check |
| StorageQuotaService (NEW) | `cannamanage-service/src/main/java/de/cannamanage/service/StorageQuotaService.java` | Quota calculation and enforcement |
| StorageController (NEW) | `cannamanage-api/src/main/java/de/cannamanage/api/controller/StorageController.java` | REST endpoint for storage usage |
| Flyway V36 (NEW) | `cannamanage-api/src/main/resources/db/migration/V36__storage_quota.sql` | Add storage tracking column |
| i18n messages | `cannamanage-frontend/src/messages/de.json` | New keys for landing page, pricing storage |
| Documents frontend service | `cannamanage-frontend/src/services/documents.ts` | Needs quota-exceeded error handling |
---
## 3. Current State (Ist-Zustand)
### Marketing Pages
- **No landing page** exists at `(marketing)/page.tsx` — the root `/` route likely falls through or shows a 404
- **Pricing page** has 3 tiers (Starter €19, Pro €49, Enterprise) with member limits and feature lists, but **no storage information**
- **Marketing layout** has a sticky header with logo + "Preise" + "Anmelden" links, and a footer with Produkt/Rechtliches columns
- Navigation text is hardcoded German (not i18n) in the layout
### Login Pages
- **Auth layout** is a minimal centered flex container: `fixed inset-0 z-50 flex items-center justify-center`
- **Admin login** renders a centered card with logo, email/password form, forgot password link, and portal link
- **Portal login** is nearly identical but uses portal-specific translations and mock auth
- Both pages use the same visual pattern — no split-layout, no brand messaging during auth
### Storage Backend
- **Document entity** already tracks `fileSize` (Long) per file
- **PlanTier enum** exists: TRIAL, STARTER, PRO, ENTERPRISE
- **No storage quota concept** exists anywhere — no `storage_used_bytes` column, no quota checks on upload
- **DocumentService** handles upload/download/delete but never checks cumulative storage
- Latest Flyway migration: `V35__generated_reports_add_timestamps.sql`
---
## 4. Risk Assessment
| Risk | Probability | Impact | Mitigation |
|------|-------------|--------|------------|
| Landing page doesn't convert (poor copy/design) | Medium | Medium (lost signups) | Follow proven SaaS landing page patterns; iterate based on analytics |
| Storage quota breaks existing uploads | Low | High (data loss) | Implement as soft-limit first — warn but don't block for existing over-limit tenants |
| i18n key explosion | Low | Low (maintenance) | Group new keys under `marketing.home`, `marketing.pricing.storage` namespaces |
| Split login layout breaks on mobile | Medium | Medium (can't log in) | Mobile-first design: left panel hidden on `<md` breakpoints |
| Quota calculation performance (SUM query) | Low | Medium (slow uploads) | Cache quota in `storage_used_bytes` column; recalculate on upload/delete |
---
## 5. Solution Options
### Option A: Full Sprint — All 4 Areas (Recommended)
- Landing page, login redesign, pricing update, storage quota backend
- **Effort:** ~16-20 hours
- **Pros:** Complete marketing+monetization story, enables public launch
- **Cons:** Larger scope, more testing surface
### Option B: Frontend Only — Landing + Login + Pricing (No Backend)
- Skip StorageQuotaService, just update frontend
- **Effort:** ~8-10 hours
- **Pros:** Faster delivery, lower risk
- **Cons:** Storage limits are marketing fiction without enforcement
### Option C: Backend Only — Storage Quota (No Marketing)
- Implement quota enforcement, defer marketing pages
- **Effort:** ~6-8 hours
- **Pros:** Real monetization enforcement
- **Cons:** No user-facing marketing value, can't launch publicly
---
## 6. Recommendation
**Option A** — the full sprint. The four areas are interdependent: the pricing page promises storage limits that the backend must enforce, and the landing page is the entry point that drives users to pricing. Login redesign is a low-risk polish pass that significantly improves first impressions.
The storage quota backend should be designed as an **incremental counter** (update `storage_used_bytes` on upload/delete) rather than a `SUM` query on every upload — this keeps upload latency constant regardless of document count.
---
## 7. Open Questions
- [ ] Should the landing page include a product screenshot/mockup, or is an illustration-based hero preferred?
- [ ] For portal login left panel: show rotating testimonials, or static feature highlights?
- [ ] Storage overage billing (€0.15/GB/mo for Pro) — is this just displayed in pricing, or should we build the actual billing integration now?
- [ ] Free trial — is TRIAL tier (PlanTier enum already has it) time-limited? Should landing page mention trial duration?