# Unified ByteLyst Portal — Roadmap & Task List

> **Date:** 2026-03-21 · **Companion to:** [`UNIFIED_BYTELYST_PORTAL_PRD.md`](UNIFIED_BYTELYST_PORTAL_PRD.md)
> **Estimated total:** 8 phases · ~129 tasks · 6-8 weeks

---

## Phase 0: Repo Scaffold & Foundations (2 days)

> **Goal:** Repo exists, builds, deploys to dev. BFF starts and returns health check. Web renders shell.

| #    | Task                                                                                        | Type    | Est | Notes                                                     |
| ---- | ------------------------------------------------------------------------------------------- | ------- | --- | --------------------------------------------------------- |
| 0.1  | Create `learning_ai_portal` repo with standard structure                                    | infra   | 1h  | `backend/`, `web/`, `shared/`, `docs/`, `AGENTS.md`       |
| 0.2  | Create `shared/product.json` (id: `portal`, port: 4020/3010)                                | config  | 15m | Follow existing product.json pattern                      |
| 0.3  | Create `products/portal/product.json` in common-plat                                        | config  | 15m | Register portal in product registry                       |
| 0.4  | Scaffold BFF with `@bytelyst/fastify-core` (port 4020)                                      | backend | 1h  | `createServiceApp()` + health endpoint                    |
| 0.5  | Add `lib/config.ts` -- Zod-validated env (JWT_SECRET, PLATFORM_URL, product backend URLs)   | backend | 30m |                                                           |
| 0.6  | Add `lib/product-config.ts` -- load from `shared/product.json`                              | backend | 15m |                                                           |
| 0.7  | Add `lib/auth.ts` -- JWT extraction + portal scope validation                               | backend | 30m |                                                           |
| 0.8  | Add `lib/request-context.ts` -- `getUserId(req)`, `getUserMemberships(req)`                 | backend | 30m |                                                           |
| 0.9  | Add `lib/product-registry.ts` -- load all product.json files, build registry                | backend | 1h  | Read from `../../products/*/product.json` or env-injected |
| 0.10 | Add `lib/product-client.ts` -- service-to-service HTTP client for product backends          | backend | 1h  | Timeout, circuit breaker, x-user-id header                |
| 0.11 | Add `lib/errors.ts` -- re-export from `@bytelyst/errors`                                    | backend | 10m | Standard pattern across all product backends              |
| 0.12 | Add `lib/datastore.ts` -- `@bytelyst/datastore` provider (Cosmos or memory via DB_PROVIDER) | backend | 30m | Required for widget layout persistence                    |
| 0.13 | Add `lib/cosmos-init.ts` -- register `portal_widget_layouts` container on startup           | backend | 30m | Partition: `/userId`                                      |
| 0.14 | Add `vitest.config.ts` + `test-helpers.ts` -- Vitest config + `buildTestApp()` helper       | backend | 30m | Standard test scaffold                                    |
| 0.15 | Scaffold web with Next.js 16 + `@bytelyst/dashboard-shell` (port 3010)                      | web     | 1h  | App Router, TailwindCSS v4, `--portal-*` CSS props        |
| 0.16 | Add `web/src/lib/product-config.ts` -- product identity + API URLs                          | web     | 15m |                                                           |
| 0.17 | Add `web/src/lib/auth.ts` -- `@bytelyst/react-auth` provider                                | web     | 30m | Cookie-based auth                                         |
| 0.18 | Add `web/src/lib/api.ts` -- typed fetch client for BFF                                      | web     | 30m |                                                           |
| 0.19 | Add `web/src/app/layout.tsx` + `providers.tsx` -- shell + auth + telemetry                  | web     | 30m |                                                           |
| 0.20 | Create `AGENTS.md` with project conventions                                                 | docs    | 30m |                                                           |
| 0.21 | Create `.github/workflows/ci.yml` -- typecheck + test for backend + web                     | infra   | 30m |                                                           |
| 0.22 | Verify: `cd backend && npm test && npm run typecheck` passes                                | test    | 15m |                                                           |
| 0.23 | Verify: `cd web && npm run typecheck && npm run build` passes                               | test    | 15m |                                                           |

