Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Homepage Recommendation System Design Plan

Date: 2026-04-24 Project: hh-lion Related projects:

  • hh-felidae: homepage section management / Tiger GraphQL layer
  • hh-pegasus: frontend homepage rendering

1. Purpose

This plan defines the recommended direction for integrating hh-lion recommendations into the Hungry Hub homepage.

The goal is not only to produce personalized-looking recommendations, but to improve business outcomes:

  • Sales
  • Revenue
  • Leads
  • Conversion rate
  • Booking rate
  • User engagement
  • Repeat usage

The key recommendation is:

Keep hh-felidae as the source of truth for homepage structure and editorial control. Use hh-lion as a recommendation decision layer that optimizes eligible sections and items within explicit business/editorial constraints.

Do not start by letting hh-lion fully generate or replace the entire homepage.

2. Current diagnosis

2.1 What is promising

hh-lion already has a useful recommendation-platform foundation:

  • Multi-source retrieval
  • Two-tower / FAISS personalized retrieval
  • Cohort fallback
  • Session retrieval
  • New item retrieval
  • Search intent retrieval
  • RRF candidate merging
  • CatBoost reranking
  • Feature store and ClickHouse integration
  • Redis online cache/session support
  • MLflow model lifecycle
  • GrowthBook experiment hooks
  • Fallback handling
  • Diagnostics and observability work

This is a good foundation for production recommendations.

2.2 Main problem

The current homepage recommendation strategy is not yet aligned with the real homepage architecture.

hh-lion currently behaves like it can generate homepage sections itself. But the actual homepage is already managed by hh-felidae and rendered by hh-pegasus according to existing section configuration, slugs, templates, device flags, and editorial ordering.

This creates a system boundary mismatch.

The better model is:

  • hh-felidae owns homepage configuration and editorial constraints.
  • hh-lion makes recommendation decisions for eligible sections.
  • hh-pegasus renders using the existing section/component structure.

2.3 Fundamental risks to fix

  1. Hardcoded generated sections in hh-lion do not match real homepage sections.
  2. Current section creation slices one ranked restaurant list into multiple named sections, which makes section labels weak or misleading.
  3. The system is mostly restaurant-focused, while the homepage includes restaurant, tag, and link sections.
  4. Member personalization can degrade too easily into cohort fallback.
  5. Offline retrieval metrics are not enough to prove revenue or conversion lift.
  6. Item-level visible impression tracking is not sufficient yet for reliable ranking and A/B testing.
  7. Pegasus already has some client-side personalization behavior that may conflict with hh-lion server-side ranking.

3.1 Ownership model

hh-felidae should own:

  • Which sections exist
  • Section title
  • Section type
  • Section template
  • Section active/inactive state
  • Device-specific visibility
  • Editorial ordering
  • Pinned editorial sections
  • Replacement permissions
  • Section-level recommendation settings

hh-lion should own:

  • Recommendation eligibility decision
  • Candidate retrieval
  • Item ranking
  • Section scoring for eligible movable sections
  • Fallback recommendation decisions
  • Recommendation metadata and diagnostics
  • Model/ranker versioning

hh-pegasus should own:

  • Rendering the homepage
  • Component selection by section type/template/slug
  • Client-side impression/click/visibility tracking
  • Avoiding duplicate personalization when hh-lion already served a section

4.1 MVP strategy

Start with existing homepage sections only.

Do not generate arbitrary AI sections yet.

Recommended MVP scope:

  1. Keep hh-felidae as source of truth.
  2. Add recommendation configuration to existing homepage sections.
  3. Let hh-lion rerank or replace items only for eligible sections.
  4. Start with restaurant sections only.
  5. Start with the Recommended For You section first.
  6. Keep editorial/pinned sections fixed.
  7. Add complete tracking and A/B testing before expanding.

4.2 Strategy evaluation

Option 1: Rerank existing homepage sections only

Recommended as the safest first step.

Pros:

  • Low integration risk
  • Keeps editorial control
  • Easier to A/B test
  • Minimal frontend disruption

Cons:

  • Does not fully deliver Netflix-like personalization
  • Limited by existing sections

Use this for early MVP validation.

Option 2: Rerank existing sections and their items

Recommended as the main near-term target.

Pros:

  • Meaningful personalization
  • Still preserves editorial structure
  • Better business upside than section-only reordering

Cons:

  • Requires reliable item-level tracking
  • Requires section policy configuration

This should be the primary implementation path.

Option 3: Add completely new AI-generated/personalized sections

Do not do this in MVP.

