# Teachfluence Web — Design Decisions & Gaps (team discussion doc)

**Status: living document — updated as the design work lands.**
This is the doc to walk through with the team. It captures (1) what the design set now covers, (2) the **new features** we designed that aren't in the app yet, (3) the **gaps** found and how we closed them, and (4) the **open decisions/questions** that need a human call.

How to read the designs alongside this doc:

- Open `index.html` (`python3 -m http.server 8091` → `http://127.0.0.1:8091/`).
- Every screen is tagged **Mevcut** (green — live today, captured 1:1 from the app) or **Planlanan** (amber — proposed, not built yet). See the legend on any canvas.

---

## 1. What the set covers

| # | Canvas | Provenance | Notes |
|---|---|---|---|
| 00–08 | Admin console (foundations · orders · catalog · course editor · marketing · forms · students · coaching/settings · web-CMS) | **Mevcut** | faithful capture of the live admin |
| 09–11 | Student app · storefront · marketing site | **Mevcut** | student/storefront in org theme (Flu = dark); marketing = Teachfluence brand |
| 12 | **Destek & Canlı Sohbet** (omnichannel inbox) | **Planlanan** | backend built, web live-chat is currently outsourced (Crisp/Intercom/Jivo) |
| 13 | **Topluluk & Alanlar** (community/spaces) | **Planlanan** | 14 backend modules, **completely headless on web** — largest single gap |
| 14 | **Bildirim Merkezi** (notifications) | **Planlanan** | PARTIAL today: a narrow admin bell exists (sub/payment only); center + prefs + push are the gap |
| 15 | **CRM & Müşteri İlişkileri** | **Planlanan** | zero web UI; extends the existing student-360 profile |
| 16 | **SCORM · xAPI · cmi5** | **Mevcut** | ← reclassified: this UI **already exists** (item-type + reporting + settings tab), just wasn't in the 00–11 capture set |
| 17 | **Analitik & Yönetim Paneli** | **Planlanan** | visitor/student/retention analytics + admin home + grading queue — backend APIs exist, **zero web consumers** |

Plus **planned bands inserted into existing Mevcut canvases** for the smaller scattered gaps (see §4) — each flagged with the amber "PLANLANAN" rail so it's clear which screens on an otherwise-live canvas are proposals.

---

## 2. Faithfulness audit (Task 1) — **done**

Method: every existing canvas (00–11) was re-checked against **(a) the live `flu` org** (read-only) and **(b) the real frontend code** in `pi-education-web` — exact Turkish labels from `messages/tr.json`, table columns, tab structure, filters, badges, and empty/error states pulled from the actual `CourseAdmin*` / storefront / student components. Drift was **fixed in place** (label text corrected, invented elements removed, dialog structures rebuilt to match). Four parallel audit agents covered 00–02, 03–05, 06–08, 09–11; each edit is anchored to a cited component or `tr.json` key.

**Categories of drift found & fixed** (representative — the 03–05 slice is listed in full because it was the last to land and is fully verified):

| Canvas | Representative fixes (all cited to real components / `tr.json`) |
|---|---|
| **03 Course editor** | Draft banner was course-specific (“Bu kurs taslak…/Yayına Al”) → real generic product copy (`PublishDraftBanner` + `Admin.Common.publishDraftBanner`); item-type picker listed two QUESTION **sub-types as top-level** → removed, Forum reordered before Webinar; section create/update dialog relabeled to the real `Bölümü Güncelle` fields (create is name-only); free-access badge “Ücretsiz Erişim”→“Ücretsiz”, release badge “Yakında”→“Yayınlanacak: 15 Şub”; exam buttons “AI ile Sınav Sorusu Oluştur”→“AI ile Soru Oluştur”, “Excel”→“Excel'den Soru Aktar”; invite dialog restructured (Doğrudan Kayıt is a **switch**, single submit — not two buttons); gradebook “Bekliyor”→“Değerlendiriliyor”; certificate editor’s **invented “Önizleme/Ayarlar” tabs removed** (it’s a single scrolling page); not-found “Kurs bulunamadı”→real generic `AccessGate.notFound`. |
| **04 Marketing** | Campaign status enum + page-title (browser-tab-only, no visible heading) corrected; system-emails table trimmed to its real 7 columns (no “Açılma”); promotions toolbar/card statuses/discount-type values, promotion-wizard steps, automation template names + trigger/action labels, and the automation-wizard nav (“Devam”→“İleri”) all matched to `tr.json`; tags create/delete/detail + tag-detail visibility label (`form.isPublic` = “Herkese Açık”) corrected. |
| **05 Forms** | Verified clean (labels/columns matched); a smart-quote-in-attribute slip introduced mid-edit was caught and reverted so all attribute quotes stay straight-ASCII. |
| **00–02, 06–11** | Same class of fixes (label/column/tab/badge/state drift) applied against live `flu` + FE code. Live spot-checks confirmed structurally faithful: Orders/overview (Gelir Analizi + 8 metric cards + Gelir Trendi), Courses hub (Takvim Etkinlikleri + Tablo/Takvim + Derslerim), Students roster (Kayıtlı Kullanıcılar; columns Öğrenci · Email · Etiketler · Toplam Harcama · Kaydolma Tarihi · Son Giriş · Son Aktivite). |