**Phase 0 deliverable:** Repo builds, BFF returns `GET /health`, web renders empty shell with sidebar. (23 tasks)

---

## Phase 1: Product Launcher & Auth (3 days)

> **Goal:** User can log in, see all their products, and launch any product dashboard.

| #    | Task                                                                                                                          | Type    | Est | Notes                                                                                |
| ---- | ----------------------------------------------------------------------------------------------------------------------------- | ------- | --- | ------------------------------------------------------------------------------------ |
| 1.1  | BFF: `GET /api/portal/products` -- fetch user memberships from platform-service `/auth/me`, enrich with product.json metadata | backend | 2h  | Returns `{ products: [{ id, name, icon, plan, role, dashboardUrl, lastActiveAt }] }` |
| 1.2  | BFF: `POST /api/portal/products/:id/switch` -- re-issue JWT with new active productId                                         | backend | 1h  |                                                                                      |
| 1.3  | BFF: service-to-service auth setup -- API key registration for portal-to-product-backend calls                                | backend | 2h  | Register `portal` as a service consumer in platform-service                          |
| 1.4  | Web: `/login` page -- email/password + OAuth buttons via `@bytelyst/react-auth`                                               | web     | 2h  | Redirect to `/` on success                                                           |
| 1.5  | Web: `(app)/layout.tsx` -- authenticated route group with `DashboardShell`                                                    | web     | 1h  | Sidebar nav: Home, Products, Activity, Search, Billing, Settings, Security           |
| 1.6  | Web: `Sidebar.tsx` -- portal sidebar with product icons + nav sections                                                        | web     | 1h  |                                                                                      |
| 1.7  | Web: `/products` page -- product launcher grid                                                                                | web     | 3h  | Card per product: icon, name, plan badge, last active, "Open" button                 |
| 1.8  | Web: `ProductCard.tsx` component -- product card with theme colors from product.json                                          | web     | 1h  |                                                                                      |
| 1.9  | Web: `/` redirect to `/products` (temporary, until dashboard is built in Phase 3)                                             | web     | 15m |                                                                                      |
| 1.10 | Web: product launch handler -- opens product dashboard in new tab with session context                                        | web     | 1h  | Deep link: `https://{domain}/?portal=true`                                           |
| 1.11 | Web: show "Get Started" CTA for products user hasn't signed up for                                                            | web     | 1h  | Links to product landing page                                                        |
| 1.12 | Test: BFF products endpoint returns correct memberships                                                                       | test    | 1h  | Vitest                                                                               |
| 1.13 | BFF: `GET /api/portal/quick-actions` -- available quick actions per product from product registrations                        | backend | 1h  | Static config in product.json + optional dynamic from backends                       |
| 1.14 | Test: Login flow to product grid to launch works E2E                                                                          | test    | 1h  | Playwright                                                                           |

**Phase 1 deliverable:** User logs in, sees grid of their products with status, can open any product in a new tab.

---

## Phase 2: Activity Feed & Notifications (3 days)

> **Goal:** User sees a chronological feed of recent actions across all products.

