Skip to main content
Petanque Life
← Back to all features
19

Homepage & Marketing Website

163 features · 17 subsystems

Public-facing marketing website at **petanque.life** that explains the platform, showcases features, and converts visitors to users. Separate from the CMS-driven federation/club websites — this is the "product" site.

Landing Page & Positioning

F19.01
Planned
How it works
  • F19.01.01 Shipped

    Hero section with value proposition and CTA targeting players, clubs, and federations

    ✅ PL-F1901a · app/ GuestHome editorial premium-hero (PL-T304)
  • F19.01.02 Shipped

    Audience-segmented entry points with "I'm a Player", "I'm a Club", "I'm a Federation" cards

    ✅ PL-F1901a
  • F19.01.03 Shipped

    Animated feature showcase providing a visual walkthrough of key platform capabilities

    ✅ PL-F1901a
  • F19.01.04 Shipped

    Social proof section with federation logos, player count, country count, and testimonials

    ✅ PL-F1901a · app/ ambassador-rail + featured-tävlingsticker (PL-T304)
  • F19.01.05 Shipped

    Live stats ticker showing matches being played now, players online, and competitions today

    ✅ PL-F1901b · app/ desktop hero side-ticker (PL-T304)
  • F19.01.06 Shipped

    Video intro and product demo reel embedded on the landing page

    ✅ PL-F1901b
  • F19.01.07 Shipped

    Multi-language landing page with at minimum FR, EN, ES, and SV translations

    ✅ PL-F1901b · app/ landing.* namespace i 5 språk (PL-T304)

Feature Pages

F19.02
Planned

Dedicated pages per feature area to sell the platform in depth.

How it works
  • F19.02.01 Shipped

    Feature overview page summarising all 18 platform domains with visuals and entry-points

    ✅ PL-F1902a
  • F19.02.02 Shipped

    Competition management feature page covering formats, draw engine, live scoring and results

    ✅ PL-F1902a
  • F19.02.03 Shipped

    Live production studio feature page with multi-camera, overlays, and streaming capabilities

    ✅ PL-F1902a
  • F19.02.04 Shipped

    Federation management feature page covering hierarchy, licensing, and finance workflows

    ✅ PL-F1902a
  • F19.02.05 Shipped

    CMS and websites feature page showcasing custom sites, page builder, and dynamic widgets

    ✅ PL-F1902a
  • F19.02.06 Shipped

    Player experience feature page highlighting ELO, stats, training diary, and casual games

    ✅ PL-F1902a
  • F19.02.07 Shipped

    Club management feature page covering members, finance, communication, and website tooling

    ✅ PL-F1902b
  • F19.02.08 Shipped

    Mobile app feature page focused on offline play, scoring, and QR check-in

    ✅ PL-F1902b
  • F19.02.09 Shipped

    Officials and umpire feature page covering grades, assignment, and training

    ✅ PL-F1902b
  • F19.02.10 Shipped

    Interactive feature comparison table showing what each plan includes

    ✅ PL-F1902b
  • F19.02.11 Shipped

    Screenshots and video demos embedded per feature page

    ✅ PL-F1902b
  • F19.02.12 Shipped

    Public feature request and roadmap page with voting

    ✅ PL-F1902b

Audience-Specific Pages

F19.03
Planned

Tailored messaging per target group.

How it works
  • F19.03.01 Shipped

    "For Players" page covering ELO, stats, finding tournaments, casual games, and training diary

    ✅ PL-F1903a
  • F19.03.02 Shipped

    "For Clubs" page covering member management, website, finance, events, and communication

    ✅ PL-F1903a
  • F19.03.03 Shipped

    "For Federations" page covering licensing, hierarchy, compliance, rankings, and reporting

    ✅ PL-F1903a
  • F19.03.04 Shipped

    "For Tournament Directors" page covering all formats, draw engine, live scoring, and streaming

    ✅ PL-F1903a
  • F19.03.05 Shipped

    "For Umpires" page covering certification, assignment, tools, and evaluation

    ✅ PL-F1903a
  • F19.03.06 Shipped

    "For Coaches" page covering training programs, player development, and video analysis

    ✅ PL-F1903b
  • F19.03.07 Shipped

    "For Spectators" page covering live scores, streaming, predictions, and following players

    ✅ PL-F1903b
  • F19.03.08 Shipped

    "For FIPJP / Continental Federations" page covering global oversight, world rankings, and compliance

    ✅ PL-F1903b
  • F19.03.09 Shipped

    Case studies and success stories tailored per audience segment

    ✅ PL-F1903b