**Adversarial verify caught real defects** the authors missed — most notably a **SECRET-space leak** in the events CTA block (a “never shown” space surfaced as a public teaser → fixed to a PRIVATE space) and **invented backend signatures** in the scattered-gap bands (`grantProductAccess` had fabricated fields → corrected to the real `orderableId, studentId|email, message?`; `autoCaptionLanguages`→ real `captionLanguages`). Every band is div-balanced and passes the class-token audit against `_kit.css`.

---

## 3. New features designed (Planlanan)

Every feature below is **already merged to `main`** on the backend (models, enums, resolvers) but has **no admin web UI**. Each is multi-tenant, **opt-in per org** (an `enabled` settings flag), permission-gated (VIEW vs MANAGE scopes), realtime over SSE/WebSocket ticket handshakes (not GraphQL subscriptions), and English in the backend with Turkish rendered client-side.

### 12 · Destek & Canlı Sohbet (Support / omnichannel inbox)
- **What:** an in-house agent inbox across Web widget / E-posta / WhatsApp / Instagram / Facebook, with assignment, SLA, canned replies, business hours, CSAT, private notes, agent presence/typing.
- **Backend:** 14 models, 9 enums (`src/support/`). Statuses `Açık→Beklemede→Ertelendi→Çözüldü` (no "closed"); realtime SSE/WS; AV scan gate on attachments.
- **Screens:** inbox (filter+counts, bulk toolbar) · conversation thread + composer (canned "/", internal note, @mention) · contact panel (→ CRM 360) · assign/presence · settings (widget/CSAT/away/retention/caps) · inbox management (channels, round-robin, SLA, minted email `flu@support.teachfluence.com`, Meta linking) · canned replies · business hours · tags · web widget (org-themed).
- **Open questions:** keep the outsourced widget (Crisp/Intercom) or cut over to in-house? · outbound Email + FB send are **not yet implemented** on the backend · AV scanner is currently a stub · SLA is wall-clock.

### 13 · Topluluk & Alanlar (Community / membership spaces)
- **What:** Circle/Skool-style paid community — Spaces with post feed, threaded comments, likes, chat rooms, social events, gamification (badges/points/9-level leaderboard), moderation. Space access gated by **tags** (so a subscription tier auto-unlocks + auto-joins).
- **Backend:** ~14 modules, huge surface (`src/community*/`). Visibility `Açık/Özel/Gizli`; moderation `Beklemede/Onaylandı/Reddedildi`; fixed 9-level curve.
- **Screens:** settings (kill switch, auto-approve, level names, blocked words) · space directory/builder (drag-reorder, visibility/policy, required-tags) · member management · post feed / space detail · moderation queue + reports + attachment review · chat · events (Taslak/Yayında/İptal) · gamification/leaderboard · community analytics.
- **Open questions:** is this a near-term ship or a longer bet? (largest gap) · relationship to the existing in-course **Forum** (which IS built) — one social surface or two?