Only consider after:

  • Existing section optimization has proven business lift
  • Tracking is reliable
  • Editorial approval workflow exists
  • Frontend supports generic recommended section rendering
  • Section titles/templates/localization are safe

Option 4: Add a toggle/config to replace existing sections

Recommended after basic reranking works.

Add section-level controls such as:

  • personalization_policy = manual | recommendation_rank_items | recommendation_selected_items
  • fallback_section_id
  • min_editorial_items
  • max_ai_items
  • experiment_key

Option 5: Keep editorial control while recommendations optimize placement/content

Recommended as the long-term operating model.

Editorial controls the canvas. Recommendations optimize within allowed boundaries.

5. Required hh-felidae changes

Add recommendation settings to homepage section configuration.

Suggested fields:

  • personalization_policy: manual | recommendation_rank_items | recommendation_selected_items
  • pinned: boolean
  • section_reordering_allowed: boolean
  • allowed_candidate_sources: string[]
  • fallback_mode: editorial | cohort | global | empty
  • min_items: number
  • max_items: number
  • metric_goal: booking | revenue | engagement | navigation | campaign
  • candidate_scope: open | section
  • editorial_priority: number
  • experiment_key: string | null
  • recommendation_surface: homepage

These fields can live either on the homepage_sections join table or a related recommendation_config table.

6. Required hh-lion API contract

hh-lion should accept existing sections as input instead of inventing the homepage layout from scratch.

6.1 Proposed request

POST /v2/homepage/decide

Request fields:

{
  "request_id": "string",
  "anonymous_id": "string",
  "user_id": "string | null",
  "session_id": "string",
  "context": {
    "city_id": 1,
    "country_code": "TH",
    "geo": "TH-1",
    "language": "en",
    "device_type": "mobile",
    "platform": "web",
    "referrer_category": "direct",
    "time_of_day": "evening"
  },
  "sections": [
    {
      "section_id": "string",
      "section_slug": "recommended-for-you",
      "section_type": "restaurant_list",
      "item_type": "restaurant",
      "title": "Recommended For You",
      "template": "string",
      "position": 1,
      "active": true,
      "pinned": false,
      "personalization_policy": "recommendation_selected_items",
      "section_reordering_allowed": false,
      "allowed_candidate_sources": ["model", "session", "cohort"],
      "min_items": 6,
      "max_items": 15,
      "metric_goal": "booking",
      "candidate_scope": "section",
      "candidate_item_ids": ["restaurant_id_1", "restaurant_id_2"]
    }
  ]
}

Candidate scope controls whether Lion may augment the caller-provided candidate pool:

  • open or omitted: candidate_item_ids seed the pool, and Lion may augment selected-items sections from session, cohort, or global sources.
  • section: candidate_item_ids are the closed section-scoped pool. Lion ranks or chooses only from those IDs and must not introduce candidates from other sources.

6.2 Proposed response

{
  "request_id": "string",
  "fallback_triggered": false,
  "experiment_assignments": [
    {
      "flag_key": "homepage_recommendation_mvp",
      "variant": "treatment",
      "assignment_timestamp": 1760000000000
    }
  ],
  "section_decisions": [
    {
      "section_id": "string",
      "action": "replace_items",
      "final_position": 1,
      "strategy": "personalized",
      "model_version": "homepage_two_tower@production",
      "ranker_version": "catboost_v1",
      "fallback_reason": null,
      "items": [
        {
          "item_id": "restaurant_id_1",
          "item_type": "restaurant",
          "position": 1,
          "score": 0.93,
          "source_type": "entity_embedding"
        }
      ],
      "diagnostics": {
        "eligibility_mode": "full_personalized",
        "candidate_pool_counts": {
          "model": 50,
          "session": 10,
          "cohort": 30
        },
        "reranker": "catboost"
      }
    }
  ]
}

7. Required hh-pegasus changes

7.1 Avoid duplicate personalization

Pegasus currently has client-side personalization behavior for restaurant sliders. If hh-lion already served a section, Pegasus should not personalize the same section again.

Add a field or prop such as:

  • personalizationSource: editorial | pegasus_client | lion_server
  • disableClientPersonalization: boolean

If personalizationSource = lion_server, skip client-side getPersonalizedRestaurants for that section.

7.2 Preserve existing rendering

For MVP, keep HomeBody.astro and existing section components mostly unchanged.

The GraphQL response should still look like the existing homepage response, but sections should include hydrated recommended items and tracking metadata.

7.3 Add tracking

Pegasus should emit:

  • homepage_layout_rendered
  • section_rendered
  • section_visible
  • item_visible
  • item_click
  • carousel_scroll
  • see_more_click
  • fallback_rendered