Pricing & Plans

F19.04
Planned
How it works
  • F19.04.01 Shipped

    Pricing page with side-by-side plan comparison across tiers

    ✅ PL-F1904a
  • F19.04.02 Shipped

    Plan feature matrix that is interactive and filterable by audience type

    ✅ PL-F1904a
  • F19.04.03 Shipped

    Currency selector that displays prices in the visitor's local currency

    ✅ PL-F1904a
  • F19.04.04 Shipped

    Annual versus monthly billing toggle with discount indicator

    ✅ PL-F1904a
  • F19.04.05 Shipped

    Custom enterprise pricing CTA targeting large federations and chains

    ✅ PL-F1904b
  • F19.04.06 Shipped

    Free trial and freemium entry point linked from pricing page

    ✅ PL-F1904b
  • F19.04.07 Shipped

    FAQ section grouped per plan to address common pre-purchase questions

    ✅ PL-F1904b
  • F19.04.08 Shipped

    ROI calculator estimating savings versus current tools per federation profile

    ✅ PL-F1904b

Trust & Credibility

F19.05
Planned
How it works
  • F19.05.01 Shipped

    Testimonials from federations, clubs, and players surfaced across the marketing site

    ✅ PL-F1905a
  • F19.05.02 Shipped

    Partner and federation logos bar building social proof on key pages

    ✅ PL-F1905a
  • F19.05.03 Shipped

    Press mentions and media coverage section linking to external articles

    ✅ PL-F1905a
  • F19.05.04 Shipped

    Security and privacy page covering GDPR, data hosting, and encryption

    ✅ PL-F1905a
  • F19.05.05 Shipped

    Public uptime status page surfacing service health and recent incidents

    ✅ PL-F1905b
  • F19.05.06 Shipped

    "Built on Craft Easy" technology trust signals highlighting framework provenance

    ✅ PL-F1905b
  • F19.05.07 Shipped

    Open API documentation link from the marketing site to the developer portal

    ✅ PL-F1905b
  • F19.05.08 Shipped

    Community size metrics shown as a live counter (players, clubs, countries)

    ✅ PL-F1905b

Conversion & Onboarding

F19.06
Planned
How it works
  • F19.06.01 Shipped

    Sign-up flow for individual players on the free tier with email verification

    ✅ PL-F1906a
  • F19.06.02 Shipped

    Club registration flow where the club admin creates a new club tenant

    ✅ PL-F1906a
  • F19.06.03 Shipped

    Federation onboarding flow with a guided multi-step setup wizard

    ✅ PL-F1906a
  • F19.06.04 Shipped

    Demo request form for federations wanting a guided product tour

    ✅ PL-F1906a
  • F19.06.05 Shipped

    Self-service demo environment with a pre-populated sandbox containing sample data

    ✅ PL-F1906a
  • F19.06.06 Shipped

    Migration assessment tool estimating which data can be imported from a current system

    ✅ PL-F1906b
  • F19.06.07 Shipped

    Contact sales form for enterprise and federation deals with qualification fields

    ✅ PL-F1906b
  • F19.06.08 Shipped

    Newsletter signup with double opt-in (PENDING→ACTIVE), confirmation email via ACS, unsubscribe flow, 4 languages

    ✅ PL-F1906b, PL-T044
  • F19.06.09 Shipped

    Webinar registration for product demos and Q&A sessions with calendar integration

    ✅ PL-F1906b

Content & SEO