| #    | Task                                                                                                 | Type    | Est | Notes                                                          |
| ---- | ---------------------------------------------------------------------------------------------------- | ------- | --- | -------------------------------------------------------------- |
| 2.1  | BFF: `lib/feed-aggregator.ts` -- parallel fan-out to product backends with timeout + circuit breaker | backend | 3h  | 3s timeout per product, fail-open                              |
| 2.2  | BFF: Define `FeedEvent` schema + product-specific event mappers                                      | backend | 2h  | One mapper per product that normalizes response into FeedEvent |
| 2.3  | BFF: `GET /api/portal/feed` -- aggregated feed with pagination (`?cursor=&limit=50`)                 | backend | 2h  | Merge-sort by createdAt desc                                   |
| 2.4  | BFF: In-memory cache (60s TTL per user) for feed data                                                | backend | 1h  |                                                                |
| 2.5  | BFF: `GET /api/portal/notifications` -- aggregate from platform-service notifications                | backend | 1h  |                                                                |
| 2.6  | Web: `/activity` page -- full-page activity timeline                                                 | web     | 3h  | Filter by product, date range, event type                      |
| 2.7  | Web: `FeedCard.tsx` -- event card with product icon, title, timestamp, deep link                     | web     | 1h  |                                                                |
| 2.8  | Web: `FeedFilters.tsx` -- product multi-select, date range picker                                    | web     | 1h  |                                                                |
| 2.9  | Web: Activity feed widget on `/` home page (compact view, last 10 items)                             | web     | 1h  |                                                                |
| 2.10 | Web: Notification bell in top bar -- badge count + dropdown                                          | web     | 2h  |                                                                |
| 2.11 | Product backends: Verify each backend has a "recent items" list endpoint                             | backend | 2h  | Add missing endpoints where needed                             |
| 2.12 | Test: Feed aggregation with 3 products up, 2 down                                                    | test    | 1h  | Circuit breaker test                                           |
| 2.13 | Test: Feed pagination, sorting, filtering                                                            | test    | 1h  |                                                                |

**Phase 2 deliverable:** `/activity` page shows chronological feed from all products. Home page shows compact feed.

---

## Phase 3: Widget Dashboard (4 days)

> **Goal:** Home page is a customizable widget grid. Users can add/remove/resize widgets.

| #    | Task                                                                                                                                                              | Type    | Est | Notes                                                     |
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --- | --------------------------------------------------------- |
| 3.1  | BFF: `modules/widgets/types.ts` -- WidgetDefinition, WidgetLayout schemas                                                                                         | backend | 1h  |                                                           |
| 3.2  | BFF: `modules/widgets/repository.ts` -- CRUD for user widget layouts in Cosmos                                                                                    | backend | 2h  | Container: `portal_widget_layouts`, partition: `/userId`  |
| 3.3  | BFF: `modules/widgets/routes.ts` -- GET/PUT layout, GET widget definitions                                                                                        | backend | 2h  |                                                           |
| 3.4  | BFF: `GET /api/portal/widgets/:widgetId/data` -- fetch widget data from product backend                                                                           | backend | 2h  | Route to correct product backend based on widgetId prefix |
| 3.5  | BFF: Register 20+ widget definitions (from PRD section 5.4)                                                                                                       | backend | 2h  | Static definitions loaded at startup                      |
| 3.6  | BFF: Cosmos container registration for `portal_widget_layouts`                                                                                                    | backend | 30m |                                                           |
| 3.7  | Web: `/` home page with widget grid layout (CSS Grid)                                                                                                             | web     | 3h  | Fixed grid for v1, drag-and-drop in Phase 8               |
| 3.8  | Web: `WidgetShell.tsx` -- generic widget wrapper (header, loading, error, resize)                                                                                 | web     | 2h  |                                                           |
| 3.9  | Web: `WidgetPicker.tsx` -- modal to add widgets from catalog                                                                                                      | web     | 2h  | Grouped by product                                        |
| 3.10 | Web: Implement 5 priority widgets: ChronoMind next-timer, NomGap fast-progress, FlowMonk today-schedule, NoteLett recent-notes, Portal billing-summary            | web     | 4h  | ~45m each                                                 |
| 3.11 | Web: Implement 5 more widgets: LysnrAI recent-transcripts, MindLyst recent-captures, JarvisJr coaching-streak, ActionTrail recent-actions, PeakPulse weekly-stats | web     | 4h  |                                                           |
| 3.12 | Web: Implement remaining 11 widgets                                                                                                                               | web     | 5h  |                                                           |
| 3.13 | Web: `useWidgetData(widgetId)` hook -- fetch + cache + loading/error states                                                                                       | web     | 1h  |                                                           |
| 3.14 | Web: Default widget layout for new users (6 widgets: feed + 5 most-active products)                                                                               | web     | 1h  |                                                           |
| 3.15 | Web: Save layout changes to BFF via PUT /api/portal/widgets/layout                                                                                                | web     | 1h  | Debounced save                                            |
| 3.16 | Test: Widget CRUD, layout persistence                                                                                                                             | test    | 1h  |                                                           |
| 3.17 | Test: Widget data fetch with product backend down (graceful degradation)                                                                                          | test    | 1h  |                                                           |

