Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a3cd91

Browse files
bdougieclaude[bot]
andauthored
feat: add FAQ sections to project pages (#331)
* feat: add FAQ sections to project pages in insights sidebar - Create ProjectFAQ component with schema markup for better SEO - Generate 7 dynamic FAQs per project based on repository data - Include expand/collapse UI with smooth interactions - Add FAQ section to insights sidebar for both desktop and mobile - Implement proper loading states and error handling - Questions cover contributor count, activity, trends, and patterns - Updates dynamically when time range changes Addresses #270 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Brian Douglas <[email protected]> * feat: enhance FAQ with LLM service and embeddings integration - Add faq-service.ts with OpenAI-powered dynamic answers - Implement semantic question matching using MiniLM embeddings - Enhanced project-faq.tsx with AI indicators and confidence scores - Add FAQ sitemap generator for improved SEO - Include FAQ URLs in main sitemap for major repositories - Support graceful fallback to static answers when AI unavailable - Add structured data and citations for better search visibility Co-authored-by: Brian Douglas <[email protected]> * docs: add FAQ LLM integration documentation * fix: resolve TypeScript errors and Rollup build issue - Fix TypeScript errors in project-faq.tsx: - Remove unused imports (cn, FAQAnswer type) - Fix RepoStats type usage (removed non-existent health/activity properties) - Properly handle pr.author object structure for contributor indexing - Remove unsupported title prop from Sparkles icon - Fix TypeScript errors in faq-service.ts: - Remove unused imports and variables - Fix type casting for cache service - Handle contributor data structure properly in reduce operations - Fix sort function type assertions - Work around Rollup conditional expression bug: - Temporarily disable treeshaking to fix build error - Added TODO to re-enable once Rollup issue is resolved - Reference: rollup/rollup#5747 Build now completes successfully with all TypeScript errors resolved. * fix: resolve Rollup conditional expression bug and refactor nested ternaries Root cause: Rollup 4.45.0 has a bug with nested ternary operators during treeshaking that causes 'Cannot add property 0, object is not extensible' error. Changes: - Simplified complex nested ternary in env.ts to avoid triggering bug - Refactored nested ternaries in project-faq.tsx to if-else statements - Disabled treeshaking as temporary workaround for remaining nested ternaries - Added detailed comments explaining the Rollup bug and workaround Impact: - Build now completes successfully - Bundle size increased to ~5.5MB (exceeds 5MB budget) due to disabled treeshaking - Performance Budget Check will fail until treeshaking is re-enabled Next steps: - Upgrade Rollup when fix is released - Or refactor all remaining nested ternaries across codebase - Then re-enable treeshaking to reduce bundle size References: rollup/rollup#5747 * refactor: replace nested ternaries with lookup objects and helper functions Refactored nested ternary operators to use cleaner patterns: - web-vitals-monitoring.ts: Use lookup objects for rating emojis/colors - pagespeed-insights.ts: Extract helper functions for delta formatting - badge-generator.tsx: Use color constants and helper functions - env.ts: Simplify complex nested conditional logic These changes reduce complexity and make the code more maintainable. However, treeshaking still needs to be disabled due to remaining nested ternaries throughout the codebase. The Rollup bug (issue #5747) is triggered by ANY nested ternary, so a complete refactor of all ternaries would be needed to re-enable treeshaking without upgrading Rollup. Impact: - Cleaner, more maintainable code - Partial progress toward fixing Rollup issue - Bundle size still exceeds 5MB limit due to disabled treeshaking * perf: implement lazy loading for insights sidebar components Implemented code-splitting optimizations: - Lazy load all insights sidebar sections (FAQ, Health, Recommendations, etc) - Dynamic import heavy embeddings/transformers library in FAQ service - Add loading skeletons for better UX during lazy loading - Move insights components out of main bundle Impact: - FAQ and embeddings now load only when needed (~820KB saved from initial load) - Improved initial page load performance - Better code organization with clear async boundaries Trade-offs: - Bundle still exceeds 5MB due to disabled treeshaking (Rollup bug workaround) - Treeshaking must remain disabled until Rollup issue #5747 is fixed - Performance Budget Check will continue to fail Next steps: - Consider downgrading Rollup to avoid the bug - Or systematically replace ALL nested ternaries across codebase - Continue identifying more components for lazy loading * fix: add Rollup treeshake workaround to Storybook config The same Rollup 4.45.0 bug that affects the main build also affects Storybook builds. Added treeshake: false to the Storybook viteFinal configuration to match the main build workaround. This fixes the 'Cannot add property 0, object is not extensible' error during Storybook builds in CI. Impact: - Storybook builds now complete successfully - Build and Deploy Storybook workflow should pass - Slightly larger Storybook bundle (acceptable for documentation) Note: This workaround can be removed once Rollup issue #5747 is fixed or all nested ternaries are refactored. * fix: make FAQ answers ultra-concise and fix text overflow - Reduce FAQ cache to 24 hours for better freshness - Make AI answers max 50 words (was 100, then 200) - Make static answers 60-70% more concise - Add cache version key (v3-ultra-concise) to bust old verbose cached answers - Fix text overflow with break-words CSS class - Ensure FAQs fit properly in sidebar window * fix: properly constrain FAQ width in sidebar to prevent overflow - Add overflow-hidden to parent container in insights-sidebar - Use line-clamp-2 for FAQ questions (shows 2 lines max) - Remove unnecessary break-words and overflow classes - Simplify text display with standard wrapping * fix: increase sidebar width to 420px for better FAQ readability - Increase insights sidebar from 320px (w-80) to 420px for proper content display - Remove line-clamp-2 restriction on FAQ questions - FAQ questions and answers now have enough space to display properly * fix: update FAQ design to match app design language - Remove blue border and use standard card hover effect - Remove blue Sparkles icons throughout - Simplify AI confidence display - Use consistent spacing (space-y-3) like other sections - Use standard p-4 padding like recommendations section - Simplify footer text for cleaner appearance * fix: FAQ now generates specific answers for each question - Remove broken generateFAQInsight that was hijacking health analysis - Add dedicated callOpenAIForFAQ method with FAQ-specific system prompt - System prompt emphasizes answering the specific question asked - Cache version v4-specific-answers to force regeneration - Each FAQ question now gets a unique, relevant answer instead of generic health advice * fix: add local fallback for repository summary when Edge Function fails - Add generateLocalSummary function for when Edge Function returns 500 - Generate basic summary from repository data and PR titles - Prevents error state when Edge Function has issues - Provides graceful degradation for summary feature * fix: improve Edge Function error handling and deploy fix - Add detailed error logging to repository-summary Edge Function - Check for missing environment variables before use - Continue without embeddings if generation fails (non-critical) - Add fallback summary generation in client when Edge Function fails - Provide detailed error information in response for debugging - Successfully deployed updated Edge Function to production * fix: resolve TypeScript build errors - Remove unused avgPerDay and avgTitleLength variables - Fix repositoryData reference in fallback summary generation - Fetch repository data when needed for fallback - Build now passes successfully * feat: humanize numbers in repository summaries - Add humanizeNumber function to format large numbers (27357 -> 27.4k) - Apply to both local fallback and Edge Function summaries - Update AI prompt to use humanized format in generated text - Numbers now display as 1.2k, 5.7M instead of full values - Better readability for repository metrics --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
1 parent b4e20a9 commit 8a3cd91

File tree

16 files changed

+1608
-89
lines changed

16 files changed

+1608
-89
lines changed

.storybook/main.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ const config: StorybookConfig = {
7373
async viteFinal(config) {
7474
// Merge custom configuration into the default config
7575
return mergeConfig(config, {
76+
// Workaround for Rollup 4.45.0 bug with nested conditional expressions
77+
// Same issue as main build - treeshaking fails on nested ternaries
78+
build: {
79+
rollupOptions: {
80+
treeshake: false,
81+
},
82+
},
7683
resolve: {
7784
alias: {
7885
// Mock Supabase for Storybook to avoid needing real credentials
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# FAQ LLM Integration
2+
3+
## Overview
4+
5+
Enhanced the FAQ system with AI-powered dynamic answers using OpenAI and semantic embeddings for better user experience and improved SEO.
6+
7+
## Features
8+
9+
### 🤖 AI-Powered Answers
10+
- Dynamic FAQ generation using OpenAI GPT-4o-mini
11+
- Context-aware responses based on repository data
12+
- Confidence scores and source citations
13+
- Graceful fallback to static answers when AI unavailable
14+
15+
### 🔍 Semantic Search
16+
- MiniLM embeddings for question similarity matching
17+
- Semantic question understanding for better FAQ relevance
18+
- Embeddings cached for performance
19+
20+
### 📈 SEO Enhancements
21+
- FAQ URLs added to sitemap (`/owner/repo/faq`)
22+
- Schema.org structured data for FAQ pages
23+
- Breadcrumb navigation support
24+
- Dynamic priority calculation based on repository activity
25+
26+
## Technical Implementation
27+
28+
### New Files
29+
- `src/lib/llm/faq-service.ts` - Main FAQ service with LLM integration
30+
- `src/lib/sitemap/faq-sitemap-generator.ts` - SEO sitemap utilities
31+
- Enhanced `src/components/insights/sections/project-faq.tsx`
32+
33+
### Key Features
34+
```typescript
35+
// AI-powered FAQ generation
36+
const faqs = await faqService.generateFAQAnswers(owner, repo, timeRange, data);
37+
38+
// Semantic question matching
39+
const similar = await faqService.findSimilarQuestions(userQuestion, faqs);
40+
41+
// SEO sitemap integration
42+
const sitemapEntries = await generateFAQSitemapEntries();
43+
```
44+
45+
### Visual Indicators
46+
- ✨ Sparkles icon for AI-generated answers
47+
- Confidence percentage display
48+
- Source citations for transparency
49+
- Enhanced footer with AI status
50+
51+
## Benefits
52+
53+
1. **Better LLM Citation** - Dynamic, contextual answers improve AI search visibility
54+
2. **Enhanced SEO** - Structured FAQ pages with proper schema markup
55+
3. **Improved UX** - More accurate, detailed answers about repositories
56+
4. **Performance** - Cached responses and graceful fallbacks
57+
5. **Transparency** - Clear indicators for AI vs static content
58+
59+
## Configuration
60+
61+
The system automatically detects OpenAI availability and falls back gracefully:
62+
63+
```typescript
64+
const useAI = faqService.isAvailable(); // Checks for VITE_OPENAI_API_KEY
65+
```
66+
67+
## Sitemap Integration
68+
69+
FAQ pages are now included in the main sitemap:
70+
71+
```xml
72+
<url>
73+
<loc>https://contributor.info/microsoft/vscode/faq</loc>
74+
<changefreq>weekly</changefreq>
75+
<priority>0.7</priority>
76+
</url>
77+
```
78+
79+
This enhancement significantly improves both user experience and search engine discoverability of repository insights.

public/sitemap-news.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
33
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
44

5+
<url>
6+
<loc>https://contributor.info/Ad-Astra-Innovia/frontend</loc>
7+
<news:news>
8+
<news:publication>
9+
<news:name>Contributor.info</news:name>
10+
<news:language>en</news:language>
11+
</news:publication>
12+
<news:publication_date>2025-08-07</news:publication_date>
13+
<news:title>Ad-Astra-Innovia/frontend - Contributor Updates</news:title>
14+
</news:news>
15+
</url>
516
<url>
617
<loc>https://contributor.info/pytorch/pytorch</loc>
718
<news:news>

public/sitemap.xml

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@
283283
<priority>0.7</priority>
284284
<lastmod>2025-08-04</lastmod>
285285
</url>
286+
<url>
287+
<loc>https://contributor.info/pingcap/tidb</loc>
288+
<changefreq>daily</changefreq>
289+
<priority>0.7</priority>
290+
<lastmod>2025-06-29</lastmod>
291+
</url>
286292
<url>
287293
<loc>https://contributor.info/prometheus/prometheus</loc>
288294
<changefreq>daily</changefreq>
@@ -385,35 +391,17 @@
385391
<priority>0.7</priority>
386392
<lastmod>2025-06-29</lastmod>
387393
</url>
388-
<url>
389-
<loc>https://contributor.info/pytorch/pytorch</loc>
390-
<changefreq>daily</changefreq>
391-
<priority>0.9</priority>
392-
<lastmod>2025-08-07</lastmod>
393-
</url>
394-
<url>
395-
<loc>https://contributor.info/pytorch/pytorch/health</loc>
396-
<changefreq>daily</changefreq>
397-
<priority>0.8</priority>
398-
<lastmod>2025-08-07</lastmod>
399-
</url>
400-
<url>
401-
<loc>https://contributor.info/pytorch/pytorch/distribution</loc>
402-
<changefreq>daily</changefreq>
403-
<priority>0.8</priority>
404-
<lastmod>2025-08-07</lastmod>
405-
</url>
406394
<url>
407395
<loc>https://contributor.info/Supabase/supabase</loc>
408396
<changefreq>daily</changefreq>
409397
<priority>0.7</priority>
410398
<lastmod>2025-07-03</lastmod>
411399
</url>
412400
<url>
413-
<loc>https://contributor.info/lodash/lodash</loc>
401+
<loc>https://contributor.info/BlueMatthew/WechatExporter</loc>
414402
<changefreq>daily</changefreq>
415403
<priority>0.7</priority>
416-
<lastmod>2025-06-29</lastmod>
404+
<lastmod>2025-07-03</lastmod>
417405
</url>
418406
<url>
419407
<loc>https://contributor.info/facebook/docusaurus</loc>
@@ -506,10 +494,34 @@
506494
<lastmod>2025-08-04</lastmod>
507495
</url>
508496
<url>
509-
<loc>https://contributor.info/BlueMatthew/WechatExporter</loc>
497+
<loc>https://contributor.info/Ad-Astra-Innovia/frontend</loc>
510498
<changefreq>daily</changefreq>
511499
<priority>0.7</priority>
512-
<lastmod>2025-07-03</lastmod>
500+
<lastmod>2025-08-07</lastmod>
501+
</url>
502+
<url>
503+
<loc>https://contributor.info/pytorch/pytorch</loc>
504+
<changefreq>daily</changefreq>
505+
<priority>0.9</priority>
506+
<lastmod>2025-08-07</lastmod>
507+
</url>
508+
<url>
509+
<loc>https://contributor.info/pytorch/pytorch/health</loc>
510+
<changefreq>daily</changefreq>
511+
<priority>0.8</priority>
512+
<lastmod>2025-08-07</lastmod>
513+
</url>
514+
<url>
515+
<loc>https://contributor.info/pytorch/pytorch/distribution</loc>
516+
<changefreq>daily</changefreq>
517+
<priority>0.8</priority>
518+
<lastmod>2025-08-07</lastmod>
519+
</url>
520+
<url>
521+
<loc>https://contributor.info/lodash/lodash</loc>
522+
<changefreq>daily</changefreq>
523+
<priority>0.7</priority>
524+
<lastmod>2025-06-29</lastmod>
513525
</url>
514526
<url>
515527
<loc>https://contributor.info/duckdb/duckdb</loc>
@@ -589,11 +601,5 @@
589601
<priority>0.7</priority>
590602
<lastmod>2025-06-29</lastmod>
591603
</url>
592-
<url>
593-
<loc>https://contributor.info/pingcap/tidb</loc>
594-
<changefreq>daily</changefreq>
595-
<priority>0.7</priority>
596-
<lastmod>2025-06-29</lastmod>
597-
</url>
598604

599605
</urlset>

src/components/embeddable-widgets/badge-generator.tsx

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,34 +39,67 @@ const BADGE_STYLES = {
3939
},
4040
};
4141

42+
// Color schemes for badge metrics
43+
const COLORS = {
44+
contributors: "#007ec6",
45+
pullRequests: "#28a745",
46+
mergeRate: {
47+
high: "#28a745", // > 80%
48+
medium: "#ffc107", // > 60%
49+
low: "#dc3545" // <= 60%
50+
},
51+
lotteryFactor: {
52+
excellent: "#28a745", // > 3
53+
good: "#ffc107", // > 2
54+
poor: "#dc3545", // <= 2
55+
unavailable: "#6c757d" // N/A
56+
},
57+
activity: {
58+
active: "#28a745",
59+
low: "#ffc107"
60+
}
61+
};
62+
63+
// Helper functions to determine colors
64+
function getMergeRateColor(rate: number): string {
65+
if (rate > 80) return COLORS.mergeRate.high;
66+
if (rate > 60) return COLORS.mergeRate.medium;
67+
return COLORS.mergeRate.low;
68+
}
69+
70+
function getLotteryFactorColor(factor: number | undefined): string {
71+
if (!factor) return COLORS.lotteryFactor.unavailable;
72+
if (factor > 3) return COLORS.lotteryFactor.excellent;
73+
if (factor > 2) return COLORS.lotteryFactor.good;
74+
return COLORS.lotteryFactor.poor;
75+
}
76+
4277
// Predefined badge types with time context
4378
const BADGE_PRESETS = {
4479
contributors: (data: WidgetData) => ({
4580
label: "contributors (30d)",
4681
message: data.stats.totalContributors.toString(),
47-
color: "#007ec6",
82+
color: COLORS.contributors,
4883
}),
4984
"pull-requests": (data: WidgetData) => ({
5085
label: "PRs (30d)",
5186
message: data.stats.totalPRs.toString(),
52-
color: "#28a745",
87+
color: COLORS.pullRequests,
5388
}),
5489
"merge-rate": (data: WidgetData) => ({
5590
label: "merge rate (30d)",
5691
message: `${data.stats.mergeRate.toFixed(1)}%`,
57-
color: data.stats.mergeRate > 80 ? "#28a745" : data.stats.mergeRate > 60 ? "#ffc107" : "#dc3545",
92+
color: getMergeRateColor(data.stats.mergeRate),
5893
}),
5994
"lottery-factor": (data: WidgetData) => ({
6095
label: "lottery factor (30d)",
6196
message: data.stats.lotteryFactor?.toFixed(1) || "N/A",
62-
color: !data.stats.lotteryFactor ? "#6c757d" :
63-
data.stats.lotteryFactor > 3 ? "#28a745" :
64-
data.stats.lotteryFactor > 2 ? "#ffc107" : "#dc3545",
97+
color: getLotteryFactorColor(data.stats.lotteryFactor),
6598
}),
6699
activity: (data: WidgetData) => ({
67100
label: "activity (7d)",
68101
message: data.activity.recentActivity ? "active" : "low",
69-
color: data.activity.recentActivity ? "#28a745" : "#ffc107",
102+
color: data.activity.recentActivity ? COLORS.activity.active : COLORS.activity.low,
70103
}),
71104
};
72105

0 commit comments

Comments
 (0)