Skip to content

Memories Feed

An authenticated user opens the app's home screen and sees a paginated feed of their captured memory sessions, each with a thumbnail, timestamp, type label, and processing status. Segments from the same recording session are automatically grouped into a single feed item.

Flow

  1. App loads home screen — The MemoriesScreen component (main/app/app/index.tsx) calls useMemoriesFeed({ limit: 20 }) via React Query. This hook calls the memories-feed Lambda.

  2. Authentication — The Lambda requires a valid Cognito JWT (require_auth_context=True). The user_id is extracted from the auth context.

  3. Database connection — The Lambda connects to PostgreSQL using credentials from SSM Parameter Store (or DATABASE_URL in local dev) and initializes SQLAlchemy.

  4. Cursor parsing — A numeric cursor (offset) and limit (capped at 50, default 20) are parsed from the request payload.

  5. Query — All WorldMMSegment records for the authenticated user are queried, ordered by start_time DESC then id DESC.

  6. Session grouping — Segments are grouped by their source_session_id. Segments without a source_session_id are each treated as their own session (keyed by segment ID).

  7. Sorting — Sessions are sorted by their latest segment's start_time (newest first) to ensure a natural chronological ordering.

  8. Pagination — Pagination is applied at the session level: OFFSET cursor LIMIT limit+1. This ensures that each feed item corresponds to exactly one session.

  9. Session aggregation — For each session, the feed derives:

  10. id: The session ID (either source_session_id or a single segment's ID if ungrouped)
  11. time: The earliest segment's start_time (session start)
  12. type: The richest segment type in the session (priority: visual > audio > text)
  13. thumbnail: The first visual segment's presigned S3 URL (TTL 1 hour), if any
  14. processing_status: The overall session status (pending if any segment pending, failed if any segment failed, complete otherwise)

  15. Next-cursor computation — If limit+1 sessions are returned, the next cursor is cursor + limit; otherwise there are no more pages.

  16. Response — Returns { "memories": [...], "next_cursor": "<offset-string>" | null }. Each memory item contains id, time, type, featured, processing_status, and optionally thumbnail.

  17. UI rendering — The MemoryFeed component renders the list. After a session finishes recording (recordingState transitions from stopping to idle), the feed is automatically refetched to show newly ingested memories.

Entry Point

  • Lambda: main/server/api/memories/feed/app.pylambda_handler
  • HTTP method: GET /memories/feed (API Gateway, Cognito-authenticated)
  • Mobile: main/app/lib/api/memory/useMemoryApi.ts

Dependencies

  • PostgreSQL (WorldMMSegment table)
  • S3 (BUCKET_NAME) for presigned thumbnail URLs
  • Cognito JWT authorizer

Audio Type Support Gap

The feed correctly returns sessions whose type is "audio" (when no visual segment exists). However, the MemoryViewerModal (docs/docs/memory-viewer-modal.md) has no AudioPlayer component and no audio branch in its renderItem logic. Audio memories fall through to the thumbnail/placeholder path — users can see the session in the feed but cannot play back the audio. Backend infrastructure for audio playback endpoints is tracked in docs/bugs/2026-05-08-audio-metadata-endpoint-403-forbidden.md.

Key Changes from Segment-Level Feed

Previously, the feed returned one item per segment, which meant a multi-media recording session (audio + video) would appear as multiple separate feed items. Now:

  • The feed groups segments by source_session_id and returns one item per session
  • The session's type reflects the richest content (visual takes priority over audio, which takes priority over text)
  • The session's thumbnail is drawn from the first visual segment if available
  • The session's processing_status reflects the overall completion state across all segments
  • Pagination operates at the session level, not the segment level, ensuring consistent and predictable page boundaries