**Phase 3 deliverable:** Home page has customizable widget grid. Each widget fetches live data.

---

## Phase 4: Cross-Product Search (2 days)

> **Goal:** Cmd+K opens a global search bar that searches across all products.

| #    | Task                                                                           | Type    | Est | Notes                                                                       |
| ---- | ------------------------------------------------------------------------------ | ------- | --- | --------------------------------------------------------------------------- |
| 4.1  | BFF: `lib/search-aggregator.ts` -- parallel search fan-out to product backends | backend | 2h  | Same circuit-breaker pattern as feed                                        |
| 4.2  | BFF: `GET /api/portal/search?q=...&products=...` -- cross-product search       | backend | 2h  | Returns results grouped by product                                          |
| 4.3  | BFF: Product search endpoint mapping -- which endpoint to call per product     | backend | 1h  | e.g., NoteLett: `GET /api/notes?search=`, LocalMemGPT: `GET /api/search?q=` |
| 4.4  | Web: `/search` page -- full search results grouped by product                  | web     | 3h  | Product sections, result cards with deep links                              |
| 4.5  | Web: `SearchBar.tsx` -- Cmd+K global search overlay                            | web     | 2h  | Debounced input, recent searches, keyboard nav                              |
| 4.6  | Web: `SearchResultCard.tsx` -- generic result card with product badge          | web     | 1h  |                                                                             |
| 4.7  | Web: Add `use-keyboard-shortcuts.ts` -- Cmd+K to open search                   | web     | 30m |                                                                             |
| 4.8  | Product backends: Verify search/filter endpoints exist for each product        | backend | 2h  | Add missing search endpoints                                                |
| 4.9  | Test: Search across 3 products, results merge correctly                        | test    | 1h  |                                                                             |
| 4.10 | Test: Search with one product down, others still return                        | test    | 30m |                                                                             |

**Phase 4 deliverable:** Cmd+K opens cross-product search. Results grouped by product with deep links.

---

## Phase 5: Billing & Settings (2 days)

> **Goal:** User manages billing and global preferences from the portal.

| #    | Task                                                                                             | Type    | Est | Notes                                        |
| ---- | ------------------------------------------------------------------------------------------------ | ------- | --- | -------------------------------------------- |
| 5.1  | BFF: `GET /api/portal/billing/summary` -- aggregate from platform-service subscriptions + stripe | backend | 2h  | Combined monthly cost, per-product breakdown |
| 5.2  | BFF: `GET /api/portal/billing/invoices` -- all invoices across products                          | backend | 1h  |                                              |
| 5.3  | BFF: `GET /api/portal/preferences` -- user global preferences                                    | backend | 1h  | From UserDoc.globalPreferences               |
| 5.4  | BFF: `PATCH /api/portal/preferences` -- update preferences                                       | backend | 1h  | Validate with Zod, save to platform-service  |
| 5.5  | Platform-service: Add `globalPreferences` field to UserDoc schema                                | backend | 1h  | Optional, backward-compatible                |
| 5.6  | Platform-service: Add `PATCH /auth/preferences` endpoint                                         | backend | 1h  |                                              |
| 5.7  | Web: `/billing` page -- subscription cards per product, combined total, invoice list             | web     | 3h  |                                              |
| 5.8  | Web: `/settings` page -- theme toggle, timezone picker, locale, notification prefs               | web     | 3h  |                                              |
| 5.9  | Web: Theme toggle (dark/light/system) applies to portal immediately                              | web     | 1h  |                                              |
| 5.10 | Web: Notification preferences -- email/push/in-app toggles, digest frequency                     | web     | 1h  |                                              |
| 5.11 | Test: Billing aggregation with mixed plan types                                                  | test    | 1h  |                                              |
| 5.12 | Test: Preferences save and reload correctly                                                      | test    | 1h  |                                              |