### 14 · Bildirim Merkezi (Notifications)
- **What:** unified in-app feed + realtime bell + push, with a per-user category×channel preference matrix and org-level routing.
- **Backend:** feed catalog + dispatch + SSE + Expo push (`src/notification*`). **v1 reality:** in-app feed always written; **push is the only gate-able channel**; email/WhatsApp stay on legacy pipelines (phase 2); SMS reserved. Today the web only has a narrow admin bell (sub/payment types).
- **Screens:** notification center/bell + full list · personal preferences (category×channel; only PUSH editable, IN_APP locked-on, others "yakında") · admin push prefs (mute + quiet hours + tz) · org push settings (per-event recipients) · org email settings · WhatsApp (phase-2 placeholder).
- **Open questions:** which channels to expose in the prefs UI now vs "coming soon"? · student notification center priority?

### 15 · CRM & Müşteri İlişkileri
- **What:** an agent-facing CRM layered on the existing student-360 (person spine = `OrganizationStudent`): lifecycle stages, 15-lane timeline, notes/calls/tasks, outreach (email + start-conversation) with monthly quota, Automation-backed sequences, saved segments, retention/churn analytics.
- **Backend:** 8 core tables + 15 timeline lanes (`src/crm/`, `src/retention/`). Fail-closed, quota-metered outreach; PII redaction retention.
- **Screens:** contact list/CRM inbox · contact 360 (stage + owner + acquisition source; tabs) · 15-lane timeline · notes/calls (+ org agenda) · tasks (+ org agenda) · outreach + quota · sequences · segment builder (live preview) · CRM settings · churn/at-risk analytics.
- **Open questions:** does CRM live under Öğrenciler or as its own top-level nav? · churn/retention analytics — here or in the Analytics canvas (17)? (currently shown in both as a teaser+detail split).

### 17 · Analitik & Yönetim Paneli (Analytics dashboards)
- **What:** the dashboards whose backend APIs exist with **zero web consumers** — visitor/traffic analytics (sources, funnel, retention), student analytics, a recent-activity feed, and a cross-course grading queue / "action needed". Plus a real Admin Home (today `/admin` just redirects to courses).
- **Backend:** `visitor-analytics`, `page-view`, `student-analytics`, `recent-activity`, `grading-queue`, `retention`.
- **Open questions:** the audit flags these as **"high-value, low-effort wins"** — worth prioritising? · do we want a dedicated Admin Home landing (vs the current redirect-to-courses)?

### 16 · SCORM · xAPI · cmi5 — **Mevcut** (capture gap, not a new feature)
- This UI **already ships** (SCORM/cmi5 as content-item types + embedded reporting + xAPI credentials/statement-browser as Settings tabs). It simply wasn't in the original 00–11 capture. Canvas 16 captures it (grouped into one canvas for review; the doc notes where each screen actually lives). Included here so the team sees the enterprise-LMS surface, but it is **live today**, not a proposal.

---

## 4. Gaps found & how we closed them

Beyond the five big feature areas (§3), the coverage audit found **smaller scattered gaps** — backend features with no web UI that live naturally inside an existing (Mevcut) canvas. These are added as **planned bands** (amber "PLANLANAN" rail) in their home canvas, so a reviewer sees the proposal next to the live screens it extends.