F19.07
Shipped
How it works
  • F19.07.01 Shipped

    Blog covering product updates, petanque stories, tips, and federation spotlights

    ✅ PL-F1907a
  • F19.07.02 Shipped

    Knowledge base and help center with searchable articles per audience

    ✅ PL-F1907a
  • F19.07.03 Shipped

    API documentation portal linked from the marketing site for developers

    ✅ PL-F1907a
  • F19.07.04 Shipped

    Public changelog with versioned release notes

    ✅ PL-F1907a
  • F19.07.05 Shipped

    SEO-optimised pages per country (e.g. "Petanque Life for Swedish Petanque")

    ✅ PL-F1907b
  • F19.07.06 Shipped

    Structured data with JSON-LD for SoftwareApplication and Organization on key pages

    ✅ PL-F1907b
  • F19.07.07 Shipped

    Sitemap and meta optimisation across all marketing routes

    ✅ PL-F1907b
  • F19.07.08 Shipped

    Social sharing previews with per-page Open Graph images

    ✅ PL-F1907b

Analytics & Conversion Tracking

F19.08
Shipped
How it works
  • F19.08.01 Shipped

    Privacy-respecting analytics (Plausible/Umami)

  • F19.08.02 Shipped

    Conversion funnel tracking (visit → sign up → active user)

  • F19.08.03 Shipped

    A/B testing capability for landing pages

  • F19.08.04 Shipped

    UTM parameter tracking for campaigns

  • F19.08.05 Shipped

    Heatmap integration (understand user behavior on key pages)

Pricing & Self-Service Onboarding

F19.09
Shipped
How it works
  • F19.09.01 Shipped

    Pricing page with tier comparison (Club / Professional / Federation)

    ✅ PL-F1909a
  • F19.09.02 Shipped

    Subscription checkout (Stripe Checkout integration, plan selection, billing toggle)

    ✅ PL-F1909a
  • F19.09.03 Shipped

    Federation deal request form (enterprise contact form for national/continental federations)

    ✅ PL-F1909a
  • F19.09.04 Shipped

    Club onboarding wizard (multi-step: club details → plan → admin setup)

    ✅ PL-F1909a
  • F19.09.05 Shipped

    Demo booking with Calendly integration (self-scheduling, inline embed, form fallback)

    ✅ PL-F1909b
  • F19.09.06 Shipped

    Trial period with automatic conversion (14-day free trial, auto-convert toggle)

    ✅ PL-F1909b
  • F19.09.07 Shipped

    Currency auto-detection on pricing page (browser locale/timezone-based)

    ✅ PL-F1909b
  • F19.09.08 Shipped

    Payment history and invoice management

Revenue Tracking & Business Analytics

F19.10
Shipped
How it works
  • F19.10.01 Shipped

    MRR/ARR dashboard with growth indicators (MoM/YoY) and churn-adjusted forecasts

  • F19.10.02 Shipped

    Churn analytics per segment with cohort retention curves and early warning indicators

  • F19.10.03 Shipped

    CAC tracking per channel with payback period, efficiency ranking, and attribution

  • F19.10.04 Shipped

    LTV per segment with LTV/CAC ratio (target >3:1) and contribution margin analysis

  • F19.10.05 Shipped

    Conversion funnel (visit → trial → paid) with drop-off analysis

  • F19.10.06 Shipped

    Cohort analysis with retention heatmap and trend indicators

  • F19.10.07 Shipped

    Revenue forecast with confidence intervals and scenario analysis

Marketing & Content

F19.11
Shipped
How it works
  • F19.11.01 Shipped

    Blog/news section with MDX content collections, Astro Content Collections, full article rendering

    ✅ PL-F1911a
  • F19.11.02 Shipped

    Case studies (federations that succeeded) — 6 studies with category filtering, 4 languages

    ✅ PL-F1911a
  • F19.11.03 Shipped

    Testimonials from players and clubs — dedicated page with 9 testimonials, category filtering, 4 languages

    ✅ PL-F1911a
  • F19.11.04 Shipped

    Newsletter signup with double opt-in — confirmation email flow, confirmation landing page, 4 languages

    ✅ PL-F1911a
  • F19.11.05 Shipped

    Public product roadmap — interactive roadmap with shipped/in-progress/planned status, feature voting (localStorage), domain-grouped features, search and filter, 4 languages (EN/FR/ES/SV)

    ✅ PL-F1911b
  • F19.11.06 Shipped

    Public changelog with RSS — timeline layout with versioned entries (v0.1.0–v0.6.0), change type badges (added/improved/fixed), RSS 2.0 feed at /changelog/rss.xml, 4 languages

    ✅ PL-F1911b
  • F19.11.07 Shipped

    Help center / docs — documentation landing page with 3 categories (Getting Started 10 steps, Administration, By Stakeholder 9 guides), search, related resources (glossary + help center), 4 languages

    ✅ PL-F1911b
  • F19.11.08 Shipped

    Glossary for pétanque terms — 7 categories (~50 terms), multilingual table (French/English/Swedish + description), category navigation, search filtering, 4 languages

    ✅ PL-F1911b

