Implement live AI-generated content and real-time stats on home route#3
Implement live AI-generated content and real-time stats on home route#3
Conversation
Co-authored-by: vishnu-madhavan-git <237662584+vishnu-madhavan-git@users.noreply.github.com>
Co-authored-by: vishnu-madhavan-git <237662584+vishnu-madhavan-git@users.noreply.github.com>
Co-authored-by: vishnu-madhavan-git <237662584+vishnu-madhavan-git@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR implements AI-generated content and live statistics on the home route, replacing static placeholder content with dynamic data fetched from Google's Gemini API. The implementation adds a new service method, UI components, and state management to display real-time product metrics and AI-generated hero content.
Changes:
- Added
fetchHomeContent()method to Gemini service for AI-generated hero section and features - Implemented
LiveStatsBarcomponent displaying 6 metrics (3 dynamic product-based, 3 static) - Enhanced home view with conditional rendering for AI content with fallback to static slides
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 11 comments.
| File | Description |
|---|---|
| types.ts | Adds HomeContent interface for structured AI response data with hero, stats, and features fields |
| services/geminiService.ts | Implements fetchHomeContent() method with JSON parsing and fallback error handling |
| App.tsx | Adds state management for home content and live stats, new LiveStatsBar component, and conditional rendering in hero section |
| LIVE_DATA_IMPLEMENTATION.md | Comprehensive documentation covering implementation details, configuration, and troubleshooting |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const jsonText = response.text.replace(/```json\n?|\n?```/g, '').trim(); | ||
| return JSON.parse(jsonText); |
There was a problem hiding this comment.
The JSON parsing approach is fragile and may fail for valid JSON responses. The regex pattern /```json\n?|\n?```/g only handles markdown code blocks with 'json' syntax highlighting, but the AI might return JSON without markdown formatting or with different formatting. Consider a more robust approach that handles various response formats, or better yet, configure the AI to use structured output mode if available in the API.
There was a problem hiding this comment.
Improved JSON parsing to handle various response formats. Now tries multiple strategies: removes markdown code blocks with different patterns, extracts JSON using regex, and validates structure before use. Commit 29fabcd
| return ( | ||
| <div key={idx} className="glass-panel p-8 rounded-2xl border border-black/5 dark:border-white/5 hover:border-nexlyn/30 transition-all space-y-4"> | ||
| <div className="w-12 h-12 rounded-xl bg-nexlyn/10 flex items-center justify-center"> | ||
| {IconComponent ? <IconComponent className="w-6 h-6 text-nexlyn" /> : null} |
There was a problem hiding this comment.
The icon mapping could fail silently if the AI returns an icon name that doesn't exist in the ICONS object. When ICONS[feature.icon as keyof typeof ICONS] is undefined, the component renders nothing in the icon container. Consider adding a fallback icon or validation to ensure a consistent UI even when the AI returns unexpected icon names.
| {IconComponent ? <IconComponent className="w-6 h-6 text-nexlyn" /> : null} | |
| {IconComponent ? ( | |
| <IconComponent className="w-6 h-6 text-nexlyn" /> | |
| ) : ( | |
| <span className="w-6 h-6 flex items-center justify-center text-nexlyn text-lg font-bold"> | |
| ? | |
| </span> | |
| )} |
There was a problem hiding this comment.
Added Shield icon as fallback when AI returns unknown icon names. This ensures a consistent UI even with unexpected icon values. Commit 29fabcd
| const content = await gemini.fetchHomeContent(); | ||
| setHomeContent(content); | ||
| } catch (err) { | ||
| console.error('Failed to fetch AI-generated home content, using fallback:', err); |
There was a problem hiding this comment.
The error message in the console log references 'AI-generated home content' but the actual error from the API call is more specific. The message should be updated to reflect that it's specifically a Gemini API failure for consistency with other error messages in the codebase.
| console.error('Failed to fetch AI-generated home content, using fallback:', err); | |
| console.error('Failed to fetch home content from Gemini API, using fallback:', err); |
There was a problem hiding this comment.
Updated error message to specifically reference "Gemini API" for consistency with other error messages. Commit 29fabcd
|
|
||
| Required in `.env.local`: | ||
| ```bash | ||
| GEMINI_API_KEY=your_api_key_here |
There was a problem hiding this comment.
The documentation references environment variable 'GEMINI_API_KEY' but the actual code uses 'API_KEY' (line 42 of geminiService.ts). This inconsistency could confuse developers trying to configure the application. The documentation should match the actual implementation or vice versa.
| GEMINI_API_KEY=your_api_key_here | |
| API_KEY=your_api_key_here |
There was a problem hiding this comment.
Fixed documentation to use API_KEY instead of GEMINI_API_KEY to match the actual implementation in vite.config.ts. Added clarifying note. Commit 29fabcd
| stats: { | ||
| label: string; | ||
| value: string; | ||
| icon: string; | ||
| }[]; |
There was a problem hiding this comment.
The 'stats' field in the HomeContent interface is defined but never used in the UI rendering. The LiveStatsBar component uses the local liveStats state instead. Either remove the unused 'stats' field from the interface and API response, or utilize the AI-generated stats in the UI to avoid requesting unnecessary data from the API.
| stats: { | |
| label: string; | |
| value: string; | |
| icon: string; | |
| }[]; |
There was a problem hiding this comment.
Removed unused stats field from HomeContent interface. The LiveStatsBar uses local product calculations instead of AI-generated stats. Commit 29fabcd
| // Fetch home content on mount | ||
| useEffect(() => { | ||
| const fetchHomeData = async () => { | ||
| try { | ||
| const content = await gemini.fetchHomeContent(); | ||
| setHomeContent(content); | ||
| } catch (err) { | ||
| console.error('Failed to fetch AI-generated home content, using fallback:', err); | ||
| } | ||
| }; | ||
|
|
||
| fetchHomeData(); | ||
| }, []); |
There was a problem hiding this comment.
The AI-generated content is fetched on every page load without any caching mechanism. This results in unnecessary API calls and costs. Consider implementing a caching strategy (e.g., localStorage with TTL, or state management with a refresh mechanism) to avoid redundant API calls when the user navigates between pages or refreshes.
There was a problem hiding this comment.
Implemented localStorage caching with 24-hour TTL. AI content is now cached and only refetched when cache expires or is invalid, preventing unnecessary API calls. Commit 29fabcd
| const jsonText = response.text.replace(/```json\n?|\n?```/g, '').trim(); | ||
| return JSON.parse(jsonText); |
There was a problem hiding this comment.
The JSON parsing doesn't validate the structure of the response before using it. If the AI returns a valid JSON object that doesn't match the expected HomeContent interface (missing fields, wrong types, etc.), the UI will fail silently or crash. Consider adding runtime validation or type guards to ensure the response matches the expected structure before setting it in state.
There was a problem hiding this comment.
Added isValidHomeContent() type guard that validates the AI response structure before using it. Falls back to default content if validation fails. Commit 29fabcd
| try { | ||
| const response = await this.ai.models.generateContent({ | ||
| model: MODELS.FAST_FLASH, | ||
| contents: [{ role: 'user', parts: [{ text: prompt }] }], |
There was a problem hiding this comment.
The API call format is inconsistent with the existing searchTech method. The searchTech method uses contents: prompt (line 49) while fetchHomeContent uses contents: [{ role: 'user', parts: [{ text: prompt }] }]. For consistency and to avoid potential API compatibility issues, both methods should use the same format for the contents parameter.
| contents: [{ role: 'user', parts: [{ text: prompt }] }], | |
| contents: prompt, |
There was a problem hiding this comment.
Changed to use contents: prompt format for consistency with the existing searchTech method. Commit 29fabcd
| import React, { useState, useEffect, useMemo } from 'react'; | ||
| import { ICONS, PRODUCTS as INITIAL_PRODUCTS, CATEGORIES, WHATSAPP_NUMBER as INITIAL_WA, ADMIN_PASSCODE, OWNER_PASSCODE, HERO_SLIDES, VISUALS } from './constants'; | ||
| import { Product, Message, GroundingSource, Category } from './types'; | ||
| import { Product, Message, GroundingSource, Category, HomeContent } from './types'; |
There was a problem hiding this comment.
Unused import GroundingSource.
| import { Product, Message, GroundingSource, Category, HomeContent } from './types'; | |
| import { Product, Message, Category, HomeContent } from './types'; |
There was a problem hiding this comment.
Removed unused GroundingSource import. Commit 29fabcd
|
@copilot give me the git code link to share the repo |
…ng, and fix docs Co-authored-by: vishnu-madhavan-git <237662584+vishnu-madhavan-git@users.noreply.github.com>
The repository URL is: https://github.com/vishnu-madhavan-git/NEXLYN---v2 |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Replaces static placeholder content with AI-generated hero content and live product statistics using the existing Gemini service infrastructure.
Changes
Gemini Service Enhancement
fetchHomeContent()method returning structured JSON for hero section and featuresCaching Implementation
Live Statistics
LiveStatsBarcomponent displays 6 metrics (3 dynamic, 3 static)useEffectHome View Updates
Type Definitions
HomeContentinterface for structured AI response data (hero and features only)Configuration
Required environment variable in
.env.local:Optional AI Studio data source integration available via
DATA_SOURCE_IDenv var anddataSourceGroundingconfig. Current implementation uses general content generation with Google Search grounding fallback.Production Features
Original prompt
Objective
Replace placeholder content on the home route with actual data fetched from the AI Studio data source using the existing Gemini service. Create live components that display real, grounded information from your data source.
Current Architecture Understanding
Existing Gemini Integration
services/geminiService.tsgemini-2.0-flash-exptools: [{ googleSearch: {} }]groundingMetadata.groundingChunksfor sourcesCurrent Home View
App.tsxaround lines 840-947HERO_SLIDESfrom constantsStep-by-Step Implementation Guide
Step 1: Create New Data Fetching Service
File:
services/geminiService.tsAdd new method to fetch specific content from your AI Studio data source:
Step 2: Create Live Product Stats Component
File:
App.tsxAdd state for live data:
Add effect to fetch live data on mount:
Step 3: Create Live Stats Display Component
File:
App.tsxAdd this component (around line 240, before the Logo component):