**Phase 5 deliverable:** `/billing` shows combined costs. `/settings` manages cross-product preferences.

---

## Phase 6: Security & Profile (2 days)

> **Goal:** Full SmartAuth security management from the portal.

| #    | Task                                                                                     | Type    | Est | Notes                                       |
| ---- | ---------------------------------------------------------------------------------------- | ------- | --- | ------------------------------------------- |
| 6.1  | BFF: Proxy security endpoints to platform-service (MFA, passkeys, devices, login-events) | backend | 2h  | Same catch-all proxy pattern                |
| 6.2  | Web: `/security` page -- MFA status, TOTP setup/disable, recovery codes                  | web     | 3h  | Reuse patterns from admin-web security page |
| 6.3  | Web: `/security` -- passkey management (register, list, remove)                          | web     | 2h  | WebAuthn browser API integration            |
| 6.4  | Web: `/security` -- device list with trust levels, session revocation                    | web     | 2h  |                                             |
| 6.5  | Web: `/security` -- login history timeline                                               | web     | 1h  |                                             |
| 6.6  | Web: `/profile` page -- name, email, avatar, connected OAuth accounts                    | web     | 2h  |                                             |
| 6.7  | Web: Connected accounts section -- link/unlink Google, Microsoft, Apple                  | web     | 2h  |                                             |
| 6.8  | Web: `/support` page -- create/track support tickets via platform-service support-cases  | web     | 2h  |                                             |
| 6.9  | Test: MFA setup flow E2E                                                                 | test    | 1h  |                                             |
| 6.10 | Test: Device revocation works from portal                                                | test    | 30m |                                             |

**Phase 6 deliverable:** Full security management. Profile with OAuth link/unlink. Support ticket creation.

---

## Phase 7: Telemetry, Polish & Launch (3 days)

> **Goal:** Production-ready portal with telemetry, error handling, and polished UI.

| #    | Task                                                                                            | Type    | Est | Notes |
| ---- | ----------------------------------------------------------------------------------------------- | ------- | --- | ----- |
| 7.1  | BFF: Telemetry event buffer -- portal-specific events (product_launched, search_executed, etc.) | backend | 1h  |       |
| 7.2  | BFF: Feature flags integration -- `@bytelyst/feature-flag-client`                               | backend | 30m |       |
| 7.3  | BFF: Kill switch integration -- `@bytelyst/kill-switch-client`                                  | backend | 30m |       |
| 7.4  | BFF: Rate limiting on search and feed endpoints                                                 | backend | 1h  |       |
| 7.5  | BFF: Request logging with structured context                                                    | backend | 30m |       |
| 7.6  | Web: Telemetry client -- track portal events via `@bytelyst/telemetry-client`                   | web     | 1h  |       |
| 7.7  | Web: Error boundaries -- per-widget and per-page                                                | web     | 1h  |       |
| 7.8  | Web: Loading skeletons for all pages                                                            | web     | 2h  |       |
| 7.9  | Web: Empty states for zero-product users (onboarding CTA)                                       | web     | 1h  |       |
| 7.10 | Web: Responsive design -- mobile-friendly sidebar collapse                                      | web     | 2h  |       |
| 7.11 | Web: PWA manifest + service worker for offline shell                                            | web     | 1h  |       |
| 7.12 | Web: `--portal-*` design tokens from `@bytelyst/design-tokens`                                  | web     | 1h  |       |
| 7.13 | Web: Keyboard shortcuts -- Cmd+K (search), Cmd+1-9 (product launch)                             | web     | 1h  |       |
| 7.14 | Docs: Update `AGENTS.md` with final architecture                                                | docs    | 1h  |       |
| 7.15 | Docs: Write `README.md` with setup instructions                                                 | docs    | 30m |       |
| 7.16 | Docker: `Dockerfile` for BFF + web                                                              | infra   | 1h  |       |
| 7.17 | Docker: Add to `docker-compose.yml` in common-plat                                              | infra   | 30m |       |
| 7.18 | CI: Playwright E2E test suite (10 core flows)                                                   | test    | 3h  |       |
| 7.19 | CI: Add portal to `run-local-all-services.sh` (in learning_voice_ai_agent repo)                 | infra   | 15m |       |
| 7.20 | Final: Typecheck + test + build green across BFF + web                                          | test    | 1h  |       |