ROI & Self-Service Sales Tools

F19.13
Shipped
How it works
  • F19.13.01 Shipped

    Interactive ROI calculator with 4 tenant-type modes (Club/Venue/Federation/Chain), type-specific input fields, live output (annual savings, ROI factor, payback time, 5-year comparison), client-side calculation, shareable URL with pre-filled params, 4 languages (EN/FR/ES/SV), WCAG 2.1 AA accessible, Plausible analytics events

    ✅ PL-T040

Platform Status & Transparency

F19.12
Shipped
How it works
  • F19.12.01 Shipped

    Live status page with real health-checks (API, DB, Redis, Auth, SWA), 60s-interval background collector (CollectStatusSamplesJob), ServiceHealthSample rolling-window uptime (90d TTL), StatusIncident admin-reporting, client-side fetch with 30s auto-refresh and honest fail-red fallback on timeout, 4 languages

    ✅ PL-T045

Physical Scoreboard Hardware Rental

F19.14
Shipped
How it works
  • F19.14.01 Shipped

    ScoreboardKit template model (Trial 8 / Silver 32 / Gold 64 / Platinum 128 / Custom) with pricing (base_price, deposit_per_board, shipping domestic/EU), slug-indexed catalog

    ✅ PL-T069
  • F19.14.02 Shipped

    ScoreboardKitInstance inventory model with lifecycle status (in_stock/booked/shipping/in_use/returning/maintenance/retired), serial_no unique, gateway + scoreboard refs, warehouse tracking

    ✅ PL-T069
  • F19.14.03 Shipped

    Public kit catalog endpoints (GET /scoreboard-kits, GET /scoreboard-kits/{id}) with active-only filtering

    ✅ PL-T069
  • F19.14.04 Shipped

    Admin kit template CRUD (POST/PATCH /scoreboard-kits) with slug uniqueness enforcement

    ✅ PL-T069
  • F19.14.05 Shipped

    Admin kit instance inventory (GET/POST /scoreboard-kit-instances) with template/status/warehouse filters

    ✅ PL-T069
  • F19.14.06 Shipped

    Availability calendar endpoint (GET /scoreboard-kits/{id}/availability?from=&to=) with 7-day rental buffer, maintenance exclusion, next_available_date

    ✅ PL-T069
  • F19.14.07 Shipped

    Seed script for 4 default kit templates (Trial/Silver/Gold/Platinum) with illustrative pricing, idempotent

    ✅ PL-T069
  • F19.14.08 Shipped

    ScoreboardRental model with full lifecycle status machine (quoted→payment_pending→paid→shipping→in_use→returning→returned→closed/cancelled/damage_pending), pricing breakdown (rental/shipping/insurance/total), Stripe refs

    ✅ PL-T070
  • F19.14.09 Shipped

    Rental booking endpoint (POST /scoreboard-rentals) with atomic kit instance reservation via MongoDB findOneAndUpdate, pricing calculation (base + extension days × boards × 25 SEK + shipping + 10% insurance)

    ✅ PL-T070
  • F19.14.10 Shipped

    Stripe Checkout integration for rental payments (mode: payment, line items: rental/shipping/insurance, automatic_tax, success/cancel URLs) + Stripe Invoice for NET-30 customers

    ✅ PL-T070
  • F19.14.11 Shipped

    Rental list/detail endpoints (GET /scoreboard-rentals, GET /{id}) with tenant_id and status filters, cursor pagination

    ✅ PL-T070
  • F19.14.12 Shipped

    Rental cancellation (POST /{id}/cancel) with status-dependent logic: immediate cancel for quoted/booked/payment_pending, Stripe refund for paid

    ✅ PL-T070
  • F19.14.13 Shipped

    Checkout URL regeneration (GET /{id}/checkout-url) for expired Stripe sessions

    ✅ PL-T070
  • F19.14.14 Shipped

    Reservation timeout job: auto-cancel payment_pending rentals after 30 min, release kit instances back to in_stock

    ✅ PL-T070
  • F19.14.15 Shipped

    Tamper auto-arm/disarm: dispatch tamper_arm downlink on rental.status→in_use, tamper_disarm on →returning

    ✅ PL-T070
  • F19.14.16 Shipped

    ScoreboardRentalDeposit model with lifecycle status machine (pending_setup→setup_complete→charged→refunded/partial_refunded/captured_for_damage), Stripe refs (SetupIntent, PaymentMethod, Customer, PaymentIntent), damage_report_id linkage

    ✅ PL-T071
  • F19.14.17 Shipped

    Deposit setup endpoint (POST /scoreboard-rentals/{id}/setup-deposit) with Stripe SetupIntent creation, Customer creation, idempotent re-retrieval

    ✅ PL-T071
  • F19.14.18 Shipped

    Off-session deposit charge (POST /{id}/charge-deposit) using saved PaymentMethod, admin-larm on card expiry/decline

    ✅ PL-T071
  • F19.14.19 Shipped

    Full deposit refund (POST /{id}/refund-deposit) via Stripe Refund API on safe kit return

    ✅ PL-T071
  • F19.14.20 Shipped

    Damage capture with partial refund (POST /{id}/capture-deposit-for-damage) — damage_cost deducted, remainder refunded, damage_report_id linkage for PL-T073

    ✅ PL-T071
  • F19.14.21 Shipped

    Deposit status endpoint (GET /{id}/deposit) for rental deposit lookup

    ✅ PL-T071
  • F19.14.22 Shipped

    Stripe webhook handlers: setup_intent.succeeded → setup_complete, payment_intent.succeeded (deposit type) → charged, charge.refunded → refunded/partial_refunded

    ✅ PL-T071
  • F19.14.23 Shipped

    www feature page /features/scoreboards: hero, SVG mockups, tech specs table, use-cases, referee call, live scoring, kit price cards with API fallback, JSON-LD Product schema

    ✅ PL-T073
  • F19.14.24 Shipped

    www kit catalog /scoreboards: server-side fetch with 3 s timeout + static fallback, availability indicators (green/amber/red), 4-col card grid

    ✅ PL-T073
  • F19.14.25 Shipped

    www booking flow /scoreboards/book/[slug]: date picker → availability check → contact form → insurance toggle → Turnstile → Stripe Checkout redirect

    ✅ PL-T073
  • F19.14.26 Shipped

    www booking status /scoreboards/booking/[id]: server-side fetch with Stripe session token, status badge, deposit lifecycle display

    ✅ PL-T073
  • F19.14.27 Shipped

    Scoreboard section added to 5 audience pages (event-organisers, tournament-directors, umpires, federations, venues) via audience-pages.ts section6

    ✅ PL-T073
  • F19.14.28 Shipped

    Comparison table: new "Physical Scoreboards" category with 5 features (live_score, referee_call, kit_rental, custody, ota)

    ✅ PL-T073
  • F19.14.29 Shipped

    i18n: all scoreboard copy keys in en, sv, es, fr (4 languages × ~100 keys)

    ✅ PL-T073
  • F19.14.30 Shipped

    Navigation: "Scoreboards" link in header nav + footer product column

    ✅ PL-T073