| Gap (backend built, no web UI) | Home canvas | Backend |
|---|---|---|
| **Group-specific pricing** / price groups ("student discount", #435) | 02 Catalog / pricing | `price-group`, `createPriceGroup`, `upsertOrderableGroupPrice` |
| **Meta integration / Instagram Auto-DM rules** | 04 Marketing | `meta-integration`, `create/updateInstagramAutoDmRule` |
| **Social-post composer** (captions/hashtags/theme/slides) | 04 Marketing | `social-post`, `social-post-theme` |
| **Order refund initiation** (view-only today) | 01 Orders | `refundOrder` / `adminRefundOrder` |
| **Subscription dunning ops** (retry charge, send reminder) | 02 Subscriptions | `retryStudentOrgSubscriptionCharge`, `sendDunningReminder` |
| **In-video-quiz authoring** (read-only today; also needs a BE mutation) | 03 Course editor | `in-video-quiz` |
| **Org video settings editor** (provider + caption langs, read-only) | 07 Settings | `organization-video-settings` |
| **Content-page redirect management** (auto-minted, no manual UI) | 08 Web/CMS | `content-page` redirects |
| **Data-provenance ledger** (AI-vs-human; only a passive line today) | 08 Web/CMS | `data-provenance` |
| **Grant free product access** | 06 Students | `grantProductAccess` |
| **Admin dark mode** (exists, never captured — this one is **Mevcut**, see D1) | 00 Foundations | root `ThemeProvider` toggle |

**Net-new (owner-requested this session), not a pre-existing gap:** a **website page-builder "Events" block** (calendar + list versions) — planned bands in **08** (editor: palette + settings) and **10** (rendered public block, org-themed). It sources public/OPEN-space published community events (`communityEvents`, canView-gated).
- **Reframed as a paid-membership CONVERSION CTA** (owner steer): the block shows the free OPEN-space events **and teases the member-only ones as locked cards** that drive a **"Üye Ol" CTA** toward the space's **`unlockingTiers`** (the subscription tier whose tag unlocks it) + `viewerRequiresPayment`. The old "gated events can't be shown publicly" constraint becomes the hook ("join to unlock"). Guardrails kept: **SECRET spaces never shown**; teaser cards carry **no PII/details** (masked title + date + space + "üyelere özel" only).
- Needs **new backend**: (1) a new editor block type (`src/editor/blocks/`) + public query wiring; (2) a **minimal public "gated-event teaser" query** returning masked, non-PII teaser data (count/date/space + unlockingTiers) for OPEN-page display — see §6.

_Three explicit gap-analysis passes (Task 3) sweep the whole set for missing states (empty/loading/error), missing flows, and consistency — logged as found._

- **Pass 1 — scattered feature gaps (done).** The §4 table above is the output: backend-built capabilities with no web UI, each added as a planned band in its home canvas (refund action, group pricing, subscription dunning, grant-access, video settings, redirect/provenance, admin dark-mode). Verify pass corrected invented mutation signatures.
- **Pass 2 — backend-ready but UI-less features (done).** Two genuine gaps confirmed by cross-checking `schema.gql` + FE render code (not just query fragments):
  - **In-video quiz (03.7, planned).** `InVideoQuiz` (video + quiz at `showAtProgress`, `allowSkip`) and student submit (`SubmitQuizInput.inVideoQuizId`) ship, but **neither the admin editor nor the student player renders it** (both only *query* `inVideoQuizzes`), and there is **no create/update/delete mutation**. Band shows the proposed admin authoring section **and** the student overlay (video pauses → quiz → “Atla” if skippable), with the missing mutation flagged as backend work.
  - **Meta / Instagram Auto-DM (04.10, planned).** Full backend ships (`metaIntegration`, `create/update/deleteInstagramAutoDmRule`, Meta webhook) but the panel has only a teaser card. Band shows connection (Instagram + WhatsApp Business + OAuth scopes), the Auto-DM rule builder (trigger `DM/COMMENT/STORY_REPLY`, keywords + VE/VEYA + case, post scope, response + delay + per-user cap), and the rule list — every field mapped 1:1 to `CreateInstagramAutoDmRuleInput`. WhatsApp here is the same channel that feeds Support (12) and notification delivery (14).
  - _Lesson reinforced:_ a present GraphQL **query fragment ≠ a built feature** — both these were being fetched but never rendered. Provenance marking checks render code, not just the query.
- **Pass 3 — states / consistency / completeness sweep (done).** A 4-agent read-only audit (admin / student-public / new-feature / backend-coverage) returned **17 evidence-cited findings**. Disposition:
  - **Fixed in place (faithfulness defects the design itself introduced):**
    - **17.3 conversion funnel** was drawn as an invented 5-step e-commerce funnel (Ziyaretçi → Ürün Görüntüleme → Sepete Ekleme → Ödeme Başlatma → Satın Alma) with a “Sepet Terk Oranı” KPI — **none of which exists**. The real `visitorConversionFunnel` is an **identity funnel** (visitors → identified → students → customers) and `PageViewEventType` has only PAGE_VIEW/PRODUCT_VIEW/CTA_CLICK. Redrawn to the real identity funnel; per-source table corrected to `visitorSources` (only `visitors`+`sessions` exist per source — conversion isn’t segmentable); removed the invented device filter (`VisitorFilterInput` = from/to/granularity only).
    - **17.4 / 17.6 source citations** corrected — cohort/retention → `retentionMatrix`, risk tiers/names → `atRiskOverview`/`atRiskStudents`/`churnAnalytics` (were mis-cited to the flat `studentOverview` snapshot); flagged the student enrollment/active **trend series** as derived (no time-series query exists).
  - **New Mevcut bands authored** for shipped surfaces that were missing from the “faithful capture” (all backed by real components + `tr.json`): **01.5 Payouts / Ödemeler** (the Orders page’s 2nd tab — transfers, upcoming, deductions, cumulative chart, export; `payoutTransfers`/`payoutDeductions`, OWNER/ADMIN+PI_PAYTR) · **02.9 Bundle (Paket) detail** (distinct Orderable per CLAUDE.md — bundled-orderables composition via `BundleOrderable` union + `BundlePricing`) · **09.9 student Exam-taking** (timed `ExamSession`: Başla / süre+soru gezgini / Sonuçlar + GRADE_PENDING) · **09.10 student Settings / Ayarlar** (`updateOrganizationStudent` profile + `PasswordSecurityCard` set/change).
  - **Documented gaps — deferred (not yet drawn), listed for the team to prioritise:** assignment submit/grade state in the learn player (09) · free-enrollment **davet** acceptance page (09) · payment-**failed** checkout state + Iyzico iframe variant (10) · Settings **Ödeme** + **Entegrasyonlar** + **Yasal Belgeler** sub-tabs (07) · **visitorRetention** cohort surface (17) · **supportUsageQuota** usage/billing screen (12) · custom-font upload (07) · per-space leaderboard + member own-stats (13). These are genuine shipped/near-shipped surfaces; they’re captured here rather than drawn to keep the set reviewable — each is a fast-follow band.

---

## 5. Cross-cutting design decisions

### D1 — Admin theme is light by default; dark is a real, supported mode
- **Evidence:** root `ThemeProvider` in `pi-education-web/app/layout.tsx` is `defaultTheme="light" enableSystem`, plus a user `mode-toggle` (`src/components/mode-toggle.tsx`). The live `flu` admin currently renders **dark** because this operator's system/user preference is dark.
- **Org `themePreference` (LIGHT/DARK/SYSTEM)** drives only the **student/website** surfaces (`src/lib/dark-mode.ts` → `learn` + `website`), **not** the admin.
- **Decision:** primary admin canvases (00–08) stay **light** (the default). We add a **dark-mode variant of the app shell** as a *Mevcut* screen (it exists today), so the design set acknowledges both. Student app (09) + storefront (10) render in the **org theme** (Flu = dark); marketing site (11) = Teachfluence brand.
- **Open question:** do we want the redesign to make admin dark-mode a first-class, org-brandable surface, or keep it a personal preference toggle?

### D2 — SCORM/xAPI/cmi5 is a *capture gap*, not a new feature
- A first pass (from backend models) suggested SCORM had no UI. A frontend cross-check proved otherwise: SCORM/cmi5 ship as **content-item types**, reporting is **embedded per item**, and xAPI credentials + the LRS statement browser are **Settings tabs** (`src/admin/xapi/`, `src/admin/settings/lrs-credentials/`).
- **Decision:** canvas 16 is **Mevcut** (it captures a live-but-previously-uncaptured feature), grouped into one canvas for review with each band captioned by where it actually lives. Lesson: "no route" ≠ "no UI" — many features live as Settings tabs, so route-only scans understate coverage.

### D3 — Own canvas vs. planned band
- **Cohesive new product areas** (Support, Community, Notifications, CRM, Analytics) get their **own Planlanan canvas** (12–15, 17).
- **Small scattered gaps** (refund action, group pricing, Instagram Auto-DM, social composer, redirect mgmt, dark mode…) get a **planned band inside their home Mevcut canvas** — the proposal sits next to the live screens it extends, which reads better for the team than a separate "misc" canvas.

### D4 — Community Events views (owner-decided this session)
Expanded canvas 13's events from one band into a full set (13.7–13.11), per the owner's answers:
- **Both admin + member views.** Admin = list + calendar, create/edit, moderator attendee roster. Member (org-dark) = upcoming list + RSVP toggle + "Kontenjan doldu" + personal agenda. **Constraint honored:** the member view shows only `goingCount` + own RSVP — the attendee roster is moderator-only (PII).
- **Both an org-wide Events hub and a per-space Events tab.** They back onto different queries: org-wide `communityEvents(from,to,spaceId)` (date-window, **no pagination**, upcoming/past split is client-side) vs per-space `CommunitySpace.events` (cursor-paginated, native `UPCOMING/PAST/ALL`). The design shows both and captions the tradeoff.
- **List ⇄ Calendar toggle** (month grid with day-dots, rhyming with the courses/coaching calendar) — the backend `from`/`to` window maps 1:1 onto a month.
- **Recurring events: designed as a PLANLANAN proposal, flagged as a backend gap.** The recurrence control in the create modal carries an amber "backend yok" tag + a note — see the open item below.
- **How students find/land on events (owner asked):** three entry points, all designed — (1) a persistent **"Etkinlikler" item in the community nav**; (2) a **"Yaklaşan Etkinlikler" highlight strip on the community home/feed** (quick Katıl + "Tümünü gör →"); (3) a **student-app home card** + event-reminder notifications for members not already in the community. The member landing page has the same list/calendar + upcoming/past, but stays `goingCount`-only (no roster).
- **Website page-builder "Events" block** (calendar + list) for the public site — see §4; needs new backend (editor block type + public query).

### D5 — Live Events ↔ Community Events: bridge, not merge (team-raised)
**The question the team raised:** *how do Live Events and Community Events relate — won't it confuse users?* They're distinct backend objects but overlap on "a live thing at a time," and both surface to students as bare "Etkinlikler". Investigation + the team's answers settled the direction.

**The two are genuinely different jobs (verified against `src/schema.gql`):**

| | **Canlı Etkinlik — `LiveEvent`** | **Topluluk Etkinliği — `CommunityEvent`** |
|---|---|---|
| Domain | Orderable **product** | Community RSVP gathering (not orderable) |
| Access | order / buy / gift / grant (free = a free order) | RSVP `GOING`/`NOT_GOING` |
| Price | yes (can also be free) | never priced |
| Live infra | **Zoom API** + `autoPublishRecording` | plain `meetingUrl` string, no Zoom API |
| Host / home | org instructors · catalog+storefront+library | any member · inside a community space |
| Job | **sell/distribute** a one-off live session | **engage** members with a free perk gathering |

**Decision (team chose "Bridge / convert", "no default", parity):** keep the two models separate but connect them with **one optional link — `CommunityEvent.liveEventId`** — and give them **feature parity**, so the admin's first choice is never a trap and students see one coherent surface.
- **One link, two behaviors.** *Convert:* "Ücretli ürüne dönüştür" on a Topluluk Etkinliği creates a linked `LiveEvent` (title/date/description carried over). *Mirror:* a linked event appears in **both** the storefront (as `LiveEvent`) **and** the community feed (a card badged "Ücretli · Canlı Etkinlik").
- **Access rule for a linked event:** **purchase replaces RSVP** (own → Katıl; not owned → Satın Al). Unlinked community events stay pure RSVP. Member-only ones keep the "Üye Ol" CTA (`unlockingTiers`, reusing the 10.7 locked-teaser pattern).
- **Unified student view + type badges** — one "Yaklaşan Etkinlikler" list mixes *Topluluk Etkinliği* / *Ücretli · Canlı Etkinlik* / *Üyelere özel*, each explicitly badged. That is the actual answer to "won't it confuse users": disambiguate by **badge**, not by hiding one type.
- **Feature parity (why "no default" is safe):** the team asked that **recordings AND attachments** work on **both** types. Today only LiveEvent records (via Zoom) and **neither** has attachments. So parity = add **attachments to both** (`attachments: [Attachment!]!`, reusing the DigitalProduct pattern) + **recording to CommunityEvent** (`recordingVideo: Video`, reusing `LiveCourseItem`). With parity, conversion is lossless and the initial pick doesn't lock the admin in.
- **Naming:** the team confirmed naming is fine — keep "Canlı Etkinlik" for the product, "Topluluk Etkinliği" for the community one; don't let bare "Etkinlikler" mean a community event outside the community shell.

**Designed as:** planned bands **13.14** (relationship model + admin convert flow + member unified badged feed) and **13.15** (Kayıt + Ekler parity on both). All **Planlanan** — every piece is new backend (see §6).

---

## 6. Open questions for the team

**The big one — build order.** All of §3 is backend-ready. Which do we build a web UI for next? A suggested ranking from the audit (impact × effort):

1. **Analytics dashboards (17)** — *high value, low effort.* The APIs exist with zero consumers; mostly read-only dashboards. Cheapest win. Also unlocks a real **Admin Home** (today `/admin` just redirects to courses).
2. **Support inbox (12)** — replaces an outsourced cost (Crisp/Intercom) with an owned surface; caveat: outbound email + FB send + AV scan are backend-incomplete.
3. **CRM (15)** — compounds with Support (shared contact spine) and directly drives revenue (outreach, sequences, at-risk).
4. **Notifications center (14)** — medium effort; the feed + prefs UI is the visible half of infrastructure that's already dispatching.
5. **Community (13)** — highest value *and* highest effort (14 modules, a whole product). Biggest bet; needs its own scoping.

Then the scattered §4 gaps as fast-follows (group pricing, refund action, Instagram Auto-DM, social composer, redirect mgmt, dark mode…).

**Specific decisions still needed:**
1. **Admin dark mode** — keep as a personal toggle, or make it a first-class org-brandable admin theme? (D1)
2. **Community vs Forum** — the in-course Forum already ships; is Community a separate social product or a superset? (§3.13)
3. **CRM placement** — own top-level nav, or nested under Öğrenciler? (§3.15)
4. **Churn/retention analytics** — owned by CRM (15) or Analytics (17)? (currently a teaser-in-17 / detail-in-15 split)
5. **Support cutover** — in-house inbox vs the current outsourced widget, given the backend send gaps. (§3.12)
6. **Notification channels** — expose only Push now (per v1), with Email/WhatsApp/SMS as "coming soon"? (§3.14)
7. **Events website block — needs a public "gated-event teaser" query.** To make the public Events block convert (tease member-only events → "Üye Ol"), the backend needs a minimal, anonymous-safe query returning **masked, non-PII** teaser data (date + space + count + `unlockingTiers`) for gated (PRIVATE-space) events — plus the new editor block type. SECRET spaces must remain excluded. Without it, the block can only show OPEN events (no conversion hook). (§4)
8. **Recurring community events — needs a backend workstream.** The owner wants recurring events (e.g. weekly office hours); the design shows a proposed recurrence control, but the backend has **no series/rrule support** and **no waitlist**. Shipping it means: a new recurrence/series model + occurrence generation, reminder-scheduling changes, and (separately) a decision on whether to add an event waitlist. Flagged here as its own backend item, not a v1 design deliverable. (§5 D4)
9. **Live Event ↔ Community Event bridge — a new backend workstream (team-raised).** To ship D5 (convert + mirror + parity), the backend needs: (a) `CommunityEvent.liveEventId` optional link + a reverse resolver (a `LiveEvent` knows its community mirror/space); (b) a convert mutation (`convertCommunityEventToLiveEvent`) that creates the LiveEvent, copies fields, and sets the link; (c) **mirror** — linked LiveEvents surfaced in `communityEvents`/`CommunitySpace.events` with **order-based (not RSVP) access** for linked events; (d) **recording on `CommunityEvent`** (`recordingVideo: Video` + a recording-ready notification); (e) **attachments on both** `CommunityEvent` and `LiveEvent` (`attachments: [Attachment!]!`, reusing the `DigitalProduct`/`Attachment` pattern). **Modeling decision to confirm with backend:** one linked row (a `CommunityEvent` carrying `liveEventId`) vs a shared `Event` supertype — the plan proposes the single-link approach as lower-risk. (§5 D5, bands 13.14–13.15)