**Phase 7 deliverable:** Production-ready portal. All tests pass. Docker-deployable. Telemetry wired.

---

## Phase 8: Post-Launch Enhancements (Ongoing)

> **Goal:** Iterative improvements based on usage data.

| #    | Task                                                          | Type    | Est | Notes                                               |
| ---- | ------------------------------------------------------------- | ------- | --- | --------------------------------------------------- |
| 8.1  | Drag-and-drop widget reordering (react-dnd or dnd-kit)        | web     | 3h  |                                                     |
| 8.2  | Embedded product views (iframe) with postMessage auth         | web     | 4h  | v2 of product launcher                              |
| 8.3  | SSE-based real-time feed updates                              | backend | 3h  | `@bytelyst/fastify-sse`                             |
| 8.4  | Cross-product quick actions (e.g., "Start Timer" from portal) | web+bff | 4h  | Product backends expose action endpoints            |
| 8.5  | Mobile-responsive PWA optimization                            | web     | 2h  |                                                     |
| 8.6  | Admin analytics -- portal engagement metrics in admin-web     | web     | 3h  | Cross-product adoption charts                       |
| 8.7  | Smart widget suggestions based on user activity patterns      | backend | 2h  | "You use ChronoMind daily -- add the timer widget?" |
| 8.8  | Unified notification center with mark-read, filters           | web     | 3h  |                                                     |
| 8.9  | Product health badges -- show backend status in product cards | bff     | 1h  | Poll health endpoints                               |
| 8.10 | Custom widget themes -- user sets accent color per widget     | web     | 1h  |                                                     |

---

## Summary

| Phase | Name                            | Duration     | Tasks   | Key Deliverable                     |
| ----- | ------------------------------- | ------------ | ------- | ----------------------------------- |
| **0** | Repo Scaffold and Foundations   | 2 days       | 23      | Repo builds, shell renders          |
| **1** | Product Launcher and Auth       | 3 days       | 14      | Login, product grid, launch         |
| **2** | Activity Feed and Notifications | 3 days       | 13      | Cross-product activity timeline     |
| **3** | Widget Dashboard                | 4 days       | 17      | Customizable widget grid            |
| **4** | Cross-Product Search            | 2 days       | 10      | Cmd+K global search                 |
| **5** | Billing and Settings            | 2 days       | 12      | Combined billing + global prefs     |
| **6** | Security and Profile            | 2 days       | 10      | Full SmartAuth security from portal |
| **7** | Polish and Launch               | 3 days       | 20      | Production-ready, Docker, E2E       |
| **8** | Post-Launch                     | Ongoing      | 10      | Drag-drop, SSE, quick actions       |
|       | **Total**                       | **~21 days** | **129** |                                     |

---

## Dependency Graph

```
Phase 0 (scaffold)
  |
  v
Phase 1 (auth + products)
  |
  +---> Phase 2 (feed) ---> Phase 3 (widgets)
  |
  +---> Phase 4 (search)
  |
  +---> Phase 5 (billing + settings)
  |
  +---> Phase 6 (security + profile)
  |
  v
Phase 7 (polish + launch)  <-- all above complete
  |
  v
Phase 8 (post-launch enhancements)
```

**Critical path:** Phase 0 -> Phase 1 -> Phase 2 -> Phase 3 -> Phase 7

Phases 4, 5, 6 can be parallelized after Phase 1.

---

_This roadmap should be reviewed after each phase. Estimates are in ideal developer-hours._