Score-Engine Integration (Uplink → Match State)

F19.15
Shipped
How it works
  • F19.15.01 Shipped

    Score-engine service: apply_uplink() processar ScoreboardEvent-flaggor och uppdaterar Match-dokument

    ✅ PL-T067
  • F19.15.02 Shipped

    Score-validering: max 13 poäng, avvisa decrement > 1, avvisa update på completed match

    ✅ PL-T067
  • F19.15.03 Shipped

    Match-final-flöde: match_final-flagga → status completed, vinnare satt, set_match-downlink för nästa match

    ✅ PL-T067
  • F19.15.04 Shipped

    ScoreboardAlert-modell: low_battery, over_temp, lost, stale, tamper med severity (warning/critical)

    ✅ PL-T067
  • F19.15.05 Shipped

    Tamper-eskalering: > 3 events inom 5 min → severity critical, tamper_event_count tracking

    ✅ PL-T067
  • F19.15.06 Shipped

    Admin-endpoints: assign-next-match, tamper-arm, tamper-disarm, alerts-lista med filter

    ✅ PL-T067
  • F19.15.07 Shipped

    SSE event-stream (GET /scoreboards/{id}/event-stream) för live admin-vy

    ✅ PL-T067
  • F19.15.08 Shipped

    Automatisk trigger: score-engine körs efter ingest sparar event

    ✅ PL-T067

