# Plan: Personalized Homepage for Logged-in Users

> **Status**: Partially Implemented (Google Scholar integration done)  
> **Last Updated**: March 12, 2026  
> **Priority**: High  
> **Depends On**: Existing homepage personalization, trending service, notification/activity signals

---

## ✅ COMPLETED: Google Scholar Integration (March 12, 2026)

Users can now link their Google Scholar profile to display their academic metrics on their Shamra Academia profile.

### What Was Built

| Component | File | Purpose |
|-----------|------|---------|
| **Entity** | `src/Entity/UserScholarProfile.php` | Stores linked Scholar profiles (citations, h-index, publications) |
| **Repository** | `src/Repository/UserScholarProfileRepository.php` | Query helpers (findByUser, findStale, etc.) |
| **Service** | `src/Service/GoogleScholarService.php` | SerpAPI client for fetching Scholar data |
| **Message** | `src/Message/SyncScholarProfile.php` | Async message for profile sync |
| **Handler** | `src/MessageHandler/SyncScholarProfileHandler.php` | Processes sync jobs via Messenger |
| **Controller** | `src/Controller/ScholarProfileController.php` | REST API endpoints |
| **Migration** | `migrations/Version20260312100000.php` | Creates `user_scholar_profile` table |
| **Config** | `config/services.yaml`, `config/packages/messenger.yaml` | Service wiring + async routing |

### API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/scholar` | Get user's linked profile data |
| `GET` | `/api/scholar/publications` | Get publications (paginated) |
| `POST` | `/api/scholar/validate` | Validate Scholar ID before linking |
| `POST` | `/api/scholar/link` | Link a Scholar profile |
| `POST/DELETE` | `/api/scholar/unlink` | Unlink profile |
| `POST` | `/api/scholar/sync` | Trigger manual resync (24h cooldown) |
| `GET` | `/api/scholar/co-authors` | Get co-authors list |

### Data Captured

- **Author info**: name, affiliation, interests, thumbnail
- **Metrics**: total citations, h-index, i10-index (all-time + since 2021)
- **Citation graph**: yearly citation counts for visualization
- **Publications**: title, authors, venue, year, citation count (up to 200)
- **Co-authors**: name, affiliation, Scholar ID

### Technical Notes

- **API**: SerpAPI (`google_scholar_author` engine) — $0.01/search, ~3 calls per full profile sync
- **Pagination**: 20 articles per API call, auto-fetches all pages
- **Sync frequency**: 24-hour minimum between syncs to avoid API abuse
- **Async**: Profile sync runs via Symfony Messenger (same worker as OCR)
- **Environment**: `SERP_API_KEY` in `.env` / `.env.dev`

### Deployment Status

- ✅ Code committed locally
- ⏳ **Pending**: Push to GitHub (WSL DNS issue) → triggers auto-deploy
- ⏳ **Pending**: Run migration on prod: `php bin/console doctrine:migrations:migrate`
- ⏳ **Pending**: Add `SERP_API_KEY` to production `.env`

### Next: UI Integration

After deployment, add these to the personalized homepage:
1. **Scholar Profile Card** in sidebar showing h-index, citation count, recent publications
2. **"Link Your Scholar Profile"** CTA for users without linked profiles
3. **Citation trend chart** using the `citation_graph` data

---

## TL;DR
The homepage already personalizes research results based on `TagInterestsUser` and `studyField`. But it's just a list of papers. Transform it into a **feed-style dashboard** with multiple content types: new papers, trending in your field, community activity, unread saved papers, and recent Q&A — giving users a reason to come back daily.

---

## Current State

- **Controller**: `HomepageController::indexAction()` (line 1141) — already has two code paths:
  - **Logged-in**: ES query by user interest tags → studyField fallback → recent docs fallback. Cached 30min.
  - **Anonymous**: Trending research (velocity algorithm from `TrendingResearchService`). Cached 30min.
- **Template**: `homepage_new.html.twig` — single card grid of `matchedResearches`
- **Data available**: `TagInterestsUser` (auto-tracked interests), `studyField`, `user_read_history`, `trending_research_cache`, community membership, favorite research

---

## Recent Progress (Already Done in the Platform)

These are recent platform changes that support this future without completing it directly:

- **Chat + engagement foundation shipped** (`14-chat-messaging` implemented, March 7, 2026), including inbox, unread counters, and async notification flow.
- **Notification infrastructure is active** (web bell, push, email via async messenger), which can later feed personalized homepage activity modules.
- **Search CTR tracking is available** (query/click logs + admin analytics), useful as a signal source for relevance ranking in homepage blocks.
- **Homepage controller already has robust fallbacks** (interest tags → study field → recent docs), so we can extend instead of rewrite.