Each event should include:

  • request_id
  • anonymous_id
  • user_id if available
  • session_id
  • section_id
  • section_slug
  • section_type
  • section_position
  • item_id
  • item_type
  • item_position
  • strategy_id
  • model_version
  • experiment variant

8. Recommendation strategy design

8.1 Do not slice one ranked list into many named sections

Current hardcoded section generation in hh-lion is risky because one generic ranked list is split into sections like:

  • Recommended For You
  • Trending Near You
  • Top Rated
  • New Arrivals
  • Based on Your Taste
  • Special Deals

This is not semantically correct.

Each section should have its own candidate pool and ranking policy.

Examples:

  • Recommended For You: model/session/cohort blend optimized for booking
  • Trending Near You: city/time/popularity with availability constraints
  • New Arrivals: new restaurant pool with exploration budget
  • Deals: discount/value/campaign-aware ranking
  • Based on Your Taste: cuisine/location/price affinity
  • Recently Viewed: session/history-based retrieval

8.2 Guest strategy

Guest personalization should be framed as contextual/session personalization, not deep member personalization.

Use:

  • city
  • country
  • language
  • device
  • referrer
  • time/day
  • geolocation if available
  • current search intent
  • recent viewed restaurants/tags
  • session clicks

Guest fallback:

  1. active session intent
  2. city/language cohort
  3. trending/popular available restaurants
  4. static fallback

8.3 Member strategy

Avoid binary full-personalized vs cohort fallback.

Use member tiers:

  1. New logged-in member with no history
  2. Light-history member
  3. Warm member with interactions
  4. High-confidence member with bookings

Fallback ladder:

  1. full personalized
  2. personalized-lite from recent history
  3. session-personalized
  4. cohort backfill
  5. global/static fallback

8.4 Ranking objective

Do not optimize only for click-through rate or offline NDCG.

Recommended target is expected business value:

  • P(click | visible impression)
  • P(package_selected | click)
  • P(begin_checkout | package_selected)
  • P(booking_confirmed | checkout)
  • expected booking value
  • availability likelihood
  • margin/commission if available
  • cancellation/no-show risk if available
  • user fatigue penalty
  • diversity/freshness constraints

9. Required tracking and analytics

9.1 Item-level exposure tracking

Do not treat returned items as viewed impressions.

Track separately:

  • item_returned
  • item_rendered
  • item_visible
  • item_clicked

Carousel items that are never visible should not be treated as true negative impressions.

9.2 Required funnel events

Required canonical events:

  • impression
  • item_visible
  • click
  • view
  • favorite_added
  • package_selected
  • begin_checkout
  • booking_confirmed
  • search

9.3 Required attribution fields

Every event should include:

  • event_id
  • timestamp
  • request_id
  • anonymous_id
  • user_id
  • session_id
  • surface
  • city_id
  • country_code
  • language
  • device_type
  • platform
  • referrer_category
  • section_id
  • section_slug
  • section_type
  • section_position
  • item_id
  • item_type
  • item_position
  • strategy_id
  • model_version
  • ranker_version
  • experiment_id
  • variant
  • fallback_reason
  • price_shown
  • currency
  • package_id
  • booking_value where applicable

10. Metrics

10.1 Primary business metrics

  • Booking conversion rate per homepage session
  • Revenue per homepage session
  • Gross booking value per homepage session
  • Booking rate from homepage-exposed restaurants
  • Package selected rate
  • Checkout start rate
  • Lead rate if applicable
  • Repeat booking rate

10.2 Secondary product metrics

  • Homepage CTR
  • Section CTR
  • Item visible CTR
  • Restaurant detail view rate
  • Search usage after homepage
  • Bounce rate
  • Session depth
  • Time to first meaningful click
  • Return usage

10.3 Guardrail metrics

  • Homepage latency p95/p99
  • Recommendation API latency p95/p99
  • Empty section rate
  • Fallback rate
  • Duplicate item rate
  • Unavailable/sold-out item exposure
  • Editorial campaign delivery
  • Exposure concentration / Gini
  • Core Web Vitals
  • Bounce rate
  • Average order value

11. A/B testing plan

Phase 0: A/A instrumentation test

Goal: Validate event quality and experiment assignment.

Check:

  • Assignment balance
  • Event loss
  • request_id propagation
  • impression -> click -> booking attribution
  • no unexpected UI differences

Control: Existing Recommended For You behavior or current fallback.

Treatment: hh-lion ranking for Recommended For You.