Webinar Management

F19.16
Shipped

Publika sidor `/webinar` + `/webinar/{slug}` + en "next webinar"-strip

How it works
  • F19.16.01 Shipped

    MarketingWebinar-modell: slug (unique index), title_i18n, description_md_i18n, starts_at, duration_minutes (15–180), host_name, host_email, speakers[], max_attendees, meet_url, calendar_event_id, recording_url, slides_url, status (DRAFT/SCHEDULED/LIVE/ENDED/PUBLISHED/CANCELLED), promote_on_homepage, promote_weeks_before (1–12, default 4), tags[]

    ✅ PL-T151
  • F19.16.02 Shipped

    MarketingWebinarAttendee + MarketingWebinarInterest — attendee med compound-index (webinar_id, email), interest med unique-index på email och topics[], unsubscribed, notified_count, last_notified_at

    ✅ PL-T151
  • F19.16.03 Shipped

    Publika endpoints: GET /public/webinars (upcoming, cache 5 min), GET /public/webinars/past (published + recording_url), GET /public/webinars/next (banner, 204 när tom), GET /public/webinars/{slug} (detalj) — leakar aldrig DRAFT/CANCELLED

    ✅ PL-T151
  • F19.16.04 Shipped

    POST /public/webinars/{slug}/register — idempotent på email, Turnstile + per-IP rate-limit (10/24h), 409 webinar_full/webinar_not_open_for_registration, skickar bekräftelsemail via ACS

    ✅ PL-T151
  • F19.16.05 Shipped

    POST /public/webinar-interest — upsert på email, merge:ar topics + språk, honeypot website_url → silent success, rate-limit 20/IP/24h, flippar tillbaka unsubscribed=false på återkomst

    ✅ PL-T151
  • F19.16.06 Shipped

    Dynamisk www-hubsida /webinar (+ sv/fr/es-locales): hero, upcoming-grid (md:3-kol), empty-state med interest-formulär (6 topics), past recording-grid, 4-språks i18n, window.__plAnalytics-spårning

    ✅ PL-T151
  • F19.16.07 Shipped

    Dynamisk detaljsida /webinar/{slug}: SSG via getStaticPaths mot /public/webinars, hero + 2-kols-body + sidebar (host/duration/tags), registreringsformulär när SCHEDULED/LIVE utan inspelning, "Watch recording"-CTA när recording_url satt

    ✅ PL-T151
  • F19.16.08 Shipped

    Homepage WebinarBanner.astro — emerald-700-strip överst på alla 4 locale-homepages, fetchar /public/webinars/next, 204 → silent, localStorage-dismiss på pl.webinar_banner_dismissed_id återvisas automatiskt när nytt webinar promoteras

    ✅ PL-T151
  • F19.16.09 Shipped

    Google Workspace Calendar + Meet via Service Account + domain-wide delegation: create_meet_event/update_meet_event/cancel_meet_event, sendUpdates="all" på uppdatering/cancel, error-koder not_configured/client_library_missing/calendar_api_error

    ✅ PL-T151
  • F19.16.10 Shipped

    ACS-mailflöde via webinar_email.py: 5 inline-format-string-mallar (confirmation, reminder-24h, reminder-1h, recording-available, cancelled), Google Calendar + Outlook deep-links, en/sv med fallback till en

    ✅ PL-T151
  • F19.16.11 Shipped

    Batch-jobb webinar_reminder_dispatch (15 min, ±15 min tolerans, 24h + 1h-fönster) och webinar_post_event_dispatch (hourly: fan-out till deltagare + matchande interest-leads efter recording-attach) — idempotenta via reminder_*_sent_at / post_event_sent_at

    ✅ PL-T151