---

## What Is Not Done Yet

- No dashboard-style logged-in homepage template exists yet.
- No multi-section personalized feed API endpoints exist yet.
- No section-level cache keys for personalized homepage modules exist yet.
- No “Continue Reading” or explicit empty-state cards are implemented on homepage.

---

## Steps

### Step 1: Expand indexAction Data for Logged-in Users

In `HomepageController::indexAction()`, add these data fetches for logged-in users:

1. **"New in Your Field" section** (already exists, but label it)
   - Current interest-tag ES query, limit 6
   
2. **"Trending This Week" section** (NEW)
   - `TrendingResearchService::getTrendingSlugs()` filtered to user's field/interests
   - Limit 4, distinct from section 1

3. **"Your Communities" section** (NEW)
   - Query `CommunityQuestion` for user's followed communities, `ORDER BY createdAt DESC LIMIT 3`
   - Show question title + community name + answer count

4. **"Unread Saved Papers" section** (NEW)
   - Query `UsersFavouriteResearches` for user, LEFT JOIN with `user_read_history` to find unread ones
   - Limit 3, show "You have X saved papers to read"

5. **"Questions You Might Answer" section** (NEW)
   - Query `AcademicQuestion` tagged with user's interest tags, `WHERE answerCount = 0 ORDER BY createdAt DESC LIMIT 3`

### Step 2: Create Dashboard-Style Template

Create `templates/homepage/dashboard.html.twig` (logged-in only):
- **Hero bar**: "Welcome back, {firstName}! You've read {count} papers this month."
- **Two-column layout**:
  - **Left (wide)**: New in Your Field (6 cards) → Trending (4 cards) → Recent Q&A
  - **Right (sidebar)**: Unread Saved (3 items) → Your Communities (3 recent questions) → Suggested Communities
- Each section has a "See More" link to the relevant page
- Keep existing anonymous homepage template unchanged

### Step 3: Cache Strategy

Each section should be independently cacheable:
- "New in Field": Cache 30min, key = `homepage:field:{userId}:{interestCount}`
- "Trending": Cache 30min, shared across users in same field, key = `homepage:trending:{fieldId}`
- "Communities": Cache 10min (more dynamic), key = `homepage:communities:{userId}`
- "Saved Papers": No cache (personal, small query)
- "Q&A": Cache 15min, key = `homepage:qa:{fieldId}`

### Step 4: AJAX-Load Sections for Performance

Initial page load renders only "New in Field" (server-side, fast).
Other sections load via AJAX after page paint:
- `GET /api/homepage/trending` → JSON
- `GET /api/homepage/communities` → JSON
- `GET /api/homepage/saved` → JSON
- `GET /api/homepage/questions` → JSON

Add these as lightweight actions in `HomepageController`.

### Step 5: "Continue Reading" Feature

Add a "Continue Reading" card at the top if the user has recently read a paper but didn't finish (heuristic: read < 30 seconds ago based on `user_read_history.createdAt`):
- "You were reading '{title}' — continue?"
- Link to the paper

### Step 6: Empty State Designs

For new users with no interests/history:
- "Tell us about your research interests" card → links to profile interests editor
- "Explore trending research" → shows general trending
- "Join a community" → shows top 3 communities by member count

---

## Updated Execution Order (Next Work)

1. **Sprint 1 (MVP backend + template split)**
   - Implement Step 1 + Step 2 (server-side only)
   - Keep one logged-in dashboard page without AJAX first
   - Ship with existing homepage cards/components and minimal UI churn

2. **Sprint 2 (performance + async sections)**
   - Implement Step 3 + Step 4
   - Add per-section cache keys and lightweight JSON endpoints

3. **Sprint 3 (engagement refinements)**
   - Implement Step 5 + Step 6
   - Add “Continue Reading” and polished empty states for new users

4. **Measurement gate**
   - Compare session duration, homepage CTR, and return frequency before/after launch

---

## Verification

1. Log in as test user with interests + read history → verify all 5 sections appear
2. Log in as fresh user (no history) → verify empty states render correctly
3. Check page load time: initial SSR < 500ms, AJAX sections < 200ms each
4. Verify cache invalidation: add new favorite → "Saved Papers" section updates within 1 request
5. Compare session duration before/after via analytics

---

## Decisions

- **Dashboard for logged-in only**: Anonymous users keep the current trending homepage (it works well for SEO)
- **AJAX sections**: Keeps Time to First Byte fast while loading personalized content progressively
- **No infinite scroll**: Sections are curated, not a feed. Each links to the full page for deeper browsing.