Primary metrics:

  • Booking rate per homepage session
  • Revenue per homepage session

Guardrails:

  • latency
  • empty section rate
  • fallback rate
  • bounce rate

Analyze separately:

  • guests
  • logged-in members
  • mobile
  • desktop
  • city
  • new vs returning users

Phase 2: Existing restaurant section item reranking

Control: Editorial/group landing item order.

Treatment: hh-lion reranks items inside eligible restaurant sections.

Do not reorder sections yet.

Phase 3: Bounded section ordering

Control: Editorial section order.

Treatment: Reorder only non-pinned sections within an allowed zone.

Do not move:

  • fixed editorial sections unless allowed
  • trust/SEO/footer sections
  • hero/search
  • manually pinned campaigns

Phase 4: Section replacement

Treatment: Allow selected sections with personalization_policy = recommendation_selected_items to use fully recommended item sets.

Phase 5: AI-generated sections

Only after previous phases show reliable lift and safe operations.

12. Implementation phases

Phase 1: Contract and tracking foundation

Priority: P0

Tasks:

  1. Define shared homepage recommendation contract.
  2. Add item-visible and section-visible events.
  3. Add request_id/strategy_id propagation.
  4. Add experiment assignment propagation.
  5. Fix ranker training event-name mismatch.
  6. Add dashboards for funnel and guardrails.

Exit criteria:

  • A/A test passes.
  • Item-level attribution is reliable.
  • Booking/revenue attribution works from homepage exposure.

Priority: P0/P1

Tasks:

  1. Add hh-felidae config for Recommended For You personalization.
  2. Add hh-lion endpoint for section item decisions.
  3. Let Tiger/felidae hydrate hh-lion item IDs into restaurant objects.
  4. Disable Pegasus client-side personalization for Lion-served section.
  5. Run A/B test.

Exit criteria:

  • No latency or fallback regression.
  • Business metric lift or clear learning.
  • Diagnostics explain guest/member behavior.

Phase 3: Restaurant section reranking

Priority: P1

Tasks:

  1. Enable rerank_items mode for selected restaurant sections.
  2. Respect candidate_item_ids from editorial/group landing sections.
  3. Apply business filters and dedupe.
  4. Run section-level A/B tests.

Exit criteria:

  • Lift on eligible sections.
  • No editorial/campaign regression.

Phase 4: Controlled section ordering

Priority: P2

Tasks:

  1. Add section_ordering_mode.
  2. Define pinned and movable zones.
  3. Score sections by expected value and confidence.
  4. A/B test bounded reordering.

Exit criteria:

  • Homepage business metrics improve.
  • Guardrails stay healthy.

Priority: P2

Tasks:

  1. Build separate tag/link candidate and ranking logic.
  2. Add tag/link-specific metrics.
  3. Integrate with existing tag/link section components.

Exit criteria:

  • Tag/link personalization improves navigation or conversion path.

Phase 6: AI-generated sections

Priority: P3

Tasks:

  1. Add editorial approval workflow.
  2. Add generated section templates.
  3. Add localization and title controls.
  4. Add strict fallback and moderation.
  5. A/B test in low-risk zones.

Exit criteria:

  • Clear incremental lift over controlled section optimization.

13. Concrete P0 action items

  1. Write and approve cross-system recommendation contract.
  2. Add recommendation config fields in hh-felidae.
  3. Add item-level visible impression tracking in hh-pegasus.
  4. Fix ranker training event-name mismatch in hh-lion.
  5. Remove or bypass hardcoded section generation for integration MVP.
  6. Add section-specific candidate/ranking policy instead of slicing one ranked list.
  7. Ensure Lion-served sections disable Pegasus client-side personalization.
  8. Define A/A and first A/B experiment in GrowthBook.
  9. Build dashboard for eligibility, fallback, model/cohort share, latency, and business funnel.
  10. Launch Recommended For You only after instrumentation is verified.

14. Final recommendation

The current hh-lion project is a good foundation, but the immediate strategy should change.

Do not invest next in making hh-lion generate a complete Netflix-style homepage independently.

Invest next in making hh-lion a reliable recommendation decision service that operates inside the existing hh-felidae homepage configuration and hh-pegasus rendering model.

The recommended path is:

  1. Track properly.
  2. Optimize Recommended For You.
  3. Rerank items inside existing restaurant sections.
  4. Reorder only eligible non-pinned sections.
  5. Add controlled replacement mode.
  6. Only later add AI-generated sections.

This approach gives the team the best chance of improving revenue and conversion without breaking editorial control, frontend integration, attribution, or operational safety.