Newsletter Engine (super-premium, multi-list, multi-tenant)

F19.17
Shipped

*Introducerad: PL-T152. Full runbook i

How it works
  • F19.17.01 Shipped

    EmailDistributor-abstraktion med send_transactional / send_bulk / handle_webhook; MailjetDistributor + ACSDistributor (failover) + NullDistributor (dev/test)

    ✅ PL-T152
  • F19.17.02 Shipped

    Beanie-modeller: NewsletterList (platform/tenant-scope), NewsletterSubscription (pending/active/unsubscribed/bounced/complained/suppressed), NewsletterTemplate (MJML-source + rendered cache), NewsletterSegment, NewsletterCampaign (draft/scheduled/sending/sent/paused/cancelled), NewsletterEvent (90 d TTL), NewsletterSuppression, NewsletterAutomationFlow, NewsletterAutomationEnrolment, NewsletterAIQuota

    ✅ PL-T152
  • F19.17.03 Shipped

    Double-opt-in med HMAC-SHA256-signerade tokens (purpose-bound: confirm/prefs/unsub, TTL 14/30/90 d) — services/newsletter_tokens.py

    ✅ PL-T152
  • F19.17.04 Shipped

    Publika endpoints: POST /public/newsletter/subscribe (Turnstile + honeypot + rate-limit 5/IP/h), GET /public/newsletter/confirm, GET/PUT /public/newsletter/preferences/{token}, POST /public/newsletter/unsubscribe/{token}, POST /public/newsletter/unsubscribe-all/{token}, POST /public/newsletter/list-unsubscribe/{token} (RFC 8058 one-click), GET /public/newsletter/open/{...}.png, GET /public/newsletter/click/{...}?url=

    ✅ PL-T152
  • F19.17.05 Shipped

    Sys-CRUD: lists + subscribers + CSV-import med attesterad consent-proof + GDPR-radering + templates (MJML-editor) + segments (visual builder) + campaigns (wizard) + automations + suppressions + deliverability + analytics-overview

    ✅ PL-T152
  • F19.17.06 Shipped

    A/B-testing: variants + random-N% / full-random-split + pooled two-proportion z-test + Wilson confidence interval + winner-selection-job (services/newsletter_stats.py)

    ✅ PL-T152
  • F19.17.07 Shipped

    Send-time-optimering: engagement_profile = {best_hour_utc, best_weekday, confidence} per subscriber; dagligt refresh-job + dispatcher som schemalägger per-recipient inom 24h-fönster, fallback till scheduled_at vid confidence < 0.3

    ✅ PL-T152
  • F19.17.08 Shipped

    Drip-automations: AutomationFlow med visual flow-builder (react-flow, trigger/wait/send/branch/exit); preset-flows: 7-day onboarding, 30-day re-engagement, 90-day win-back; triggers: subscription_confirmed, webinar_registered, tenant_onboarded, user_inactive_days, manual_enroll

    ✅ PL-T152
  • F19.17.09 Shipped

    Dynamic content blocks i MJML: {% content-block key variants=[...] %} med send-time-evaluation per subscriber-context (språk/tenant/merge_data)

    ✅ PL-T152
  • F19.17.10 Shipped

    AI-assist via Gemini 2.5 Pro: /sys/newsletter/ai/subject-lines, /ai/content-polish, /ai/preview-audience-reaction (5 personas); quota 50 req/operator/24h via newsletter_ai_quota; alla calls audit-loggade med prompt+response-hash

    ✅ PL-T152
  • F19.17.11 Shipped

    Heatmaps + cohort-analytics: click-koordinat-aggregation per campaign, open/click-rate per cohort (tenant/role/language/source), engagement-score per subscriber (rolling 30d), at-risk-flagg (< 0.1 → feeder till re-engagement-automation)

    ✅ PL-T152
  • F19.17.12 Shipped

    Cross-client-preview via Litmus API: screenshots per klient (Gmail, Apple Mail, Outlook, Yahoo) + spam-score-check; blockerar schedule vid spam-score > 5

    ✅ PL-T152
  • F19.17.13 Shipped

    Visuell segment-builder: drag-and-drop AND/OR-grupper, live recipient-count, sparbara segments; allow-list av fält + ops (eq, neq, in, nin, gt/gte/lt/lte, regex escaped, exists); services/newsletter_segment.py

    ✅ PL-T152
  • F19.17.14 Shipped

    Campaign-dispatcher-job (newsletter-campaign-dispatcher, 1 min-cadence): throttled send enligt throttle_per_hour (default 5000/h); per recipient: MJML-render + merge-vars + link-rewrite + pixel-inject + compliance-footer + List-Unsubscribe-header + RFC 8058-one-click; pause/resume/cancel

    ✅ PL-T152
  • F19.17.15 Shipped

    Distributor-webhook: POST /_internal/distributor-webhook/{provider} med HMAC-signaturverifiering, idempotent på provider_event_id; hard_bounce → suppression; soft_bounce-escalation efter 5 consecutive; complaint → suppression + status=complained

    ✅ PL-T152
  • F19.17.16 Shipped

    Premium-template-gallery (12+ pre-designed): announcement, digest, event_invite, product_drop, case_study, win_back, re_engagement, onboarding_step, tournament_recap, scoreboard_release, federation_update, seasonal — clone-to-customize

    ✅ PL-T152
  • F19.17.17 Shipped

    Embeddable signup-form — Astro (www/src/components/conversion/NewsletterSignup.astro) + Next.js (web/src/components/blocks/NewsletterSignupBlock.tsx); prop listSlug, layouts (inline/modal/card), 4-språk i18n, Turnstile + honeypot

    ✅ PL-T152
  • F19.17.18 Shipped

    Preference-center-sida: www/src/pages/{en,sv,fr,es}/newsletter/preferences.astro med query-string-token, lista av lists i samma scope, name/language/per-list-membership, unsubscribe-all

    ✅ PL-T152
  • F19.17.19 Shipped

    Webinar-integration (T151): GDPR-strikt default-unticked opt-in på POST /public/webinars/{slug}/register; vid kryss skapas NewsletterSubscription(status=pending, source=webinar_registration) parallellt med webinar-confirmation

    ✅ PL-T152
  • F19.17.20 Shipped

    Tenant-admin read-only-vy: admin/app/(dashboard)/newsletter/{index,[id]}.tsx + /admin/newsletter/{lists,lists/{id}/subscribers,campaigns}-API scoped via request.state.tenant_id (403 utan tenant-kontext)

    ✅ PL-T152
  • F19.17.21 Shipped

    Compliance: consent-proof per subscribe (IP-hash + UA-hash + form_id + timestamp + method), CAN-SPAM physical-address auto-inject i footer, audit-trail för subscribe/confirm/preferences/unsubscribe/import/suppression/GDPR, 3-year post-unsub retention

    ✅ PL-T152
  • F19.17.22 Shipped

    Deliverability-dashboard: per from-domain reputation + SPF/DKIM/DMARC-status + bounce/complaint/unsub 30d-rater + spam-score-historik; halt-sends-action vid threshold-breach (bounce > 2 % eller complaint > 0.1 %)

    ✅ PL-T152
  • F19.17.23 Shipped

    Tester: 35 testfall i api/tests/test_t152_newsletter.py — unit (z-test, Wilson, pick_winner, tokens, segment DSL), integration (full subscribe→confirm→prefs→unsub-cykel, suppression, honeypot, rate-limit 429, tenant-admin 403), alla passerar

    ✅ PL-T152