- 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
7.2 KiB
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
- Landing Page — Create a professional homepage that converts visitors to signups
- Login Redesign — Split-layout login pages that reinforce brand value during auth flow
- Pricing Rework — Add storage tier information, update pricing model
- 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_bytescolumn, 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?